Where the Reset Method only gets called once when the component is first added, Unity will call OnValidate
much more often:
- When the component is first added or the
Reset
function is used from its context menu (same asReset
). - When the component is loaded, such as when opening a scene, editing a prefab, or after you modify a script and Unity recompiles it.
- When the component is modified in the Inspector.
So we can use it to simply get the required component if one wasn't already assigned:
using UnityEngine;
public sealed class OnValidateMethodExample : MonoBehaviour
{
[SerializeField] private Rigidbody _Rigidbody;
private void OnValidate()
{
if (_Rigidbody == null)
TryGetComponent(out _Rigidbody);
}
private void FixedUpdate()
{
_Rigidbody.AddForce(Vector3.up * 10);
}
}
Advantages
- All the same advantages of the Reset Method, which are:
- Fastest runtime performance - Unity deserializing the reference to set the field is faster than a script calling
GetComponent
on startup and the cost of calling it in Edit Mode doesn't actually matter. - The Inspector shows what other components the
OnValidateMethodExample
depends on and which one is actually being used. - The other components can be anywhere. The script isn't hard-coded with the assumption that the
Rigidbody
will be attached to the sameGameObject
. - It will automatically find the required
Rigidbody
(if there is one) when you first add theOnValidateMethodExample
component.
- Fastest runtime performance - Unity deserializing the reference to set the field is faster than a script calling
- If you add or rename a serialized field after you have already added the script to an object, the
OnValidate
method will get called again.
Disadvantages
Summary | Description | Solution |
---|---|---|
Verbose | This approach uses more code than any other. | Extension Methods can help reduce the length without losing the advantages of this approach. |
Only runs on loaded objects | If you add or rename a serialized field after you have already added the script to an object in a different scene that you don't currently have open, the OnValidate method will not get called on that object unless you go and actually open that scene and re-save it. |
Using a [FormerlySerializedAs attribute can avoid losing assigned values when you rename a field, but otherwise this can only really be avoided by the Get Component, Get Component Cached, and Require Component approaches which always perform their search at runtime. |