Dev Log

Unity3d, Dev Log Jeremy Wolf Unity3d, Dev Log Jeremy Wolf

The State Pattern

Whoa. It’s been nearly a year since I’ve made a post. I’ve been busy. A lot has happened, but that’s a topic for another post.

So I’m going to try something new, well a few things. But the first thing I’m going to try is writing a blog post for my next video. I figure taking the time to explain the video in writing will help me cement the ideas and provide one more resource for you all. There are many people who’d prefer to read than to watch a video. So maybe it’s a win-win? We’ll see.

But enough of that. Let’s get onto the second new thing.

That’s is exploring programming patterns. It’s something I’ve wanted to do because I want to learn more about programming patterns. Plus Bolt 2 will eventually (!!) get released and when it does many of the basic programming patterns will be far easier to implement AND folks developing with Bolt can benefit from implementing them.

Since Bolt 2 is now fully in hiding under the protection of Unity (who knows when the alpha will make it out to the public again) the upcoming video will be entirely C# based.

I should also give credit where it’s due. I’m no genius - that should be clear if you’ve read more than a few paragraphs of my writing. Much of what I know or think I know about programming patters comes from the book “Game Programming Patterns” by Robert Nystrom. It’s well worth a look if you are unfamiliar with the topic of programming patterns..

The State Pattern

“Allow an object to alter its behavior when its internal state changes. The object will appear to change its state.”

Like any other pattern the State pattern has its limitations, but also like any other pattern when used correctly it can help to detangle code which can make debugging code or adding features easier and much less frustrating. And that’s a win no matter how you look at it.

You may have heard the term “Finite State Machine” or “FSM” thrown around. Both of these terms refer to the same thing which is an implementation of the state pattern. The Unity asset Playmaker is based on the uses of FSMs and Bolt has the ability to create them with “State Macros.”

To help illustrate the state pattern, I’ve created a simple Unity project. There is a NPC played by a capsule and it’s goal is to wander around the maze and collect the yellow cubes. When it sees a red sphere (critter) it will chase it and attack it. Nothing too fancy.

So with that in mind, how would you program this behavior? Take a minute and think it through. No cheating!

Just about ready to go up on steam! ;)

Just about ready to go up on steam! ;)

This actually doesn’t look too bade with the use of functions… but will get out of control in a hurry.

This actually doesn’t look too bade with the use of functions… but will get out of control in a hurry.

I know when I first got started with C# and Unity, I would have done it with an if statement or two (or seven). And that works. It really does. Until you need to add another behavior. Or another game mechanic gets layered in. And we all know it won’t end there. The layers will continue to get added until the code breaks, bugs appear or the project gets forgotten because it was getting too hard to work with.

Simple FSM = Enum + Switch

So let’s look at the simple FSM. I still remember learning about this and was utterly confused by how to implement it but at the same time amazed at what it did to my code once I finally got it working. At that time I hadn’t really learned to use functions well so I had 100’s of lines in my update function. Needless to say it was nearly impossible to debug and when I discovered FSMs it was a major break through!

Simple FSM using an ENum and a Switch

Simple FSM using an ENum and a Switch

In the case I described above the NPC behavior can be broken down into 3 different states or 3 different smaller behaviors. I thought of these as wander, collect and attack. A custom enum can then be created with these three values.

With the enum created a switch statement can be placed in the update function. For each case we can call the relevant function for that behavior. But we still need a way to change or switch (get it!) the state. For the most part this can still be done with basic if statements.

And now this may sound like we’ve back pedaled to our original solution and just made things more complex.

But!

There is a major advantage here!

When we started, inside the update function we had to have a way to determine which state we were in - picking from ALL the possible states. Imagine how complicated that would be if there were 5, 6 or maybe even 10 different states. Yuck! Nothing clean about that.

With this method we only have to decide IF we need to change states GIVEN that we are already in a particular state. This greatly simplifies the decision making albeit at the cost of a few extra lines of code.

In a FSM it’s common that a given state can only transition to a limited number of other states. For example in my case maybe I don’t want the NPC to stop collecting if it sees a red sphere and it should only attack a sphere if it’s wandering around with no cubes in sight. If that’s the case the “state pattern” may actually reduce the amount of code needed as well as serving to untangle the code.

This implementation of the state pattern can be used for all kinds of different behaviors. It could be used to control animations, background music, or which UI elements are being displayed. 

As an aside, in my personal project, I use a vaguely similar approach that makes use of a static enum and events for game modes so that various managers and UI elements can act or react based on the state of the game. The clarity of being in exactly one state has greatly simplified my code and made it far less error prone.

So this is all well and good, but you may be able to see the end result of this approach is still messy if the number of states starts to get large.

A Step Further => More Abstract + More Manageable

Having all the states switching inside the Update function can quickly get unmanagable and if nothing else is pretty hard to look at.

So let’s go one step further. This step adds another layer or two of abstraction to the system, still has some downsides but does clean up our code and will make larger FSMs easier to manage.

This step will place each state in its own (mostly) self contained class. The state will be in control of itself and will determine when to make a transition as well as determine which state to transition to.

Interface.png

Step 1 is to create a new interface. In my case I’ll call the interface INPCState. The interface will have just one function that will take in all the NPC data and will return a value of the type INPCState. This returned state will be the state for the next frame as the “Do Action” function will be called by the base class of the NPC which in turn will run the behavior for a given state.

The Wander State with all the functions included

The Wander State with all the functions included

Step 2 is to create a new class for each state of the FSM and that state needs to implement the interface INPCState. Each of these classes should also contain any functions or logic needed for that state. In my case I have choosen to leave all the variables on the NPC base class. This keeps each state class tidy, but does mean that the state class will be changing values on the NPC base class which is usually something I like to avoid - you win some and you lose some.

Inside each state’s “Do Action” function we need to call the relevant functions AND we need to decide which state to use for the next frame. You can see the full code to the left, but for now let’s jump back to the NPC base class which will help make sense of the return values.

Step 3 is to refactor the NPC base class. Here we need a new variable of the type INPCState that will hold a reference to the current state. We also need instances of each state - it would be possible to make this work with static classes and using an abstract class rather than an interface, but if you know what that means you can probably implement it yourself.

The simplified NPC Base Class

The simplified NPC Base Class

In the OnEnable function I’ve set the current state to the wander state to ensure that the current state variable is never null.

Then the real magic happens in the Update function. Here we have just one line! So awesome. Here we call the “do action” function on the current state and then set the current state to the value returned from that state.

That makes total sense, I swear it does, but it’s abstract.

Give a mintue to let it sink in.

This is so clean.

Step 4 is to add conditionals to the state classes to determine which state to be in for the next frame. Notice that we have passed in a reference to the NPC base class into the “Do Action” function and from there we can get a reference to the instances of the state classes.

Pro’s

The base class is exceptionally clean. You can now see how the class appears to change it’s state (behavior). Effectively the entire Update function changes depending on the current state and what in that state’s “Do Action” function. That’s cool.

If we want to add an additional state we simply create a new class, add an instance to the NPC base class and finally add conditions to allow a transition to the new state from other states.

As long as the number of states stays fairly small 5 or maybe 10 this is a pretty manageable solution.

Con’s

It’s hard to maintain if the system truly gets complex. In this case most sophicated structures such as behavior trees might be needed.

All the variables in the NPC base class are public. Which is a bit messy and not super awesome. This could be partially solved by creating a data container that itself is private in the NPC base class but has public variables… This passes the buck a bit, but would prevent those variable from being changed by classes without access to the data container. A generic data container would also potentially open the doors a bit wider for reuse of the states by other NPC types - so worth thinking about.

As mentioned before, the states are changing values of variables on the NPC base class. Not ideal and something I usually go out of my way to avoid if possible.

Read More
Unity3d Jeremy Wolf Unity3d Jeremy Wolf

Easy UI Styles for Unity

So like many of us when in the middle of the project it’s easy to get distracted and start building tools that probably take longer to create than the time the saved by the tool. And what do you know, a few years back I created Easy UI Styles…

I was finding it hard to iterate on my UI designs. I’d change a color here and it would look better, but then I’d need to change it 7 other places and then it was a tad or dark. Or a tad to light. Oh and then I wanted the font a bit smaller.

Ugh.

So Easy UI Styles let me define a style in a custom editor and then apply it object by object in the scene.

A little while back I started switching my project from UGUI text to Text Mesh Pro (holy crap it looks better) and Easy UI Styles didn’t support it. So down the rabbit hole I went! Several hours later the asset now supports 99% of the setting for Easy UI Styles - seemly there are 2 settings that can’t be set by an external script.

While I was at it I created a new video for the asset as well as a cut down free version of the asset. You can get the “Lite” version on the asset store once it’s accepted or until then you can download it here. The full paid version is free for my Patrons (wink wink).

Read More
Jeremy Wolf Jeremy Wolf

9th Grade Math to the Rescue

With summer here and my day job being a teacher I have a lot more time on my hands all of a sudden.

Nobody has told me to show up for work, so I haven’t gone for a while.

I’ve also intentionally taken a little break from cranking out YouTube videos. Lets be honest the $8 a month I’m pulling in on ads isn’t paying the bills or a reason to flirt with burnout.

This is letting me spend more time working on my personal project. Right now the game is functional, or rather it fluctuates between functional and broken as I write more code, but that’s a not the story I want to share.

At the moment, I’m in the middle of iteration 2 of 37 in terms of polishing and refining the game mechanics. I’ve been squashing bugs left and right while making bits smoother and easier to use.

As part of those iterations, I’ve been working on the UI. Trying to make it less ugly, which is very different from trying to make it look good, and adding “juice” where I can. The ugliest of all the UI at the moment and roughest in terms of functionality is the “combat selection” panel. I want the player to be able to click on a “tournament” and have that tournament be centered in a scrollRect (Unity). So, I did a little playing on my own and it “worked.”

I sure am liking quotes today…

But reaching for a slightly higher standard than just “working”, I decided to use the google and see if other folks had a slick way to make it work. I found posts and discussions, but it all seemed overly complicated. Why is this hard?

Okay yes, Unity’s UGUI system can be pretty opaque at times… but again that’s not the point. Stop distracting me.

And then! Just like each morning during the school year… I remembered that I teach math. And this is just a math problem! I also teach physics. So I figured I’d gather some data and model the situation

9th grade math to the rescue!

Whoa! A real life use of a linear equation.

Whoa! A real life use of a linear equation.

The complex problem quickly showed itself to be just a linear equation, the position is based on the number of children (tournaments) in the scrollrect, which is fixed, and the index of the child I wanted to center. This is of course based on the children all being the same size (width in my case).

For those following along, yes, I have three variables so no it’s not “linear” but lets not get too picky. Nobody likes to sit next to that guy at the party so don’t be that guy.

And yes, it’s very ugly, but it works. That’s good enough to call it a win!

Such beauty!

Such beauty!

This was a good reminder, that as helpful as the interwebs can be sometimes the solution you find is a hammer and your problem isn’t a nail. A couple deep breaths, a few trips pacing around the living room like a crazy person and you can often find a simple(r) solution to your problem. I’ve found that showering and pooping also work, but I didn’t need the big guns this time around.

Read More

Older Posts