Enforcing a Min/Max Relationship


Let’s now use what we’ve learned and what we’ve got to make sure our max angle is always greater than our min angle. We’ll do that whenever either value’s field loses the focus, again with the BlurEvent we’ve used before. But, we’ll need direct access to both the minAngle and maxAngle fields of the AnglesCustom component we’re editing. That’s partly done by binding the two FloatFields we used in the UI Builder to those fields of the component. It’s also partly done by obtaining a reference to the AnglesCustom component itself.

We do that second part in the OnEnable method of our CustomInspector, by using the inherited target member field of the Editor class:

    AnglesCustom anglesCustom;

    void OnEnable()
    {
        anglesCustom = target as AnglesCustom;
    }

When that code runs, target has the reference we need. It’s of type Object, so we need to convert it to an AnglesCustom reference. After that, we’ll have direct access to the fields of the AnglesCustom component we are editing.

In the UI Builder, be sure you name your two FloatFields “min” and “max,” so the code below can query fro them and get references to them.

In our CreateInspectorGUI method, we’ll get references to the two FloatField’s, and register BlurEvent callbacks for each of them:

        FloatField minField = root.Q<FloatField>("min");
        FloatField maxField = root.Q<FloatField>("max");

        minField.RegisterCallback<BlurEvent>(OnMinFieldBlur);
        maxField.RegisterCallback<BlurEvent>(OnMaxFieldBlur);

The BlurEvent handler methods are short and simple:

    void OnMinFieldBlur(BlurEvent evt)
    {
        anglesCustom.minAngle = Mathf.Clamp(anglesCustom.minAngle, -360, 360);
        anglesCustom.maxAngle = Mathf.Clamp(anglesCustom.maxAngle, anglesCustom.minAngle, 360);
    }

    void OnMaxFieldBlur(BlurEvent evt)
    {
        anglesCustom.maxAngle = Mathf.Clamp(anglesCustom.maxAngle, -360, 360);
        anglesCustom.minAngle = Mathf.Clamp(anglesCustom.minAngle, -360, anglesCustom.maxAngle);
    }

This is where, even in this short example, we can see the power of a Custom Inspector. Not only does it let us lay out our fields and resize them how we want, it can adjust any field in the component being edited, when a change in any other field requires it. Here, each method makes sure the entered value is in the allowed range of [-360, 360]. But, after that, it makes sure that if the minAngle value changed, the maxAngle value is not below it and, if the maxAngle value changed, the minAngle value is not above it.

Let Unity compile your new Custom Inspector and try entering values above and below the ends of the range (like -400 and 400). You’ll see them clamped to the allowed range. But, after that, try entering two typical values you might use, like -90 for min and 90 for max, then set the min to something greater than max (like 100, in this example). You’ll the max value is also set to 100. Now our Custom Inspector is making sure the developer can’t enter nonsense values, where the max is ever less than the min.

There’s a lot more to Custom Inspectors, but we’ll leave that for another set of tutorials. For now, we’ll get back to working on the CameraLander system itself. We know enough at this point about Custom Inspectors to be able to add one that handles all of our needs for the CameraLander in a graceful, sophisticated way. When we have it working, we’ll add that Custom Inspector then.

Leave a comment

Log in with itch.io to leave a comment.