OnValidate in Unity: A Brief Guide

August 21, 2023

As a game developer for Unity, it took me a while to encounter OnValidate. That’s a little strange because OnValidate is very useful. It is a great tool to check data in the Editor. And, it helps you to make your Unity Editor more dynamic. With OnValidate, you can set up powerful workflows that help you to develop your game faster. So, I set out to write a brief guide on OnValidate for new Unity game developers.

What you need to know for OnValidate

  • Use OnValidate to check serialized data in the Unity Editor.
  • OnValidate only executes in the Editor. Don’t include runtime-specific logic here.
  • OnValidate prevents invalid data from entering your system. This saves debugging time.

What you will learn

In this article, I will walk you through the basics for the OnValidate function. You’ll learn how OnValidate works, how to use OnValidate, and best practices. And, I’ll give an example from my own code. If you understand how to use this function, you will build better games faster. So, stick with me to become a pro on OnValidate.

What is OnValidate?

OnValidate is a method that you can define within a script attached to a GameObject or component.

In any MonoBehaviour class, just define the method. Here’s how you would define it:

void OnValidate()
{
  // Your code here
}

Any time that you change a field of a component, the Unity Editor triggers OnValidate. This makes it easy to perform data validation. You can use OnValidate to kick off a workflow based on data changes.

Why should I use OnValidate?

OnValidate is a tool to maintain the integrity of your project’s data. If you use robust OnValidate checks, you can make sure that your data meets specific rules. If you don’t use OnValidate, your data can be anything. Random data leads to errors. Errors lead to crashes. Crashes waste your time. When you catch these errors early, you save yourself time and effort in the future.

(Random values can be super useful, though. For example, you can use randomization to help you brainstorm new game ideas like our random game generator)

OnValidate is also a tool to help your project’s inspector become more powerful. You can use OnValidate to initiate complex data creation. You can use this tool to automate repetitive tasks to help you build your game more quickly.

Later in this article, I will explain how you use OnValidate. Before we get there, you need to understand one more important detail: OnValidate does not run in built projects.

OnValidate only runs in the Editor

OnValidate only runs within the Unity Editor. It does not execute during runtime gameplay in built projects. You can only use this method for Editor-time validation and preparation. You can’t use it for runtime logic. This limitation helps prevent unexpected performance overhead. Your data validation remains focused on development and testing phases.

OnValidate allows you to add rules that check your data when you make changes in the Inspector. OnValidate saves you time and effort by preventing bugs. And, it only runs in the editor, so it does not pollute your runtime.

Advantages of OnValidate for Data Validation

The OnValidate method offers several advantages for data validation:

  • Immediate Feedback:
    With OnValidate, you can catch and correct errors immediately after making changes in the Inspector, reducing the chances of runtime issues.
  • Consistent Data:
    It ensures that the data being entered adheres to certain rules or constraints, maintaining the integrity of your objects and scenes.
  • Saves Debugging Time:
    By validating data early in the development process, you can identify and fix potential issues before they cause runtime bugs, reducing debugging time.
  • Dynamic Workflows:
    You can use OnValidate to kick off workflows when you change a value in the Inspector. This helps you build your project more quickly by avoiding repetitive setup tasks.

Applying OnValidate for Value Constraints

OnValidate can be applied in scenarios where you want to enforce specific value constraints on serialized variables:

Example: Let’s say you have a game character’s health attribute. You can use OnValidate to ensure that the health value never goes below zero and never exceeds a maximum value. If a value violates these constraints, you can automatically adjust it back to a valid range within OnValidate.

using UnityEngine;

public class PlayerHealth : MonoBehaviour
{
  [SerializeField]
  private int maxHealth;
  private void OnValidate()
  {
    maxHealth = Mathf.Clamp(maxHealth, 0, 100);
  }
}

In this case, you could also use the [Range()] Attribute: https://docs.unity3d.com/ScriptReference/RangeAttribute.html

using UnityEngine;

public class PlayerHealth : MonoBehaviour
{
  [SerializeField, Range(0, 100)]
  private int maxHealth;
}

If you are unfamiliar with how to serialize properties in Unity, learn everything you to need to know about Serialize Field in Unity

Examples of Generating or Modifying Data with OnValidate

The previous example was a great primer for showing how to use OnValidate in a basic context. But, you will want to use OnValidate to perform more complex actions. In this example, I will show how you can use OnValidate to automatically modify data based on specific conditions:

Example 1 - Auto-Adjustment

Imagine you have a Unity component that combines the positions of two child objects to determine its own position. If someone manually changes the position of the component, you can use OnValidate to automatically recompute the position based on the child objects’ positions.

using UnityEngine;

public class CombinedPosition : MonoBehaviour

{
  [SerializeField]
  private Transform targetA;

  [SerializeField]
  private Transform targetB;
  
  private void OnValidate()
  {
    transform.position = (targetA.position + targetB.position) / 2f;
  }
}

Example 2 - Level Design

In a level design scenario, you might have a script that generates terrain features based on a set of parameters. Using OnValidate, you could automatically regenerate the terrain whenever those parameters are changed, ensuring that the terrain always aligns with the intended design.

using UnityEngine;

public class TerrainManager : MonoBehaviour

{
  public enum TerrainType
  {
    Mountains,
    Plains,
    Canyons
    }
    
    [SerializeField]
    private TerrainType terrainType;
    
    private void OnValidate()
    {
      RegenerateTerrain(terrainType);
    }

    private void RegenerateTerrain(TerrainType terrainType)
    {
      // Regenerate the terrain
    }
}

Example 3 - Dynamic Scaling

Suppose you’re building a UI system, and you want a UI element’s size to automatically adjust based on its content. Using OnValidate, you can ensure that the UI element’s size updates whenever the content changes, providing a more dynamic user interface.

using UnityEngine;

public class UIManager : MonoBehaviour

{
  [SerializeField]
  private string dialogue = ""Ciao mamma"";

  private void OnValidate()
  {
    RectTransform rectTransform = GetComponent<RectTransform>();
    rectTransform.sizeDelta = new Vector2(dialogue.Length \* 10, rectTransform.sizeDelta.y);
  }
}

In each of these examples, OnValidate helps maintain the desired state of your objects and scenes by automatically generating or modifying data based on specific conditions or constraints. This streamlines development and ensures consistency while reducing the need for manual adjustments.

Primary Focus of OnValidate

Your primary focus when using OnValidate should be to ensure data consistency, integrity, and validation during the development process. Use it to catch errors early and provide immediate feedback when serialized variables are modified.

OnValidate only works in the Editor with Serialized Data

OnValidate is a powerful tool for validating and preparing data during development, but it does have some limitations:

  • Editor-Only:
    The OnValidate method is meant for Editor-time validation and preparation. It won’t be called during runtime, so any logic specific to runtime behavior should not be placed here.
  • Performance Impact:
    Performing resource-intensive tasks or complex computations within OnValidate can slow down your Editor. In turn, this can slow down your development process. Probably not something you need to worry about. But, good to keep it in mind.
  • Serialization Only:
    OnValidate is meant for serializable fields. Non-serializable fields or complex logic involving non-serialized properties won’t work as expected within this method. Non-serialized field values will be reset when making a Build, so anything you set in OnValidate will be thrown out. Learn more about SerializeFields here: /blog/serializefield-in-unity

OnValidate is great for Immediate Feedback and Consistent Data

The OnValidate method in Unity is called whenever you modify an Inspector-exposed variable or change something in the Editor. It’s a powerful tool to catch errors early and ensure data consistency. Here are some scenarios where you will want to use OnValidate to build faster:

  • Immediate Feedback:
    Use OnValidate to validate and sanitize input data immediately after changes are made. This can prevent runtime errors and unexpected behavior.
  • Avoid Debugging Delays:
    Catch potential issues before entering play mode by validating data during editing. This saves time compared to discovering problems during runtime debugging.
  • Ensure Consistency:
    Use OnValidate to enforce consistency between related variables, ensuring that they adhere to certain rules or constraints.

Consider using OnValidate for Serialized, Dependent, or Boundary values

You will need to decide which variables you validate using the OnValidate method. In general, though, there are some categories of variables that you could consider validating:

  • Serialized Variables:
    Variables that are exposed in the Inspector could be validated to prevent invalid data from being input by users, like a string input that requires all characters to be formatted using lowercase letters.
  • Dependent Variables:
    If changing one variable should influence another, use OnValidate to ensure these dependencies are maintained.
  • Boundary Values:
    Ensure that numeric values, such as sizes, lengths, or ranges, fall within acceptable bounds. (I recommend using RangeAttribute for this use case).
  • References:
    Validate references to other components or assets to prevent null references or incorrect assignments. (Make sure that you use SerializeField for these references).
  • Complex Data Structures:
    Validate arrays, lists, or dictionaries to ensure their contents are valid and consistent.

Rendering in the OnValidate method call

While rendering operations typically aren’t performed directly within OnValidate, you might consider using OnValidate to trigger a rendering-related update as a response to a modified value in the inspector. Here is one way you might approach this:

  • Separation of Concerns:
    Keep OnValidate focused on validation and data preparation.
  • Flagging for Rendering:
    If a change requires a rendering update, use OnValidate to set a flag. Then, handle the actual rendering updates in the Update or LateUpdate methods.
  • Efficiency:
    Be cautious with performance. Rendering is always a resource-intensive operation. Avoid triggering it too frequently during validation.

Remember, the OnValidate method is meant for Editor-time validation and preparation. While you can trigger rendering updates indirectly, heavy rendering operations are typically better suited for the regular update loop.

Conclusion

In summary, using OnValidate can improve your game development workflow by catching errors early and ensuring consistent data in particular fields. As the developer, you should focus on making it easy for your designers to use your systems without guidance.

Use OnValidate to validate serialized variables, dependent variables, and boundary values. When it comes to rendering, separate the rendering concerns from OnValidate and trigger rendering updates in appropriate update loops.

In conclusion, Unity’s OnValidate function holds significant importance for data validation and helps you build games faster and with less bugs.

1. Using OnValidate for Data Validation

Unity’s OnValidate function plays a crucial role in ensuring data integrity, catching errors early in the development process, and maintaining consistency within your projects. It empowers developers and designers to validate and adjust serialized variables and object properties directly in the Unity Inspector, preventing invalid data from entering the system and reducing the likelihood of runtime issues.

2. Using OnValidate to Increase Efficiency

OnValidate enhances development efficiency by providing immediate feedback during the editing phase.

This approach can avoid errors and inconsistencies directly. It can also help identify errors and inconsistencies before reaching the runtime environment, which will help save you time debugging your game.

OnValidate makes it easy to validate and adjust user-inputs in the Editor in real-time. Iterate on your projects more quickly and leverage iterative design practices to build better games. Catch issues early to be more productive and avoid rework.

3. Key Takeaways Regarding Best Practices

When working with OnValidate, remember the following best practices:

  • Validation and Consistency Checks:
    Use OnValidate primarily for data validation and consistency checks during development.
  • Avoid Resource-Intensive Calculations:
    Try to avoid resource-intensive calculations, rendering events, and scene modifications to keep your Editor environment running quickly.
  • Automation and Adjustment:
    Use OnValidate to automate the generation or adjustment of data based on specific conditions or constraints.
  • Immediate Feedback:
    Use real-time error reporting in OnValidate to provide immediate feedback to your designers as they edit values in the Inspector to prevent errors from propagating to runtime environments.
  • Iterate Faster:
    Catch and address issues early without entering play mode so that you designers can rapidly change values while jumping in-and-out of play mode.

By effectively applying OnValidate and following these best practices, you can maintain valid data in your project, maintain consistency across your project, and develop games more quickly in Unity.

Additional Resources for OnValidate

This article has turned out much longer than I intended. But, I am sure that some of you may still want to learn more about OnValidate. So, I compiled some additional reading for you.

To access Unity’s official documentation on OnValidate, check here:

For some community documentation and community insights on using OnValidate, check out these links:

Want to build better games?

© 2024