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

Unityな日々(Unity Geek)

Unityで可視化アプリを開発するための試行錯誤の覚書

他のGameObject、Componentにアクセスする

現在のScriptがアタッチされているGameObject以外のGameObjectにアクセするには次の方法がある。


1)Inspectorでアサインする
public変数としてGameObjectを定義し、Inspector上で該当GameObjectをアサインする方法。
簡単だが、この方法だとScriptだけで完結しないため、デバッグや再利用がし辛い

他のGameObjectにアタッチされているComponentに直接アクセスする場合は、public変数で該当Componentを定義し、InspectorでそのComponentを持つGameObjectをアサインすることに注意。(これはUnityEditor上でGameObjectを操作することしかできないための便法と思われる。)

using UnityEngine;
using System.Collections;

public class example : MonoBehaviour {
    public OtherScript target; //Inspector上でOtherScriptを持つGameObjectをアサインする
    void Update() {
        target.foo = 2;
        target.DoSomething("Hello");
    }
}


2)GameObjectの階層構造をたどる
現在のGameObjectから親または子のGameObjectをたどる方法。出発点は"transform"であることに注意。下は子GameObjectにアクセスする事例。GetComponentを組み合わている。

using UnityEngine;
using System.Collections;

public class example : MonoBehaviour {
    void Example() {
        transform.Find("Hand").GetComponent<OtherScript>().foo = 2;
        transform.Find("Hand").GetComponent<OtherScript>().DoSomething("Hello");
        transform.Find("Hand").rigidbody.AddForce(0, 10, 0);
    }
}

すべての子GameObjectに対して同じ操作を行う場合、foreach ... in transform ループで子GameObject(のTransformコンポーネント)をひとつずつ見ていく。

using UnityEngine;
using System.Collections;

public class example : MonoBehaviour {
    void Example() {
        foreach (Transform child in transform) {
            child.Translate(0, 10, 0);
        }
    }
}

親GameObjectを取得するには、(childGameObject.)transform.parent とする。


3)名前またはタグを使う

using UnityEngine;
using System.Collections;

public class example : MonoBehaviour {
    void Start() {
        GameObject go = GameObject.Find("SomeGuy");
        go.transform.Translate(0, 1, 0);
        go.GetComponent<OtherScript>().DoSomething();
        GameObject player = GameObject.FindWithTag("Player");
        player.transform.Translate(0, 1, 0);
        player.GetComponent<OtherScript>().DoSomething();
    }
}


4)メッセージの送受による

イベントハンドラを通じてColliderコンポーネントから、アタッチされているScriptを取得する。
そのScriptが存在するかどうかは、if(該当Script名)とする。

using UnityEngine;
using System.Collections;

public class example : MonoBehaviour {
    void OnTriggerStay(Collider other) {
         other.rigidbody.AddForce(0, 2, 0);
        if (other.GetComponent<OtherScript>())
            other.GetComponent<OtherScript>().DoSomething();
        }
    }
}


5)同タイプのすべてのオブジェクトを取得する
FindObjectOfType(タイプ名)を使う。クラス(スクリプト)の場合のタイプ名は、typeof(スクリプト名)とする。

using UnityEngine;
using System.Collections;

public class example : MonoBehaviour {
    void Start() {
        OtherScript other = FindObjectOfType(typeof(OtherScript));
        other.DoSomething();
    }
}

複数ある場合は、FindObjectsOfType()を使って配列として取得する。

using UnityEngine;
using System.Collections;

public class example : MonoBehaviour {
    void OnMouseDown() {
        HingeJoint[] hinges = FindObjectsOfType(typeof(HingeJoint)) as HingeJoint[];
        foreach (HingeJoint hinge in hinges) {
            hinge.useSpring = false;
        }
    }
}

なお、FindObject(s)OfTypeの実行は非常に遅い。可能であれば他の方法を使うのがよい。