はじめに
今回はMonoBehaviour.OnValidate()
とMonoBehaviour.Reset()
について取り上げたいと思います。
MonoBehaviour-Reset() - Unity スクリプトリファレンス
MonoBehaviour-OnValidate() - Unity スクリプトリファレンス
これらのメソッドを利用することで、コンポーネントをアタッチすると自動でプロパティに参照をつけたり、一括でコンポーネントの値をいじったりすることができます。
早速みていきましょう。
MonoBehaviour.OnValidate()
この関数はスクリプトがロードされた時やインスペクターの値が変更されたときに呼び出されます(この呼出はエディター上のみ)
インスペクターからプロパティをいじった際に発火されるメソッドだと覚えておけばOKです。
使い方
public class Sample : MonoBehaviour { [SerializeField] private int value; /// <summary> /// インスペクターのリセットボタンが押されたら実行される /// </summary> private void Reset() { Debug.Log("Reset"); } /// <summary> /// スクリプトがロードされた時やインスペクターの値が変更されたときに呼び出される(エディター上のみ) /// </summary> /// <returns></returns> private void OnValidate() { Debug.Log("OnValidate"); } }
MonoBehavior
を継承しているクラスでReset()
・OnValidate()
を定義します。
Reset
は以下のタイミングで呼ばれます。
- コンポーネントをアタッチしたとき
- インスペクターの
Reset
ボタンを押したとき
対してOnValidate
は以下のタイミング。
- コンポーネントをアタッチしたとき
- インスペクター上のプロパティをいじったとき
応用例
アタッチ時に参照をつける
よく利用される例として、コンポーネントをアタッチした際に自動で参照をつけることに用います。
[RequireComponent(typeof(Rigidbody))] public class Sample : MonoBehaviour { [SerializeField] private Rigidbody value; /// <summary> /// インスペクターのリセットボタンが押される&アタッチ時に呼ばれる /// </summary> private void Reset() { // RequireComponent属性より、必ずGetComponentできることが保証されている value = GetComponent<Rigidbody>(); // Rigidbodyがアタッチされていることが保証されていないなら、TryGetComponentを利用する if (TryGetComponent(out Rigidbody rigidbody)) { value = rigidbody; } } }
他のコンポーネントの値を変更する
インスペクター上のプロパティの値が変わった際に、他のコンポーネントのプロパティをいじるなんてこともできます。
DynamicBone
を利用した際に、一つのゲームオブジェクトに同じコンポーネントがたくさんついていて、一つ一ついじるのがめんどくさいといったときに活躍してくれました。
[RequireComponent(typeof(Example))] public class Sample : MonoBehaviour { [SerializeField] private int value; /// <summary> /// スクリプトがロードされた時やインスペクターの値が変更されたときに呼び出される(エディター上のみ) /// </summary> /// <returns></returns> private void OnValidate() { var example = GetComponent<Example>(); // publicな変数なら直接いじる example.value = value; // privateな変数ならリフレクションを利用 example.GetType() .GetField("privateValue", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance) ?.SetValue(example, value); } } public class Example : MonoBehaviour { public int value; [SerializeField] private int privateValue; }