05 August 2021

Game Object Parents and Killer Kangaroos

Back in college there was a bit of programmer lore about some engineers working on a helicopter flight simulator for the Australian Air Force. As the story goes, they decided to save time when adding herds of kangaroos by inheriting the behavior of infantry units that were already in place, just tweaking the movement speed a bit.

Apparently this all worked fine right up to the point where they were showing off the new simulator to some visiting pilots, when the kangaroos sprang out and plastered the helicopter with ground-to-air missiles.

Now I’m not really sure how much of the story is true, but it illustrates how complex behavior can be shared among different types of objects quickly and easily (sometimes even too easily) by using a Parent → Child relationship. Just remember:

With great power...

Organizing your objects together into families is a powerful way to make your game logic simpler and quicker to build. Using parent & child relationships can drastically shrink the number of behaviors and messages needed for your game. And less game logic means your game is faster to build and easier to update in the future.

There are two primary ways that using parents can simplify your game. Behavior logic is inherited by child objects, so that the shared behavior only needs to be added and updated in one place and is shared by all children. Parent relationships can also greatly simplify selecting objects for collisions, proximity checks, raycasts, or messages.

Inheriting Behavior

Often when building a game, I’ll discover that many different types of objects will share much of the same logic. For example, a game might have enemies that can all damage the player, and they might also all have health that the player or environment can deplete.

When faced with a situation like this, it often makes sense to create an object type called Enemy, where I can place all the common behavior to be shared by all the enemy types. This Enemy object type will not be added to any levels, and will only be used to share logic among all the various enemies in my game.

I can then create various enemy types, for example a Ghost, a Skeleton, and a Slime, and each one would have it’s Parent set to to Enemy.

Selecting a parent is easy, just edit the object and choose a parent object in the dropdown:

Set the parent

Now the Ghost will run all of its parent object’s logic before running its own. Any logic that should be shared among all the various enemies can now go into the Enemy object type, where it will be automatically shared with all of the children.

Simplifying Object Selection

Another great use for parent & child relationships is to simplify target groups of objects at once for collisions, raycasting, or sending mesages.

Using our previous example, lets say we want to reduce the player’s health each time he touches the Ghost, Skeleton, or Slime objects.

The typical solution would be to add three different Collision triggers, one each for the Ghost, Skeleton, and Slime. But because these objects all share a common parent of type Enemy, then we can use a single Collision trigger block, select Enemy as the type, and the trigger will activate when the player touches any object who has an Enemy ancestor.

Because there will normally be many of these types of interactions in a game, the savings can add up quickly.

As we’ve seen, choosing the right parent objects can both simplify your game logic and reduce the total amount of logic you have to build. This in turn helps speed up development and keep your game organized.

Of course, it’s possible to over-use inheritance as we saw with the kangaroos, but if you keep an eye out you can often win some quick and easy improvements by taking advantage of object parents.