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

テラシュールブログ

旧テラシュールウェアブログUnity記事。主にUnityのTipsやAR・VR、ニコニコ動画についてのメモを残します。

シーン内のオブジェクトをInstantateするメリット

弾を生成する場合、以下の手順を行うのが一般的だ。

  1. 弾のprefabを生成
  2. Resources、もしくは参照から1を取得
  3. 2をGameObject.Instantiateする
実はGameObject.Instantiateは、別にプレハブでなくとも実行できる。
GameObject.Instantiateの本質は「GameObjectをクローンする」の一点なので、例えばシーン内に存在するオブジェクトを量産する場合にも使用することが出来る。


利点

これの便利な点は2つ。


プレハブのバリエーションが作りやすい


この方法でプレハブを使用した場合、プレハブの参照を維持したままバリエーションを持ったプレハブを用意する事ができる。例えば下の画像では、3種類のパターンのオブジェクトが生成可能。しかもベースとなるプレハブは1個のため、ベースプレハブを変更すればパラメータを一括変更することが可能。

本来はプレハブ化したオブジェクトは値を一部変更する事でユニーク化する事ができるが、プレハブ本体を変更すると全体が変化してしまうため、結局完全なユニークで分割する事になる。

スクリーンショット 2014-06-13 1.50.54


画面を見ながら調整しやすい


この方法で作成する擬似プレハブは既にシーンに配置された物を使用するので、実際に使用する大きさや雰囲気を掴みながら作業を進めやすい。例えば下の画像の障害物は、プレハブからではなくシーンのオブジェクトからオブジェクトを取得している。実際見ると大きさを掴みやすくて中々良い。

スクリーンショット 2014-06-13 0.59.21
デメリットは、ゲーム内全体で共有しにくいこと。また、リソースを確保・破棄するためにResourcesを使っているゲームには使いにくい。

そしてコレ書いてる時にバリエーションプレハブを思いついた。今度実験する。


やり方

例えば、以下の様なスクリプトをPrefabControllerオブジェクトにアタッチする。

using UnityEngine;
using System.Collections;
using System.Collections.Generic;

public class PrefabController : SingletonMonoBehaviour<PrefabController>{

    public static T Load<T>(string name)  where T : Component
    {
        GameObject prefab = System.Array.Find(Instance.prefabs, (item) => item.name == name);
        return (T)prefab.GetComponent(typeof(T));
    }

    public static GameObject Load(string name)
    {
        return System.Array.Find(Instance.prefabs, (item) => item.name == name);
    }

    public GameObject[] prefabs = new GameObject[0];

    new void Awake()
    {
        ifInstance != this)
        {
            Destroy (gameObject);
            return;
        }

        ifprefabs.Length == 0 )
        {
            RegisterChildren();
        }

        gameObject.SetActive(false);
    }

    [ContextMenu("RegisterChildren")]
    void RegisterChildren()
    {
        Transform _transform = transform;
        
        List<GameObjectgameObjectList = new List<GameObject>();
        for(int i=0i_transform.childCounti++)
        {
            Transform obj = _transform.GetChild(i);
            gameObjectList.Add(obj.gameObject);
        }

        prefabs = gameObjectList.ToArray();
    }
}

で、PrefabController以下にプレハブの元となるオブジェクト群を配置する。

後は実行時にResourcesの代わりに以下のコードを呼ぶ。

GameObject prefabPrefabController.Load(prefabName);
GameObject obj = GameObject.Instantiate(
prefab);