Tuesday, May 11, 2021

Room Template UI Improvement

 

Poor programmers blame their tools for their mistakes. Great programmers build their own.

 

I've found myself picking up game development, putting it down, starting on a new project, picking up game development again, putting it down again, and on and on the cycle goes. This cycle has been going on for some time and I haven't really been sure why. It's almost like something was short-circuiting my flow state and making the entire experience dissatisfying.

Today, I came to the realization that all of the tools I have made are getting in my way.

Unity is a game engine in two parts: the designer interface and the scripting backend. The design side of making a game has enough information and enough niceties that a skilled designer can take art, scripts, and sounds, combine them all into a series of experiences, and end up with a polished product at the end.

Programmers, on the other hand, bury themselves in the code. The behavior of everything from enemies to GUI is their domain. Each and every thing

The problem when you mix these two workflows together is that they can sabotage each other. A programming task that wants feedback will have the developer jumping into the unity editor - design side - and immediately testing out what they have. This is great when everything is working smoothly, not so much when you have to figure out what you're doing every time. 

 Say you have a box like this:

This is the ugly cake room. I'd like to save this room for later; let's put it into a data structure called a Template so we can take it down and pull it up on a whim. How do we do that? By building an asset file out of it.

This is the inspector UI of a room template builder. Things are organized roughly in order, but it's hard to tell what's what at a glance, there's a bunch of useless information that the builder needs but the designer doesn't care about, and who can tell what template 2 exits to at all? I certainly couldn't.

This is actually the improved UI. The old one was worse... we'll just pretend that doesn't exist.

The template itself saves just fine. The UI on this asset is also kind of ugly, and it has no texture. Only the Unity default image.

Normally when I pull up an old project I'll get excited about some idea that I would like to try making and make it as fast as possible. I'll muddle through any weirdness in here, re-learning anything as I go along, getting used to the thing that I had made, and eventually just leaving with a feeling that I made what I wanted but something about the whole experience was off. 

Any time I would hit the UI I would already be in the mindset of "design" and not the mindset of "programmer". Everything I have built like this is built with knowledge of how it works in mind. There's no room for mis-remembering and if I showed a random person what this did, who knows? Looks like a bunch of text, some numbers, unsorted checkboxes, and buttons. Nothing really draws your eye to any part and the best you can do is "muddle through".

Switching from Visual Studio to Unity is like flipping a switch. One side is code, the other side is design. The designer in me is cringing at the programmer who just wants to get things done, and the programmer in me is getting frustrated at the ease of flow between prototyping, testing, and bugfixing. It's so bad that I'm repeating myself. 

If it's that bad, then I can certainly do something about it. What about this...


That's a LOT better. It's so much better that I'm surprised I didn't try this before. There's a large button to draw your attention, multiple buttons below it that are easier to navigate, the checkboxes for room exits are sort of in the same spot as the room connections, and there's a readout on the (now somewhat in order) location of the rooms in this template group.

The code for this is at the bottom of the post. It was tedious to write and was repetitive and fiddily. A lot of the code looks like this:

int spacer = 40;
for (int i = builder.foldoutConnections.Length - 1; i >= 0; i--)
{
    int y = i % builder.templates.y;
    int x = i / builder.templates.y;
    builder.foldoutConnections[i] = EditorGUILayout.Foldout(builder.foldoutConnections[i], "Template " + (i + 1) + " (" + x + "," + y + ") connections");
    if (builder.foldoutConnections[i])
    {
        GUILayout.BeginVertical();

        GUILayout.BeginHorizontal();
        GUILayout.Space(spacer);
        builder.connections[i * 4 + 0] = EditorGUILayout.ToggleLeft("Up", builder.connections[i * 4 + 0]);
        GUILayout.EndHorizontal();

        GUILayout.BeginHorizontal();
        builder.connections[i * 4 + 3] = EditorGUILayout.ToggleLeft("Left", builder.connections[i * 4 + 3], GUILayout.Width(60));
        builder.connections[i * 4 + 1] = EditorGUILayout.ToggleLeft("Right", builder.connections[i * 4 + 1], GUILayout.Width(60));
        GUILayout.EndHorizontal();

        GUILayout.BeginHorizontal();
        GUILayout.Space(spacer);
        builder.connections[i * 4 + 2] = EditorGUILayout.ToggleLeft("Down", builder.connections[i * 4 + 2]);
        GUILayout.EndHorizontal();

        GUILayout.EndVertical();
    }
}

Not bad for a bit of time in Unity's documentation on EditorGUI. I'm sure this can be improved; template connections would look nice in the same layout as a 2x2 grid with buttons instead of checkboxes... but that would take more than the 3 minutes I spent figuring out how to arrange them properly. I'll chuck it on the back burner for now.

What about the cake room asset?

Scriptable Objects automatically change their icon when their script is changed. This works well enough for differentiating generic objects. The templates don't particularly need an icon associated with each one... that will come later.

The main thing that's bothered me for a long time is the flow of loading up templates. You have to go to the template builder, type in the name of the template, and press load. This is more-or-less fine... is what I keep telling myself. I swear, on the blood of monsters and all that is worthy of derision, this problem is just like the other problems fixed today: it's tedious, irritating, and why did I put up with it this long?!

Let's just load the asset directly from its display.


It would also be nice to preview this template without needing to load up a scene dedicated to editing them. That's... going to come later. The button will eventually bother me enough that the feature will get built, and the button can just exist for now.

Here's a lesson in being lazy: The GUI elements are in the correct spot and I'm too tired to get this done in one day. Things are arranged in quite a bit more readable fashion, so it's good enough for now. Plus anyone who looks at this can ask why there's a bunch of TODOs staring them in the face.

There's been quite a few changes in all of this. I just need to test everything out to make sure that nothing is broken and...


I forgot to save the rotation of the tiles in this template. There wasn't any code to save the rotation when I started on this trip. I just wanted to make some nice rooms so I could take this idea of building a dungeon of cards and protecting the mDiyo workshop from a whole ton of slimes crawling on every wall they can touch.

This entire process is a lesson in Yak Shaving that turned into the primary goal. I'm not sure exactly how I feel about that, but it feels good enough for one day.


Anyone who wants to peruse my code can take a look at pastebin. TemplateBuilder needs to be attached to a GameObject; everything else should work as-is.

TemplateBase
Template
TemplateMaster
TemplateEditor

Template Builder
Template Builder Editor

No comments:

Post a Comment

Self Reflection, Avatar Reflection

It started as a joke. One day I decided that my game development was going poorly because I was too attached to my characters. If I messed a...