Ink and Lines #1: Custom Unity Field Inspector


Ink and Lines is a game about censoring documents for an authoritarian government somewhat akin to that of 1984. The player is tasked with reading documents and censoring them according to strict rules laid out for them. When the player makes a mistake, they will receive a demerit. Three demerits in a day and its game over. 

The base logic for checking if the player followed the rules is simple, I go through a list of words and images for the finished document and check flags for each to determine if the item should have been censored and if the player did indeed censor it. But I'm likely going to be creating hundreds of documents for this project, so I'll need a handy way of quickly setting them up and marking which parts need to be censored. 

My system needs to be able to handle all kinds of documents, with multiple images and text fields in any arrangement. Sometimes images and text will be hidden on the margins, etc. I'm likely going to be hand crafting each document individually, so the fewer steps to encode the censorship requirements into them the better. 

Here's an example minimalist document. It's a UnityEngine.UI.Image with a TextMeshProUGUI element on top. Real simple. 



So next I create a DocumentTextElement that stores a list of the words in the textmesh and a list of enums of the same size. This component will live on the document gameobject. The enums will determine if the word at that index is supposed to be censored or not, and for what reason. It's essential to store the reason so that I can provide feedback to the player on which rule they broke. Provided the TextMeshProUGUI, I can have these lists auto-populate with each word and a default enum value of no rule broken. 

But how do I set the rules for the words that should be censored? I could use Unity's default inspector view of the lists and scroll through them and change the values in each list, corresponding it to the list of words, but that is obviously much too finnicky and prone to mistakes. 

I want to be able to just see all the words in order and tell what rule if any they have applied to them. Then by clicking on them I should be able to change their state. This is where the CustomPropertyDrawer comes in handy, as it will allow me to render the relevant data in any way I wish in the Unity Inspector. The base code for the class looks like this:

[CustomPropertyDrawer(typeof(DocumentTextData))] 
public class DocumentTextDataDrawer : PropertyDrawer {
    public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)     {
        //draw custom field! 
    }
}

The DocumentTextData is the class that holds the lists of words and enums, and is a serialized field in my DocumentTextElement monobehavior. Now inside OnGUI() we get the lists, and pass it to this method that draws the important bits:


The CleanseRuleId is the flag for the censorship rule, which has a None field by default. the if(changed) check is the logic that triggers when I click on the button in the inspector. Using a static value set elsewhere, I can easily change the rule that I assign. 

So now with this all set up I now see a new view in my DocumentTextElement component:


14 is just the number of words, which might not be terribly useful to display, but its there. Then you can see the words from our document in ordered buttons and all greyed out. That is the color I set for CleanseRuleID.None. I can change my current rule to assign in another component, and now when I click on the words it will change their rule enum value. 


It works! Some quick debug logging shows that the flags are indeed being set correctly.

 I can probably format the buttons a bit better, as you can see some words don't quite fit, but this works well enough for now. I have each rule color coded so that I can easily distinguish between them. So that should handle all the text components in my documents. The only other case will be images, which will be much simpler as I will be using individual components for each image, meaning it will be a simple enum dropdown box to select which censorship rule applies if any to the given image. No custom property drawers necessary!

My next post will be about how I handle the censoring interaction on documents, where I will dive a bit into the handy features of TextMeshPro. 

Get Ink and Lines

Leave a comment

Log in with itch.io to leave a comment.