【Unity】RequireComponentで安全にコンポーネントを操作する
スクリプトからコンポーネントを操作するとき、よくやってしまいがちなのが、コンポーネントの有無を確認せずに触ってエラーを出してしまうこと。
Transformならどのゲームオブジェクトも確実に持ってるから安心ですが、RigidbodyやColliderなんかはうっかりGetComponentしてしまうこともあります。
「俺はそんなことしないぜ!」という上級者でも、プロジェクト後半の睡眠時間が足りなくなってきて、夢の中でもコーディングをするような時期になれば注意力が散漫になることも。
コンポーネントのチェックを機械に任せておけばヒューマンエラーを回避できるし、何より今回の主役である『RequireComponent』は1行追加するだけで済むので、初心者でも上級者でも使うと便利です。
環境
macOS 10.13 High Sierra
Unity2018.1.0f2
RequireComponentとは
RequireComponentはスクリプトの中で使えるAttribute(属性)のひとつです。
直訳すれば、「要求する」「コンポーネントを」なので、このAttributeが付いているスクリプトがゲームオブジェクトにアタッチされた時、指定されたコンポーネントがアタッチされてなければ、そのコンポーネントを自動的にアタッチしてくれます。
なんと便利な……!
スクリプトの中からいじることの多いRigidbodyを使うときには、このAttributeがあると安心です。アタッチしてないのにGetComponentして何度Unityに怒られたことか……。
使い方は簡単で、Projectウィンドウなどから作成したスクリプトのクラス名の前に、
[RequireComponent(typeof(コンポーネント名))]
を追加するだけ。使用例は以下のようになります。
このスクリプトを任意のゲームオブジェクトにアタッチすると、Rigidbodyコンポーネントを自動的にアタッチしてくれます。
動きの確認
念のため、[RequireComponent]を使わないときの動きも確認してみます。
上のスクリプトで[RequireComponent]の行をコメントアウトしてゲームを実行するとこんな感じ。
Update()でもRigidbodyに触ろうとしているので、延々とMissingComponentExceptionが出続けます。
このエラー自体はすぐ解決できるものの、忙しいときにこれが出ると「うわっこんな初歩的なミスを……」と、ちょっと精神的なダメージが入ります。
これが[RequireComponent]を使うと……。
スクリプトをアタッチしたときに[RequireComponent]で指定したコンポーネントを一緒にアタッチしてくれます。
これでアタッチし忘れもなくなりますね。安心。
なお、[RequireComponent]で指定したコンポーネントを歯車アイコンのメニューから『Remove Component』しようとすると、「削除できないよー」と怒られます。
もしRigidbodyをRemoveしたい場合は先に[RequireComponent]をRemoveしておかないといけないので注意。
スクリプトもRequireComponentできる
RequireComponentと名前が付いていますが、自分で作成したMonoBehaviourを継承したスクリプトも対象にできます。
試しに、『RequireCharacterComponent』と『RequiredCharacterStatus』という2つのスクリプトを作成し、このうち『RequireCharacterComponent』の中に[RequireComponent]を記述してみます。
こちらが要求する方のスクリプト。
こっちは要求される側。
Inspectorウィンドウの[Add Component]ボタンから、要求する側の『RequireCharacterComponent』をアタッチしてみます。
アタッチすると、以下のように要求される側の『RequiredCharacterStatus』もアタッチされました。
細かいですが、要求された側の方が上にきます。先にアタッチされたコンポーネントが上にくるので、そりゃそうだって感じだけど、順番を気にする人は注意。
RequireComponentがRequireComponentしてたらどうなるの?
2重Require、孫請けのような形で[RequireComponent]されていたらどうなるんでしょ?
上で挙げた要求される側である『RequiredCharacterStatus』からさらに要求してみます。こちらにも[RequireComponent]をつけます。
要求されるスクリプトはこちら。
これらのスクリプトを作った後、Inspectorウィンドウの[Add Component]ボタンから、大元の『RequireCharacterComponent』をアタッチしてみます。
二重にRequireComponentできました。ちゃんと動いているようですね。
二重に依存関係があるので、スクリプトを外すときはちょっとめんどくさいかもしれません。
MonoBehaviourを継承してないスクリプトは?
MonoBehaviourを継承していない場合はどうなるんでしょうね。
多分ダメだとは思いつつも、やる前から諦めるのは好きじゃないので確かめてみます。
以下のように、MonoBehaviourを継承していない自作スクリプトを用意します。
上で作った『RequiredCharacterStatus』の[RequireComponent]でこのスクリプトを指定して、Inspectorウィンドウの[Add Component]ボタンから追加しようとすると……。
Invalid operation. と怒られてしまいました。MonoBehaviourを継承していないスクリプトはUnity側から制御できないため、コンポーネントとしてアタッチすることができません。
なのに[RequireComponent]で要求しているから怒られてしまうんです。
なお、直接『RequireNoMono』をInspectorウィンドウの[Add Component]ボタンから追加しようとしても、一覧に表示されないのでアタッチすることはできません。
まとめ
うっかりアタッチしてないコンポーネントを操作しないように、[RequireComponent]をつけておくとベネ。
[RequireComponent]されているコンポーネントが[RequireComponent]していてもうまく働くので、他のスクリプトを参照することが多ければ設定しておくといいかも。
ゲーム開発の攻略チャートを作りました!
-
前の記事
Unityでゲームを作ってるので乱数について勉強を始めてみたよ 2018.06.28
-
次の記事
【Unity】同じコンポーネントが複数アタッチされるのを防ぐ方法 2018.06.30
コメントを書く