【Unity】シーン上のオブジェクト取得時にシングルトンっぽい動きの実現

というわけで、時々「ブログ名変なの」とか言われるりべるんです。
「ゴマちゃん」で「フロンティア」で「バージョン2」ってだけなのですが・・・。

今回もよく分からないタイトルですが、要は「シーン上に1つしかないオブジェクトのコンポーネント」を取得する際に、シングルトンパターンっぽく出来ないかというお話です!

「Unityでシングルトン」的な話題はぐぐると幾らでもヒットしますが、MonoBehaviour を継承していないクラスでのお話だったりします。
(MonoBehaviour を継承しなければ new 演算子でインスタンス化できます)
しかし、Unity 的にはシーン上に管理用オブジェクトを配置し、インスペクターから必要なパラメータやプレハブの設定をしたい・・・という場面があります。

自分のゲームで言うと、ゲーム内の共通エフェクトをまとめた EffectManager 何かが正にそれです。
エフェクト毎にプレハブを設定しておき、マネージャから生成・破棄の管理をしています。

shot2ss20161203194259608

そんなシーン上に1つしかないオブジェクトを効率よく取得する方法について考えてみました!

単一オブジェクトのコンポーネント取得

シーン上に存在するオブジェクトを取得するには Find() か何かしてくるわけですが、そのオブジェクトを複数のクラスから参照する場合、いちいち Find() → GetComponent() は避けたいところです。
ということで、「自身の静的フィールドにインスタンスを保持し、あったらそれを返す、なかったら Find()&GetComponent() する」という動きを実装してあげます。

using UnityEngine;
using System.Collections;

public class TestManager : MonoBehaviour {

    private static TestManager testManager;

    public void hoge() {
        Debug.Log("hoge");
    }

    public static TestManager getInstance() {
        if (testManager == null) {
            testManager = GameObject.Find("TestManager").GetComponent<TestManager>();
        }

        return testManager;
    }
}

取得時はシンプルに getIntance() を呼ぶだけです。

void Start() {
    TestManager testManager = TestManager.getInstance();
    testManager.hoge();
}

GameObjectで応用

別にクラスのインスタンスに限らず、シーン上に1つしか存在しない GameObject を取得する場合にも使えます。
ちょっと変えるだけでいけそうな雰囲気。

using UnityEngine;
using System.Collections;

public class TestManager : MonoBehaviour {

    private static GameObject testManager;

    public void hoge() {
        Debug.Log("hoge");
    }

    public static GameObject getInstance() {
        if (testManager == null) {
            testManager = GameObject.Find("TestManager");
        }

        return testManager;
    }
}

取得方法も変わりません。
GameObject に対して操作するときはこれでもOKですね。

GameObject testManager = TestManager.getInstance();
Debug.Log(testManager.ToString());

シーン上に1つしかないもの・・・DirectionalLight や mainCamera とかですね。
特にカメラはあれこれ動かす機会が多くなりそうなので重宝します。
実現のために1つスクリプトを作成しなければなりませんが、複数クラスから Find() を連発するよりはマシかと思われます。

まとめ

そんなわけで、MonoBehaviour を継承したオブジェクトを何度も取得する場合について考えてみました!
Unity5 で早くなったとはいえ、Find() や GetComponent() を繰り返すのは避けたいところですね。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

*