ゲームオブジェクトの取得

■概要

スクリプト内でゲームオブジェクトを取得する方法は
「GameObjectのFind関数を使用する」「Assetsフォルダから読み込む」
「ゲームオブジェクトをメンバ変数とし、Unity上で設定する」等があります。

■Find関数使用による取得

GameObjectクラスにはFind関数が用意されており、
その関数を使用することでHierarchyにあるゲームオブジェクトを取得することができます。

●手順
	以下はHierarchyにあるBallオブジェクトをBallControllerスクリプトで
	Findを使用して取得をし、操作するまでの手順です。

	①.HierarchyにSphereを作成し、名前を「Ball」にする

	②.Hierarchyに空のGameObjectを作成し、「BallController」にする

	③.スクリプト「BallController」を作成する

	④.スクリプトに以下の内容をコーディングする
		public class BallController : MonoBehaviour {
			private GameObject m_Ball;

			// Use this for initialization
			void Start () {
				// BallをHierarchyからみつける
				m_Ball = GameObject.Find ("Ball");
			}
				
			// Update is called once per frame
			void Update () {
				// ボールをこのスクリプトで動かす
				Vector3 pos = m_Ball.transform.localPosition;

				if (Input.GetKey (KeyCode.UpArrow)) 
				{
					pos.y += Time.deltaTime;	
				} else if (Input.GetKey (KeyCode.DownArrow)) {
					pos.y -= Time.deltaTime;
				}

				if (Input.GetKey (KeyCode.LeftArrow)) 
				{
					pos.x -= Time.deltaTime;
				} else if (Input.GetKey (KeyCode.RightArrow)) {
					pos.x += Time.deltaTime;
				}

				m_Ball.transform.position = pos;
			}
		}

	⑤.スクリプト「BallController」をゲームオブジェクト
	  「BallConroller」に関連付ける

	⑥.実行して挙動を確認する
	  ※矢印キーを押してBallが動いたら成功

●Find
	戻り値:
		成功:GameObject
		失敗:null
		
	引数:
		string:ゲームオブジェクトの名前
		
	内容:
		指定した名前のゲームオブジェクトがHierarchy上に存在したら
		そのオブジェクトが返り、存在しなければnullを返す

	例:
		// 「Cube」という名前のオブジェクトを探す
		GameObject obj = GameObject.Find("Cube");

■Assetsフォルダから読み込む

AssetsフォルダにあるPrefabやテクスチャなどのリソースの読み込みは
ResourcesクラスのLoad関数を使用して読み込むことができます。

●手順
	以下の手順はプレハブ化したBoxをLoad関数を使用して読み込み
	Instantiate関数で複製を行うまでの手順です。

	①.プロジェクトビューにResourcesフォルダを作成する

	②.HierarchyでCubeを作成し、名前を「Box」にする

	③.Boxをプレハブ化する
	    ※プレハブ化したBoxはResourcesフォルダに入れる

	④.HierarchyにあるBoxを削除する

	⑤.Hierarchyに空のGameObjectを作成し、名前を「BoxController」にする

	⑥.スクリプト「BoxController」を作成する

	⑦.BoxControllerに以下の内容をコーディングする
		public class BoxController : MonoBehaviour {
			private GameObject m_Box;
			private float m_Timer;

			// Use this for initialization
			void Start () {
				// ResourcesフォルダからBoxプレハブを読み込み
				m_Box = Resources.Load("Box") as GameObject;
				m_Timer = 0;
			}
				
			// Update is called once per frame
			void Update () {
				m_Timer += Time.deltaTime;

				if (m_Timer > 1.0f) 
				{
					Instantiate (
						m_Box,
						new Vector3 (Random.Range (-5.0f, 5.0f),
							Random.Range (-5.0f, 5.0f),
							Random.Range (-5.0f, 5.0f)),
						Quaternion.identity);

					m_Timer = 0.0f;
				}
			}
			
	⑧.スクリプト「BoxController」をゲームオブジェクト
	  「BoxController」に関連付けする

	⑨.実行する
	  Boxが一定間隔で生成されていれば成功

●前提条件、知識
	・Resourcesフォルダ
		Assetsフォルダにあるリソースを読み込むためには
		「Resourcesフォルダ」が必要です。
		フォルダの作成はプロジェクトビューのAssets内で
			右クリック => Create => Folderで作成できます。

	・as演算子
		as演算子はC#の機能でダウンキャストを行う際に使用する演算子です。
		基底クラスを派生クラスに型変換できたら、
		そのままキャストが行われ、型変換で不可能な場合はnullを返します。
		これによりダウンキャストが失敗した際のフリーズのリスクを
		回避することが可能です。

		書式:
			派生クラス 変数名 = 基底クラス as 派生クラス

		具体例:
			namespace AsTest
			{
				class Animal
				{
					public Animal() { }
				}

				class Dog : Animal
				{
					public Dog() {}
				}

				class Cat : Animal 
				{
					public Cat() {}
				}

				class Program
				{
					static void Main(string[] args)
					{
						Cat test = new Cat();
						// アップキャスト
						Animal animal = (Animal)test;
						// ダウンキャスト
						Cat cat = animal as Cat;
						// ダウンキャスト
						Dog dog = animal as Dog;
						string str = "";

						if (cat != null)
						{
							str = "Catのダウンキャスト成功";
							Console.WriteLine();
						} else {
							str = "Catのダウンキャスト失敗";
						}
						Console.WriteLine(str);

						if (dog != null)
						{
							str = "Dogのダウンキャスト成功";
						} else {
							str = "Dogのダウンキャスト失敗";
						}
						Console.WriteLine(str);
					
				       		while (true) ;
					}
				}
			}

			実行結果:
				Catのダウンキャスト成功

■ゲームオブジェクトをメンバ変数とし、Unity上で設定する

ゲームオブジェクトのメンバ変数を作成し、その変数に対して
Unity上でプレハブ、またはHierarchy上のゲームオブジェクトを指定することで
指定したゲームオブジェクトをスクリプト上でアクセスすることができます。

●手順例:
	①.ゲームオブジェクトをPrefab化する
		Hierarchy上で「Cube」を作成し、「OriCube」とし、
		プロジェクトビューのAssetsフォルダにD&Dする

	②.動的作成を行うゲームオブジェクトを作成する
		空のゲームオブジェクトを作成し、「CubeFactory」とする

	③.スクリプトを作成する
		C#でスクリプトを作成し、名前を「CubeFactory」とする

	④.ゲームオブジェクトのメンバを追加する
		CubeFactoryをエディタで開き、GameObject型のメンバ変数を作成する
		※public必須

		public GameObject m_CubeBase;

	⑤.②で作成したオブジェクトにスクリプトを関連付ける
		ゲームオブジェクト「CubeFactory」にスクリプト「CubeFactory」を関連付ける

	⑥.メンバ変数にゲームオブジェクトを関連付ける
		CubeFactoryオブジェクトのInspectorの「CubeFactory(Script)」の
		ゲームオブジェクトのメンバ変数に①で作成したPrefabを関連付ける

上記の流れを実行することで、ゲーム実行時に「CubeFactory」のメンバ変数には
「OriCube」が設定されているので、このメンバに対してアクセスすることが可能です。

■注意点

Load関数を使用した場合やメンバ変数への指定でAssetsのプレハブを指定した場合の
注意点ですが、これらのオブジェクトはそのまま使用することはできません。
これらはオブジェクトはあくまで原本として扱い、Instantiateなどの生成関数で
複製してゲーム上(Hierarchy上)に実体化させる必要があります。
以下の処理はデータの初期設定を行うという意味では効果がありますが、
Hierarchy上に実体がないので画面上には一切効果を発揮していません。

	例:
		Vector3 new_scale = new Vector3(2.0f, 1.0f, 1.0f);
		// コピー元の取得
		m_Box = Resources.Load("Box") as GameObject;
		m_Box.transform.localScale = new_scale;