読者です 読者をやめる 読者になる 読者になる

測八空

趣味レベルのUnityメモ

「Script」フィールドについて詳しく調べてみたらUnityの深淵に触れた

記事を見て頂きありがとうございます。このブログは、個人的に詰まった時の解決策をてきとーに書きなぐるだけの予定でしたが、お仕事でUnityを使っている方からTwitterで直接反応を貰って、舞い上がってしまいました。超嬉しいです。

舞い上がりついでに、前回の記事は余りにも内容が薄すぎたので、もう少し詳しく「Script」フィールドについて調べてみました。

タイトルに深淵がどうと書いてありますが、恐らくUnity上級者の方にとっては当たり前であろう事が書いてあります。駄文ともどもご容赦下さい。

 

前回のコード

前回貼ったコードをコメントで軽く説明すると、このようになります。

重要なのは5行目。MonoScript.FromMonoBehaviour()です。ここでは、target(MonoBehaviourを継承したクラス)を元に、MonoScriptというオブジェクトを取得しているようです。

こんな事をしなくとも、ソースコードのファイルを選択するだけなら、AssetDatabase辺りにパス文字列を返すメソッドを作るだけで十分な気がします。何故、わざわざこのようなオブジェクトを取得する仕様になっているのでしょうか?

MonoScriptとは

MonoScriptは、「スクリプトのAssetを扱うためのクラス」のようです。なぜそれが必要なのか、もう少し調べてみましょう。

型階層を覗いてみると、

 

Object

┗TextAsset

 ┗MonoScript

となっています。

 

おや、お馴染みのObjectクラスが見えますね。

Objectクラスは、Unity上に存在するすべてのオブジェクトの基底クラスという話なので、MonoScriptの根っこにあるのも、まあ理解できます。

 

 

ん?Objectが……すべての……?

 

 

 

Unity上に転がっている、あらゆるモノはObjectField()にセット出来る

 

つまり何が言いたいかというと、スクリプトどころかSceneやフォルダ、テキスト.txtまで、HierarchyとかProjectとかに表示されている物であれば、なんでもかんでもObjectField()にセットすることが出来ます。

(EditorOnlyなものや、DefaultAsset(特にインターフェースが用意されてないもの)もあります)

 

確かめる方法は簡単です。こんな感じのユーティリティを作って……。

 

このように(gifアニメ)

f:id:Sokuhatiku:20170207170914g:plain

(TestSceneという項目が選択できていませんが、Assetsタブにある同名のSceneファイルが選択できます)

 

MeshやPrefabどころかPDFやショートカットといった、何に使うのかよく分からないものまでObjectField()にぶち込む事が出来ます。また、ぶち込まれたObjectをAssetDatabaseに問い合わせることで、パスを始めとしたAssetに関する情報の取得も可能です。

 

ここで分かったことをまとめると、

Unityに認識されている(ProjectビューもしくはHierarchyビューに映っている)オブジェクト / アセットは、ビルトインのもの / インポートしたもの、最終的なビルドに含まれるもの / 含まれないものに関わらず、その全てがObjectを継承している、またはObjectを継承したクラスによって管理されている。

 

それで何が出来るの?

例えば、さっき書いたチェッカーの出力を見てみると、EditorOnlyなスクリプトにも、MonoScriptオブジェクトが対応している事が分かります。つまり……、

「Editor」フィールド

f:id:Sokuhatiku:20170207162817p:plain

Editorフィールドをダブルクリックすると、Editorスクリプトの方のソースコードを開けます。Scriptビューが消えて困っている時。それはインスペクタをカスタマイズしている、つまりCustomEditorが存在している訳で、それを開けない事にもやもやしていたのですが、やっと実現できました。満足です。

実際に使用する際は拡張メソッドなどで1行で呼び出せるようにしておくと、便利かと思います。

 

まだまだ応用の幅は広い

全てのオブジェクトがObjectを継承しているという事は一見当たり前に感じますが、私はGameObjectやComponentなど、ゲームに関係あるものだけだと、無意識の内に限定して考えていました。しかし実際には、EditorOnlyなオブジェクトもすべてObjectを継承しているのです。特に、スクリプトファイルがObjectとして扱えるなんて、思いもしませんでした。

また、上に挙げたものは、Objectが持つ力のほんの一例に過ぎません。このObjectベースの仕様を理解していると、今後のEditor拡張の自由度がぐっと上がると思います。

Projectビューは、単なる簡易ファイラーではありません。Hierarchyビューと同じような、実体(インスタンス)を持つオブジェクトのツリーです。Objectクラスの子であれば何でも配置できる、OSのファイルシステムと連動するHierarchyなのです。

(Assetフォルダに配置したファイルがProjectビューに映るのは、ファイルの追加を検知したUnityが、配置されたファイルに対応したクラスのインスタンスを自動で生成するからです。そのインスタンスが保持するデータは、.metaファイルに記述されています。)

 

 

あとがき

今まで何度Unityはすごいよ!強力だよ!と言われても、確かにすごいけど正直使いにくい、なんでこんな設計なんだという感想ばかりだったのですが、今回の調査でその凄さ、ポテンシャルの一端を垣間見た気がします。マインスイーパで2、30マスくらいが一気に開いた気分です。

あと、Editor拡張の入門とか書いてる人は、最初のページに「Unityの世界のすべてはObjectで出来ている……。」って書くとかっこいいと思います。

UnityEngine.Object (←全てを構成する!!)

┣GameObject (←Unity入門時にこれが基本単位だと教わる)

┣Component

┗(その他の色々なアセット)