プロジェクト構成
Udonite がどのスクリプトをコンパイルするのか、アセンブリ定義との関係、そして Udon に載せないコードの外しかた。
プログラムになるスクリプト
次をすべて満たすクラスが Udon プログラムになります。
MonoBehaviourを継承している(直接でもUdoniteBehaviour経由でも構いません)abstractでなく、ジェネリックでなく、他の型の入れ子でもない- そのスクリプトが
Assets/の下のどこかにある
条件を満たすクラスはすべてルートで、ルートごとに専用の Udon プログラムが同じ GameObject 上に付きます。登録は要りませんし、特別なフォルダもありません。Assets/Scripts/Doors/Door.cs にあるスクリプトも Assets/Door.cs にあるスクリプトも、同じように見つかります。
条件を満たさないクラスはエラーではありません。抽象基底クラス、ジェネリックのヘルパー、ただのデータクラス、静的ユーティリティは、ビヘイビアが使う普通の C# です。それ自体がプログラムにならないというだけです。
アセンブリ定義
アセンブリ定義を使っても使わなくても、Udonite の動きは変わりません。
アセンブリ定義がどこにもなければ、スクリプトは Unity 既定の Assembly-CSharp に入り、Udonite はそれをコンパイルします。.asmdef を置けばスクリプトはそのアセンブリに入り、Udonite はそちらをコンパイルします。どちらかが本筋で、もう一方が回避策ということはありません。条件は、そのアセンブリが Assets/ の下にソースを持っていることだけです。
これは見た目より重要です。アセンブリは、コードから何が見えるかを二つ決めるからです。
参照。 ビヘイビアは、自分のアセンブリが参照している型をすべて使えます。ワールドを World.Runtime と World.Interactables に分け、後者が前者を参照しているなら、World.Interactables のビヘイビアは World.Runtime の型を普通に使えます。
定義シンボル。 アセンブリがコンパイルに使うスクリプト定義シンボルは、そのまま Udonite のコンパイルにも使われます。#if UNITY_EDITOR も自作の定義も、プロジェクトの他の場所とまったく同じように働きます。
エディタ専用アセンブリは対象外です。プラットフォーム一覧が Editor になっている .asmdef に入っているのはツールであってワールドのロジックではないため、その中身は Udon にコンパイルされません。
複数のファイルに分ける
ビヘイビアは 1 ファイルに収まっている必要はありません。同じアセンブリの別ファイルにあるヘルパークラス、enum、インターフェイス、基底クラスはそのまま使えるので、ワールドは必要なだけファイルを分けて構いません。
境界はファイルではなくアセンブリです。ヘルパーが別のアセンブリにあるなら、ビヘイビアのアセンブリがそれを参照する必要があります。Unity の他の場所と同じです。
パッケージ内のスクリプト
Packages/ の下のスクリプトは Udon にコンパイルされません。これは抜けではなく意図したものです。取り込んだパッケージには、Udon の存在を知らずに書かれた MonoBehaviour クラスが何百と入っていることがあります。それをコンパイルすれば、自分が書いたわけでも直せるわけでもないコードについての拒否でコンソールが埋まってしまいます。
例外は Udonite 自身が同梱するコンポーネント(NetworkTransform など)です。これらはワールドで動くために作られているので、パッケージの中にあってもコンパイルされます。
パッケージのビヘイビアをワールドで使いたい場合は、Assets/ の下に自分のビヘイビアを書き、そこからパッケージのコンポーネントを動かすのが確実です。
UdonSharp との併用
UdonSharpBehaviour を継承したクラスには手を出さず、UdonSharp のコンパイルに任せます。Udonite が引き受けるのは MonoBehaviour のクラスだけなので、同じスクリプトを取り合うことなく両方のコンパイラを一つのプロジェクトで動かせます。
Udon に載せないコード
Assets/ の下にあってもプログラムにすべきでないコードがあります。エディタ用のツール、デスクトップでしか動かない外部コンポーネント、移植の途中のスクリプトなどです。除外すれば Udonite はそれをコンパイルしなくなります。
いちばん早いのはチェックボックスです。Udonite → Open Window を開き、Overview タブのツリーでそのスクリプトかフォルダのチェックを外します。フォルダを外すとその下すべてが除外されます。除外済みのものを再びチェックすると、無効な行を残すのではなく除外そのものを取り除きます。除外されたスクリプトやフォルダは消えるのではなく、ツリーの中でグレーアウトして残ります。開いているシーンにまだ生きたインスタンスがあれば警告が出ます。そのインスタンスはもうすぐ Udon プログラムを持てなくなるからです。同じウィンドウの Diagnostics タブと Settings タブは はじめかた で扱っています。
どのチェックボックスも、裏では同じファイルを読み書きしています。手で編集してもチェックボックスと同じように効きます。除外は ProjectSettings/UdoniteExclusions.txt に 1 行 1 件で書きます。順序は問いません。1 行はアセンブリ名か、アセットの GUID のどちらかです。
# Udonite の除外設定。1 行 1 件で、順序は問いません。
asm:SomeVendor.Runtime # ワールドでは決して動かないパッケージ
guid:3c6e5249679282e459858775b10f38d0 # Assets/Editor/LevelBuilder.cs
asm: はアセンブリ名を取ります。サードパーティのパッケージをまるごと外すときは、たいていこれです。Unity はそうしたパッケージを一つのアセンブリにまとめてコンパイルするからです。
guid: は Unity の 16 進 32 桁を取ります。アセットの隣にある .meta ファイルに書かれています。スクリプト 1 つでもフォルダでも指定でき、フォルダを指定するとその下がすべて除外されます。
GUID なのには理由があります。パスは誰かがファイルを動かした瞬間に一致しなくなり、しかも黙って一致しなくなります。この種のルールにとっては最悪の壊れかたです。GUID なら移動しても生き残ります。末尾の # の注記を残しておく価値があるのも同じ理由です。GUID がいつか解決できなくなったとき、その行が何だったかを示す記録はその注記しかありません。アセットが削除されると、その行はファイルを次に何かが読んだ瞬間 — ウィンドウを開いたとき、あるいは次のコンパイルのとき — に自動で取り除かれ、何も指さない GUID として残ることはありません。
フォルダの GUID は手では見つけにくいものです。Unity は自分の UI のどこにもそれを表示しません。Overview からフォルダを除外すれば GUID を打ち込む必要は一切なく、それがファイルにフォルダの行を入れる確実な方法です。
再登録はありません。フォルダの除外を、その中の 1 ファイルだけ後から含めることで狭めることはできません。そのファイル自身の GUID をフォルダの外から除外するか、除外フォルダの外に移動してください。
エントリは削除せずに止めることもできます。!asm:Cinemachine のように先頭に ! を付けると、行(とその注記)はファイルに残りますが、その間は何も除外しません — Overview ではそのスクリプトは含まれているものとして表示され、行がないのと同じに見えます。! を書くのは手作業で、Overview が代わりにやってくれることはありません。ただしその後で同じスクリプトを Overview から除外すると、複製を書くのではなくその行を再び有効にします。手で足した ! を元に戻すのに GUID を打ち直す必要はないということです。その後もう一度含めると、今度は無効化するのではなく行そのものを取り除きます。
ここではよく起きることが二つあり、それぞれ専用のコードがあります。読み取れない行は UDN0007 として、期待する書式とともに報告されます。除外したコードをまだ呼んでいるビヘイビアは UDN0008 として報告されます。ワールドではその呼び先が存在しないからです。
作業中に Udonite が伝えること
コンパイルより前に伝わるものが二つあります。どちらも、あなたがすでに見ている場所で読まれるためのものです。
エディタの波線。 Udonite は Roslyn アナライザを同梱しているので、いくつかの拒否はコンパイル後ではなく入力中に現れます。書き換え可能な static フィールド、catch 節、そして Udon が決して呼ばない Unity イベントです。コンパイラと同じ UDN コードを持つので、検索して出てくる答えは二つではなく一つです。
これらは警告で、すべてを拾うわけではありません。エディタがきれいでもプログラムがコンパイルできるとは限りません。それを教えてくれるのはコンパイルだけです。
空のビヘイビア参照。 別のビヘイビアを指す public フィールドに何も配線されていないとき、コンソールがビヘイビア名とフィールド名を挙げて知らせます。
Udonite: Switch on 'Door Controls' has an empty behaviour reference: 'target'.
Calling through one halts the behaviour for the rest of the session with nothing
logged, so wire it in the inspector, or make the field private if the script
assigns it itself.
報告されるのは他のビヘイビアへの参照だけです。空の GameObject や AudioSource のフィールドは普通のことで、意図的なことも多くあります。ビヘイビアへの参照は呼ぶために存在していて、null のまま呼ぶことが、何の痕跡も残さない失敗そのものです。
プログラムができる場所
各プログラムは対応するビヘイビアと同じ GameObject に付き、アップロードでワールドに乗るのはそれです。C# は次の編集のためにプロジェクトに残ります。普段以上にコミットすべきものはありません。プログラムは Unity が再コンパイルするたび、そしてシーンを保存するたびに作り直されます。