Instantiate (prefab, transform.position, transform.rotation) as GameObject;
って書くのめんどくさい
あるゲームオブジェクトの Prefab をシーン内にアタッチする時に、こういったコードを書くかと思います
Example.cs
public GameObject effectPrefab;
public float effectLifeTime = 3.0f;
void Update () {
// 左クリック
if (Input.GetMouseButtonDown (0)) {
// エフェクトを Prefab からゲームシーンへアタッチ
var effect = Instansiate (
effectPrefab,
transform.position,
transform.rotation
) as GameObject;
// エフェクトの Transform ノードを自分の子要素にする
effect.transform.parent = transform;
// エフェクトをコルーチンで消す
StartCoroutine ("AutoEraseEffect", effect);
}
}
IEnumrator AutoEraseEffect (GameObject effect) {
yield return new WaitForSeconds (effectLifeTime);
Destroy (effect);
}
↑ の例だけだったら別に良いのだけれど、
- アタッチしたオブジェクトの localPosition を変更したい…
- アタッチしたオブジェクトの rotation は Prefab で設定したものから変更したくない…
- アタッチしたオブジェクトにあるはずの Component を取り出して使いたい…
等々、「Instantiate (...) as GameObject って毎回長いの書きたくないけどバリエーションが沢山あってダルい…」と思うようなユースケースが多々出てくるかと思います。
PrefabController
自分の場合 ユーティリティクラスとしてこういうのを最初に書いておきます
PrefabController.cs
using UnityEngine;
using System;
public enum CloneMode {
/// <summary>
/// Clone rotation follow parent.
/// </summary>
FollowParent,
/// <summary>
/// Clone rotation keep prefab's rotation.
/// </summary>
KeepRotate
}
public class PrefabController : MonoBehaviour {
// 引数の mode (デフォルトは parent の rotation に従う)に合わせて Prefab のアタッチメント
// Transform のノードはヒエラルキーのトップ
public static GameObject Clone (GameObject prefab, Transform parent, CloneMode mode = CloneMode.FollowParent) {
Transform rotationOrigin;
switch (mode) {
case CloneMode.KeepRotate:
rotationOrigin = prefab.transform;
break;
default: // Follow Parent Transform
rotationOrigin = parent;
break;
}
return Instantiate (prefab, parent.position, rotationOrigin.rotation) as GameObject;
}
// 引数の parent の子要素としてアタッチ
public static GameObject CloneAsChildren (GameObject prefab, Transform parent, CloneMode mode = CloneMode.FollowParent) {
var instance = Clone (prefab, parent, mode);
instance.transform.parent = parent;
return instance;
}
// 引数の sibling の兄弟要素としてアタッチ
public static GameObject CloneAsSibling (GameObject prefab, Transform sibling, CloneMode mode = CloneMode.FollowParent) {
var instance = Clone (prefab, sibling, mode);
instance.transform.parent = sibling.parent;
return instance;
}
}
つくりたいゲームの仕様次第ですが、たとえば 「シーンロードの際に非同期通信を行い、ゲームのレベルデザイン設定ファイルを受け取ってそこからゲームオブジェクトを生成させる」などのユースケースで効果を発揮します。
おまけ 「エフェクト(パーティクルシステム)」には自分で自分を Destroy する仕組みをもたせた方が管理が楽
有名なアセットの Detonator や Explosion V1 & V2 などはそういうパターンで設計されていますが、アタッチされてから、自分で一定時間演出して、自分で Destroy (gameObject);
を呼ぶ仕組みにしておくと便利です。
ただ、外側から GameObject として持っているメンバーは他のオブジェクトからも参照できるので、 NullReferenceException
に注意しましょう