Unityのスクリプトで、別スクリプトの「関数/メソッド」にアクセスするメモです。簡単なサンプルで確認していきます。
はじめに
Unityのバージョンは2021.3.14f1です。
例えば、「プレイヤーを動かすスクリプト」と「スコアを加算するスクリプト」の2つがあるとします。この時、プレイヤースクリプト内から別スクリプトに当たるスコア加算スクリプトにアクセスするイメージです。
実装開始
サンプルの作成なので、出来るだけシンプルに動作だけを見ていきます。
オブジェクトの作成
「2D Object」→「Sprites」→「Square」を追加します。
「Create Empty」で空のオブジェクトを追加、名前は「Score」にします。
スクリプトをアタッチ
下記のようにそれぞれ「Squareスクリプト」と「Scoreスクリプト」をアタッチします。
GameObject.FindやFindObjectOfTypeなど
各スクリプトを下記のようにします。Scoreスクリプトでは呼び出しでスコアを加算。
using UnityEngine; public class Score : MonoBehaviour { private int score = 0; public void UpdateScore() { score++; Debug.Log(score); } }
スペースキー押下でScore内の関数を実行しています。
using UnityEngine; public class Square : MonoBehaviour { void Update() { if (Input.GetKey(KeyCode.Space)) GameObject.Find("Score").GetComponent<Score>().UpdateScore(); } }
試しに実行してみてスペースキーを押して下記のようになればOK。
似たような感じで下記のような「FindObjectOfType」、ScoreオブジェクトにタグをつけてFindGameObjectWithTagもあります。
FindObjectOfType<Score>().UpdateScore();
しかし、公式リファレンスでは、パフォーマンス面から毎フレームでこの関数を使用することは推奨されませんとされています。
インスペクタでセット
頻繁に利用する場合「GetComponentも含めてあらかじめセット」しておくのが良い方法ですね。例えば、スクリプトを下記のようなに変更。Scoreスクリプトはそのまま。
using UnityEngine; public class Square : MonoBehaviour { [SerializeField] private Score _score; void Update() { if (Input.GetKey(KeyCode.Space)) _score.UpdateScore(); } }
インスペクタ画面でセット。
インスタンス化
複数スクリプトから利用したい場合、インスタンス化するのも一つの方法ですね。各スクリプトは下記のような感じ。
using UnityEngine; public class Score : MonoBehaviour { public static Score Instance {get; private set; } public int score = 0; private void Awake() { instance = this; } public void UpdateScore() { score++; Debug.Log(score); } }
using UnityEngine; public class Square : MonoBehaviour { void Update() { if (Input.GetKey(KeyCode.Space)) Score.Instance.UpdateScore(); } }
Manager系(GameManager、UIManager、SoundManagerなど)はInstance化してあるのをよく見かけますね。他にもUnityActionを利用するなど様々な方法があります。