If you check the older versions of my ‘MultiTag’ class I had a static method on it to test if a string passed in was a valid tag. This was to be used to validate tags, but because Unity has no way to get the list of known tags at runtime, I never really implemented the method. Instead the method just returned true if the string wasn’t null or empty.

Well last night I wanted to make a class that could be used to represent a mask for tags. Similar to LayerMask, it could be used to test if a GameObject contained one of any tags. Of course this could be remedied by just an Array/List of acceptable tags, but it didn’t make for a nice look in the editor. Furthermore I wanted a nice class to represent it with for cleanness sake (well I wanted a struct, but had to settle for class). This also meant that I could validate the tags being added to the mask as well.

Here’s the thing I noticed. You can set the tag of a GameObject to anything that isn’t a known tag. Otherwise Unity throws an exception saying the tag is not defined. This annoys me because there’s no way to test otherwise, except to just catch the exception at time of setting. There was really my sole motivator. I think it’s ballocks unity does offer it by default. It’s not like this takes up a whole bunch of memory or anything.

The idea is that we just have a ScriptableObject, on which I create an array, and fill it with the names of all the tags. I’ll store an instance of that ScriptableObject in the root Resources folder, and consider it a singleton (though there’s no true enforcement of that, as I can’t stop you from creating copies of the file). I keep it there so that it can be loaded at runtime no matter what. I use the same folder for things like GameSettings and the sort as well. You’ll notice that I make the collection of tags available as a ReadOnly collection, this is because the tags can not be modified at runtime, so I don’t want to even make that optional. I’m a stickler for encapsulation.

Thing is, this only gives us a place to store the tags. I have to fill the tags as well, and I don’t want to have to hand modify it every time the tags are updated. So I hacked together an Editor script that compares the tags in my ScriptableObject to the tags in the TagManager. What I do is I hook into the SceneView.onSceneGUIDelegate event when the editor loads using the InitializeOnLoad attribute. Then every call to this event I check the duration since the last time I synced (I hard coded it to every 1 second) and compare the existing tags to what I have stored in my ScriptableObject.

The problem here though is that I wrote up TagData to be encapsulated. Furthermore I don’t have the SerializedObject during this event as it’s not occurring while having the editor focused on it. I could jump through some hoops to get the SerializedObject, or I just wrote an interface to allow the editor access to the encapsulated parts of the object.

I often do this, where I create a class inside some serializable object called ‘EditorHelper’. It acts as a wrapper around the desired type, and because it’s scoped locally to the class it’s in, it can modify private members. This does mean that at runtime someone could just instantiate one of these EditorHelper classes to do so, but I don’t consider this breaking encapsulation as it requires very explicit steps that are obvious to the programmer that they’re breaking encapsulation at that moment.

The class is fairly simple and looks like this:

You can see it in the context it is written here in the source:
SpacepuppyFramework – TagData.cs

So now the editor I write can easily create instances and modify it. I also added a ‘Sync’ button as well to manually call to sync if desired.

TagData_Inspector

Now at runtime all I have to do is access that ‘TagData.Tags’ property to get a list of all known tags. This can be used for validation purposes. Which I now implemented in my MultiTag class as well as my new TagMask class. Both of which are found in the frameworks source.

SpacepuppyFramework – MultiTag.cs

SpacepuppyFramework – TagMask.cs

SpacepuppyFramework – TagData.cs

SpacepuppyFramework – TagDataInspector.cs

Leave a Reply

Your email address will not be published. Required fields are marked *