【Unity】RequireComponentで安全にコンポーネントを操作する

【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]を使うと……。

スクリプトをアタッチすると……
スクリプトをアタッチすると……

 

Rigidbodyも一緒にアタッチしてくれる
Rigidbodyも一緒にアタッチしてくれる

 

スクリプトをアタッチしたときに[RequireComponent]で指定したコンポーネントを一緒にアタッチしてくれます。

これでアタッチし忘れもなくなりますね。安心。

なお、[RequireComponent]で指定したコンポーネントを歯車アイコンのメニューから『Remove Component』しようとすると、「削除できないよー」と怒られます。

Can't remove component
Can’t remove component

 

もしRigidbodyをRemoveしたい場合は先に[RequireComponent]をRemoveしておかないといけないので注意。

スクリプトもRequireComponentできる

RequireComponentと名前が付いていますが、自分で作成したMonoBehaviourを継承したスクリプトも対象にできます。

試しに、『RequireCharacterComponent』と『RequiredCharacterStatus』という2つのスクリプトを作成し、このうち『RequireCharacterComponent』の中に[RequireComponent]を記述してみます。

こちらが要求する方のスクリプト。

こっちは要求される側。

Inspectorウィンドウの[Add Component]ボタンから、要求する側の『RequireCharacterComponent』をアタッチしてみます。

自作スクリプトでRequireComponent
自作スクリプトでRequireComponent

 

アタッチすると、以下のように要求される側の『RequiredCharacterStatus』もアタッチされました。

無事アタッチされた
無事アタッチされた

 

細かいですが、要求された側の方が上にきます。先にアタッチされたコンポーネントが上にくるので、そりゃそうだって感じだけど、順番を気にする人は注意。

 

RequireComponentがRequireComponentしてたらどうなるの?

2重Require、孫請けのような形で[RequireComponent]されていたらどうなるんでしょ?

上で挙げた要求される側である『RequiredCharacterStatus』からさらに要求してみます。こちらにも[RequireComponent]をつけます。

要求されるスクリプトはこちら。

これらのスクリプトを作った後、Inspectorウィンドウの[Add Component]ボタンから、大元の『RequireCharacterComponent』をアタッチしてみます。

大元のスクリプトをアタッチ
大元のスクリプトをアタッチ

 

二重にRequireComponentしてもアタッチされる
二重にRequireComponentしてもアタッチされる

 

二重にRequireComponentできました。ちゃんと動いているようですね。

二重に依存関係があるので、スクリプトを外すときはちょっとめんどくさいかもしれません。

MonoBehaviourを継承してないスクリプトは?

MonoBehaviourを継承していない場合はどうなるんでしょうね。

多分ダメだとは思いつつも、やる前から諦めるのは好きじゃないので確かめてみます。

以下のように、MonoBehaviourを継承していない自作スクリプトを用意します。

上で作った『RequiredCharacterStatus』の[RequireComponent]でこのスクリプトを指定して、Inspectorウィンドウの[Add Component]ボタンから追加しようとすると……。

はい、すみません
はい、すみません

 

Invalid operation. と怒られてしまいました。MonoBehaviourを継承していないスクリプトはUnity側から制御できないため、コンポーネントとしてアタッチすることができません。

なのに[RequireComponent]で要求しているから怒られてしまうんです。

なお、直接『RequireNoMono』をInspectorウィンドウの[Add Component]ボタンから追加しようとしても、一覧に表示されないのでアタッチすることはできません。

まとめ

うっかりアタッチしてないコンポーネントを操作しないように、[RequireComponent]をつけておくとベネ。

[RequireComponent]されているコンポーネントが[RequireComponent]していてもうまく働くので、他のスクリプトを参照することが多ければ設定しておくといいかも。

アセット作ってます!

CTA-IMAGE

Unityでの開発に役立つアセットを作っています。

3DダンジョンRPGを開発するスピードを200%加速するAssetや、ファンタジーRPGのダンジョンを彩るパーツを取り揃えています。

特に3DダンジョンRPGのゲームを1から作るのは結構時間がかかります。ダンジョン部分の作成はこうしたアセットを使って、開発をブーストさせてみませんか?