【Unity】同じコンポーネントが複数アタッチされるのを防ぐ方法
今回もAttribute祭り。
ゲームオブジェクトにはコンポーネントをアタッチすることができますが、コンポーネントの中には「複数アタッチされると困るなー」というものもあります。
自分でスクリプトを作った時にいくつもインスタンスがあると困るケースなど、複数のコンポーネントをアタッチできないようにしたい時に便利なのが、[DisallowMultipleComponent]のAttributeです。
これを付けておくと、そのスクリプトは1つのゲームオブジェクトに複数アタッチすることができなくなります。
環境
macOS 10.13 High Sierra
Unity2018.1.0f2
DisallowMultipleComponentとは
DisallowMultipleComponentはスクリプトに記述するAttribute(属性)のひとつで、同じゲームオブジェクトに、このAttributeがついたスクリプトを複数アタッチできないようにします。
直訳すると、「許可しない」「複数の」「コンポーネント」となります。そのまんまですね。
例えばManager系のクラスだと、複数のコンポーネントが動いているとめっちゃ都合が悪いしバグの元です。なので、機械的にアタッチできないようにしておけば安心です。
Unityのスクリプトリファレンスの『DisallowMultipleComponent』では説明文だけでサンプルコードが無いため、ここでサンプルコードを紹介。
複数アタッチしてみる
まずは[DisallowMultipleComponent]を記述しないで、以下のスクリプトをゲームオブジェクトに複数アタッチします。
5つアタッチしてみました。この状態でゲームを実行してみると……。
今回のケースだとコンソールへの出力だけで済んでいますが、これがもしManager系のクラスで、シーンのロードなんかしていた日には、5つもシーンが読み込まれることに……。
そんな事故は未然に防いでおかねばならないので、[DisallowMultipleComponent]を記述しておきましょう。
記述する場所はクラス名の前です。
このスクリプトをInspectorウィンドウから追加でアタッチしてみます。
ちゃんとダイアログで『Invalid Operation.』と警告してくれます。Managerが二重にシーンを読み込むなんて悲劇はなかったんや……(1敗)
なお、すでに複数アタッチされている状態だと、スクリプトに[DisallowMultipleComponent]を書いても複数アタッチされたままなので注意。あくまでスクリプトに書いた後、コンポーネントをアタッチする時に有効なようです。
Copy Componentでも防ぐ
コンポーネントの右上にある歯車アイコンの中に、[Copy Component]の項目があります。
これを使ってコンポーネントのコピペをしても防いでくれるかな?
コンポーネントのコピペではダイアログが出ず、コンソールにエラーが出力されました。結果的に複数のアタッチはできていないので問題なさそう。
スクリプトからAddComponent
Inspectorウィンドウからだと、複数コンポーネントのアタッチはできませんでした。念のためスクリプトからもできないことを確認します。
今回使っている『MultipleComponentTest』のスクリプトを以下のように編集します。もし複数アタッチが可能なら、追加されるたびにStart()が呼び出されて無限にコンポーネントが増えていく恐ろしい仕様です。
Ifの世界線だとこうなります。
[DisallowMultipleComponent]が付いていると、どうなるかなー。
ちゃんと複数アタッチを防いでくれました。コンポーネントのコピペのケースと警告の種類が違うのは……何でしょうね?
おまけ
RigidbodyやMesh Filterなどは複数アタッチできないのですが、この時のメッセージが[DisallowMultipleComponent]のケースと違っていました。
複数アタッチさせないという目的はどちらも達成しているので気にするほどのことでもないのかも。
まとめ
同じスクリプトやコンポーネントを同じゲームオブジェクトにアタッチさせたくない時には、[DisallowMultipleComponent]を使っておくと安心です。
ただ、同一のゲームオブジェクトでしか防いでくれないので、複数のゲームオブジェクトに跨って防ぐことはできません。
シーン内で絶対に1インスタンスしか作りたくない! という時には、自力でシングルトンになるようにした方が良さげかも。
ゲーム開発の攻略チャートを作りました!
-
前の記事
【Unity】RequireComponentで安全にコンポーネントを操作する 2018.06.30
-
次の記事
【Unity】Mathfの切り上げ、切り捨て、偶数丸め。使い分けが大事よね 2018.07.03
コメントを書く