Crafting custom editor scripts in Unity is a game-changer when developing your own game. Custom inspectors, windows, and tools tailored to your project’s needs offer efficiency and precision, making the development process smoother and more enjoyable.
Here are some benefits of writing your custom editor in Unity
- Tailored Workflows: Designing a custom editor allows you to streamline workflows specific to your game’s needs. You can create tools that simplify complex tasks, speeding up development and reducing errors.
- Increased Productivity: Custom editors automate repetitive tasks, saving valuable time during asset management, level design, or game creation. This efficiency boost allows you to focus more on actual game development.
- User-Friendly Interfaces: Tailoring inspectors and windows to your project ensures a more intuitive and user-friendly interface. It enables easier navigation and manipulation of game elements, benefiting you and your team.
- Precise Control: Fine-tuning properties and settings through custom inspectors provides precise control over game elements. This level of detail ensures that your game behaves exactly as intended, minimizing unexpected issues.
- Enhanced Creativity: By removing the constraints of default Unity tools, custom editors encourage experimentation and innovation. You can explore new ways of implementing features and mechanics, fostering creativity.
Let’s build an example together
Let’s begin by defining our goal: we have a “Player” class responsible for the health-related attributes.
Firstly, we aim to ensure that the health attribute remains within a specified range, constrained between a minimum and maximum value. This attribute will also be a serialized field, allowing it to be accessed and modified within the Unity Inspector.
Next, we’ll initiate by crafting a new editor class and situating it within an ‘Editor’ folder. This action signals Unity to exclude the class from the final build, preventing any potential errors during compilation.
[UnityEditor.CustomEditor(typeof(Player),true)]
public class PlayerEditor : UnityEditor.Editor
{
public override void OnInspectorGUI()
{
serializedObject.Update();
GUI.enabled = false;
EditorGUILayout.PropertyField(serializedObject.FindProperty("m_Script"));
GUI.enabled = true;
serializedObject.ApplyModifiedProperties();
}
}
We’ll generate a fresh class named ‘PlayerEditor,’ inheriting from ‘UnityEngine.Editor.’ The subsequent step involves marking this class as a custom editor for the ‘Player’ class. We achieve this by employing the ‘CustomEditor’ Attribute, specifying ‘Player’ as the target. Optionally, we can pass a boolean as the second parameter, allowing other classes inheriting from ‘Player’ to be managed within this editor.
Within the ‘OnInspectorGUI’ method, we can manage various aspects related to the class. By accessing the ‘serializedObject’ field within the Editor class, we can obtain references to all the fields.
Before diving in, let’s ensure uniformity by configuring the editor to include a ‘Script’ field and disabling it.
We begin by invoking ‘serializedObject.Update(),’ a crucial method that ensures the object is refreshed and ready for any subsequent adjustments.
Concluding our modifications, we call ‘serializedObject.ApplyModifiedProperties().’ This function refreshes the object’s values and marks them for potential undo events.
Between these functions, we have the opportunity to design our custom fields. We begin by obtaining references to the fields using ‘serializedObject.FindProperty,’ providing each field’s name. Once retrieved, we proceed to draw these fields using ‘EditorGUILayout.PropertyField,’ utilizing the previously stored field references.
Upon completion, the code structure resembles this:
public override void OnInspectorGUI()
{
serializedObject.Update();
GUI.enabled = false;
EditorGUILayout.PropertyField(serializedObject.FindProperty("m_Script"));
GUI.enabled = true;
var minHealthProp = serializedObject.FindProperty("minHealth");
var maxHealthProp = serializedObject.FindProperty("maxHealth");
var healthProp = serializedObject.FindProperty("health");
EditorGUILayout.PropertyField(minHealthProp);
EditorGUILayout.PropertyField(maxHealthProp);
EditorGUILayout.PropertyField(healthProp);
serializedObject.ApplyModifiedProperties();
}
“Now, having restored the initial state, we’ve effectively reconstructed the inspector from the ground up. Now, we’re poised to incorporate custom functionalities, like a slider representing health, all the while ensuring it adheres to the defined minimum and maximum health values.
Drawing a slider is straightforward using ‘EditorGUILayout.IntSlider.’ By specifying the slider’s label, current value, minimum, and maximum values, we obtain the updated value. After acquiring this new value, we cautiously assign it to the health field only if the GUI has indeed changed. During assignment, we ensure to clamp the value between the defined minimum and maximum health values.
Adding a playful touch, we can easily introduce a button to randomize the current health. Utilizing ‘GUILayout.Button,’ the function’s result signals if the button has been pressed. Upon button press, we implement custom logic — in this case, randomizing the health field.
if (GUILayout.Button("Randomize health"))
{
var randomHealth = Random.Range(minHealthProp.intValue, maxHealthProp.intValue);
healthProp.intValue = randomHealth;
}
here is the final look of the inspector
and here is the final code of the editor
using UnityEditor;
using UnityEngine;
namespace OM.Editor
{
[UnityEditor.CustomEditor(typeof(Player),true)]
public class PlayerEditor : UnityEditor.Editor
{
public override void OnInspectorGUI()
{
serializedObject.Update();
GUI.enabled = false;
EditorGUILayout.PropertyField(serializedObject.FindProperty("m_Script"));
GUI.enabled = true;
var minHealthProp = serializedObject.FindProperty("minHealth");
var maxHealthProp = serializedObject.FindProperty("maxHealth");
var healthProp = serializedObject.FindProperty("health");
EditorGUILayout.PropertyField(minHealthProp);
EditorGUILayout.PropertyField(maxHealthProp);
EditorGUILayout.PropertyField(healthProp);
var newHealthValue = EditorGUILayout.IntSlider("Health", healthProp.intValue, minHealthProp.intValue, maxHealthProp.intValue);
if (GUI.changed)
{
healthProp.intValue = Mathf.Clamp(newHealthValue, minHealthProp.intValue, maxHealthProp.intValue);
}
if (GUILayout.Button("Randomize health"))
{
var randomHealth = Random.Range(minHealthProp.intValue, maxHealthProp.intValue);
healthProp.intValue = randomHealth;
}
serializedObject.ApplyModifiedProperties();
}
}
}
Here is a tool I made for UI animation
https://assetstore.unity.com/packages/tools/animation/animation-creator-timeline-ui-tween-186589
In conclusion, custom editor scripts in Unity wield immense power in tailoring your development experience. These personalized tools empower you to streamline workflows, enhance productivity, and foster creativity within your game development journey. By crafting specialized editors, you not only optimize efficiency but also pave the way for innovative and intuitive game design. Embrace the potential of custom editors and unlock new horizons in your Unity projects, where your creativity knows no bounds.