Explanation
So you implemented the FrameChecker from the last post but your editor is looking pretty bad. If you managed to make the FrameChecker appear in the inspector, you are seeing 3 integer boxes. Besides not looking great, it's probably making it hard for you to quickly modify things and have an idea of what you are actually doing.
Let's refresh what that class does. We created the FrameChecker to give it an animation clip and a range of frames in which we want to do something. For example, an attack. The animation for a punch may have 12 frames, but we only want to do damage in frames 4 to 8.
Problems
With the standard inspector you can input any frame number. You could even input negative frame numbers, or one greater than the total number of frames. Also you could make the start of the range bigger than the end, like hitting in frames 9 to 2. All of those are invalid states for our class, they break the implicit contract we were thinking of when we made it.
What do we want?
We want to enforce the contract, so you (or whoever uses this class) can only use valid inputs and therefore get valid outputs. Also we want a clear input interface and a way to provide visual feedback for valid and invalid values.
The Contract
The minimum possible frame number is 1.
The maximum possible frame number is the total frame number that the animation has.
hitFrameEnd should be bigger than hitFrameStart (they can't be equal).
I want a clear indicator of how many frames every move stage has (Startup, Active and Recovery)
The first 3 we can enforce via code. You would have to use C# setters or a custom method because in this case FrameChecker is not a MonoBehaviour, so we can't use OnValidate(). I won't go into this because there's already a lot of answers all over the internet.
Let's focus on the inspector.
Custom Inspectors and Property Drawers
Custom Inspectors and Property Drawers are types of scripts that allow us to customize the Unity Editor. The differences is that Custom Editors are used for MonoBehaviours and PropertyDrawers for any Serializable class.
If you create a standard C# class (as opposed to a Unity script that inherits from MonoBehaviour) you won't be able to see it in the inspector unless you make it Serializable.
That's easy, you just need to add a line just before your class definition:
[System.Serializable]
public class FrameChecker...
Note that as this class is not a MonoBehaviour you can't add it directly to a GameObject, you'll need to add it as a property in a script that inherits from MonoBehaviour.
If you made the class Serializable you can now see it in the inspector as a list of it's public properties. Making a Property Drawer will allow us to customize that.
You can make all sort of crazy things with Custom Editors and Property Drawers, but what we want today is this:
To create a basic Property Drawer we need to do the following:
Make a new class (I'll call it FrameCheckerDrawer)
Make that class inherit from PropertyDrawer
Declare an Attribute to let Unity know which class this PropertyDrawer is for.
Attributes are the things we declare inside square brackets, in this case it would be
[CustomPropertyDrawer(typeof(FrameChecker))]
Override two methods: OnGUI and GetPropertyHeight. The first one is where we draw the inspector, in the second one we let Unity know how much space it will occupy.
So let´s see how that would look before we start actually coding the thing:
using UnityEngine;
using UnityEditor;
[CustomPropertyDrawer(typeof(FrameChecker))]
public class FrameCheckerDrawer : PropertyDrawer {
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) { ... }
public override float GetPropertyHeight(SerializedProperty property, GUIContent label) { ... }
}
Let's determine the height first. If you check the image above you'll see that we have basically 4 rows:
The name of the property (Frame Checker)