fbpx

What is the update method design pattern? The update method behavioral pattern works with the game loop pattern and lets you manage the behavior of multiple game characters or items that each override a method called update.

If you’re building a game that has a fixed number of game elements or at least a fixed number at the start of the game and each one just sits there until one piece is moved each turn, then this pattern is not the best choice.

This pattern is perfect for an adventure game where the hero can stumble across a pack of wolves. Some of the wolves will rush the hero while others might try to circle around and attack from the rear. Or even if there are no monsters involved at all and the hero is just walking through town. Unless this is a ghost town, there should be other people and each character will be busy with personal tasks and errands.

Without this pattern, how would you manage all these diverse situations?

Maybe you could put four separate wolves in the game loop but this would quickly make a complete mess of your game loop. Not just with trying to keep track of each of the wolves but more importantly trying to keep track that there should be wolves in the first place.

If it wasn’t for the common application of this technique within game loops, this might not have ever reached the status of a design pattern. It’s really just a collection of derived classes that all override a method called update. What makes this a pattern is that you’ll likely need to do the same thing in any game that has multiple independent game characters.

The episode also describes three design decisions you’ll need to be aware of and gives you some guidance for ways to handle them.

  1. The game loop will call update on each game object one after another. Over the course of many frames, this has the appearance of updating each game object at almost the same time. This can cause problems though. Especially when the objects interact with each other.
  2. Anytime you have a collection that you’re iterating through, you need to be careful with modifying the collection while trying to visit each item in the collection.
  3. What’s the scope of the game object collection? You won’t be able to update every object in the entire game in every frame. So you need to plan carefully how to keep track of objects that are too far away to be of immediate concern. The problem though is that the objects could come back into scope and if you handle this wrong, then the game can seem fake.

If you’d like to read the book that describes this pattern along with diagrams and sample code, then you can find Game Programming Patterns at the Resources page. You can find all my favorite books and resources at this page to help you create better software designs.

Listen to the full episode or read the full transcript below.

Transcript

The basic description says that this pattern simulates the behavior of multiple independent objects by updating each one, one frame at a time.

We’ve actually finished going through all the patterns in the Gang of Four book. There’s a really good book called Game Programming Patterns by Robert Nystrom that I recommend that documents several more patterns applicable to game development.

If you’re building a game that has a fixed number of game elements or at least a fixed number at the start of the game and each one just sits there until one piece is moved each turn, then this pattern is not the best choice.

You might still be able to use it if the game pieces have some independent behavior. Maybe they randomly taunt the player or have some unique animation. But if they just wait for their turn to move, then this pattern is not the right choice.

This pattern is perfect for an adventure game where the hero can stumble across a pack of wolves. Some of the wolves will rush the hero while others might try to circle around and attack from the rear.

Or even if there are no monsters involved at all and the hero is just walking through town. Unless this is a ghost town, there should be other people too and each other character will be busy with personal tasks and errands.

Without this pattern, how would you manage all these diverse situations? Maybe you could put four separate wolves in the game loop but this would quickly make a complete mess of your game loop. Not just with trying to keep track of each of the wolves but more importantly trying to keep track that there should be wolves in the first place.

What we need is a way to treat each villain, each monster, and each town guard the same.

Then they can all be put in a collection of game objects and we can use polymorphism to call an update method on each one.

Polymorphism was explained in episode 25 about inheritance and overriding methods. I’ll explain it quickly here again.

You start out with a base class that declares a virtual method. In this case, that method will be called update.

Then in specific derived classes, you override the update method to do something specific for that derived class. Now, if you know that you have a pack of wolves to deal with and they’re all wolves, then this might seem like just some extra work with no benefit. But if the hero can get those wolves to follow him back to town, then maybe the guards will join in the fight. This is where polymorphism comes into play. By treating all the game objects as if they are all the same base class, then, when the update method is called it will be routed to the proper class type, either a wolf or a guard depending on the actual type of the instance.

Because a wolf and a guard might have different data members and occupy different amounts of memory, we can’t put them all in the same collection. Items in a collection need to all be the same. But we can put pointers to the base class in the collection. And that’s how polymorphism works. You have a collection of base class pointers that actually point to different derived classes and when you call a virtual base class method, then the appropriate derived class method override is what gets called.

Now that we have a way to treat game objects the same through a base class that defines a virtual update method, we can put any number of these game objects in the collection.

And this actually leads to an important benefit of this design pattern.

It allows you to load game objects as needed into the game. This allows you to control the game through a data file. The game designers can now specify a particular intersection of two roads in the forest and define that there should be some kind of encounter with one or more wild beasts. The game designers can make the actual type of creatures depend on the hero’s experience. At the beginning of the game, maybe the hero is attacked by a couple rats. And later, the same location might be populated with the pack of wolves.

There’s some more details about this pattern that I’ll explain right after this message from our sponsor.

( Message from Sponsor )

If it wasn’t for the common application of this technique within game loops, this might not have ever reached the status of a design pattern. It’s really just a collection of derived classes that all override a method called update. What makes this a pattern is that you’ll likely need to do the same thing in any game that fits the description at the beginning of this episode.

And because of this specific usage, there’s some other details you should be aware of.

Here’s three specific problems you’ll need to consider.

The first thing is that the game loop will call update on each game object one after another. Over the course of many frames, this has the appearance of updating each game object at almost the same time. It’s that “almost” part that can cause problems though. Especially when the objects interact with each other. Let’s say the first wolf gets updated and it checks where the second wolf is before deciding where to go next. The first wolf is looking at the location of the second wolf as it currently exists. Then the game loop updates the second wolf. Now, the second wolf will be basing its actions on the newly updated state of the first wolf. There’s a mismatch that can cause problems and the order that the game objects are updated can affect the outcome. This is a problem waiting to hatch into a bug.

You might be able to control this by using the double buffer pattern described in episode 82. If you take this approach, then the game loop first updates each game object but this update occurs in a private copy of each object’s state. This allows each game object to make update decisions based on a consistent snapshot of all the game objects. Once all the updates are done, the game loop can go through all the game objects again and call another virtual method to commit the changes. This swaps the buffers for each game object. If you don’t understand what I’m talking about, make sure you listen to episode 82 and then come back to this episode.

The next thing to be aware of is applicable anytime you have a collection that you’re iterating through and that’s the difficulties of modifying the collection while trying to visit each item in the collection.

Why would you need to modify the collection?

Well, at some point, the hero will hopefully destroy the rats or the wolves attacking the hero. Or maybe the hero is fighting an evil magic user who summons another creature to help fight. The point is that game objects can come and go and you need to handle this properly. Maybe you don’t include new game objects in the update method calls during the same frame that the new object appears. And for dead objects, instead of removing them from the collection immediately, maybe you can set a flag to remember the creature is dead. Then after all the active game objects have been updated, you can make another pass through the collection to remove or add objects.

The last thing to consider is the scope of the game object collection. A large game set in an open world is not going to be able to hold every single game object and even if it could, do you really want to be updating each one for each frame?

Some of the game objects might never even be encountered by the hero or maybe they’re far out of sight. In the real world, we all have our lives that we each experience in full detail in every moment. Even if we’re not aware of all this detail, it’s still there. This is the old problem that says “If a tree falls in a forest and there’s nobody around to hear it, does it still make a sound?” Philosophers have been debating this forever and the answer has little effect on our lives.

But the answer and actually the approach you take as a developer when dealing with this problem is very applicable to a game.

Why would you waste precious processing time simulating a frame by frame fall of a tree when the game character is nowhere around? Obviously you won’t.

But at the same time, if the hero spots a pack of wolves and decides to run away instead of fight, then what do you do when the hero visits the same spot again later? If the wolves are in the same spot several days later, then the game starts to lose a lot of the immersion qualities. It seems fake and boring. And the same thing can happen if the player decides to fight instead and brings the hero back just minutes later. In this case, the wolves had better still be there or the game will also seem fake and shallow.