Have you ever selected the wrong object in Unity by accident then moved/scaled/rotated it?
I know I have.
Have you ever moved/scaled/rotated an object in Unity to its perfect state then wondered, how the hell do I make sure no one (including me) accidently touches this thing again?
I know I have.
And thus quite early in my journey with Unity I was frustrated to no end with the lack of locking objects. Actually I should say the visible/easy-to-use mechanism for doing this since Unity might have some esoteric way I'm unaware of. I guess we could always just make sure that the selected objects are the correct ones and undoing mistakes isn't terribly hard (or terribly un-buggy but that's not for this post). I just like to code stuff. So let's see what we can do about it.
My first ever approach was creating a new custom inspector, what Unity tags a CustomEditor and calls an Editor, for the Transform component. This proved to be the easiest solution but fairly cumbersome and overly rigid so I scrapped that idea.
My second approach was creating a new MonoBehaviour for each transform component I wanted to lock and then tag it with the ExecuteInEditMode attribute. ExecuteInEditMode is a poor concept which is needed because of Unity's weak handling of the editing/runtime dichotomy. Also it comes with some unintended baggage and frankly I try to avoid it as much as possible.
I'm not going to elaborate on the actual component script here since the next approach is fairly similiar in concept.
My third iteration is the one I'm currently using and is the one I want to talk about in this post. Following my other posts, this puzzle is made of a few parts working in tandem to create uni... eh, harmony. But what are these puzzle pieces you ask?
First and foremost we need the data component which holds our cached values.
Next our system will need to somehow know which values are currently locked and which are free. I guess boolean flags are the simplest way to achieve this but I've actually opt to create enumeration flags (which proved useful for other things later on as well by the way).
And lastly we'll need to craft the component's custom inspector to actually enable our system's required behaviour.
For bonus points we'll also create a few utility scripts to aid us in generating locked entities and generally make it easier to support certain functions on the data. And finally I'd like to note that I have a few custom extensions for the transform component which shortcut the way values are set.
Let's start by implementing the basic and most straightforward requirement of the system; locking an entity's position.
And accompanying inspector,
Wow. That simple! And less than actually useful. Adding this to an entity in the game (notice how I keep calling Unity's GameObject an Entity, right?) will just lock it to the scene's origin at the zero position. Not quite what we wanted. But at least the system is working, the entity has become immovable and all is good in the world. Well, besides everything locked to zero :P
Before going on and finishing this post I'll just point attention to the OnSceneGUI() method. I'm using this rather than the normal OnInspectorGUI() method since the latter is NOT called when the component is folded or hidden in the inspector panel while the former certainly is. And the fact I'm locking local positions rather than global, this is done to avoid unintended behaviour when locking transforms in a hierarchy.
The next post will be the final post (hopefully) with us implementing a more robust solution for customizing locked values as well as allowing users to lock/free components easily during scene editing.