Now that you've had a month to digest part one of Sentura's dive into the lovely world of Unreal Engine 4, it's time to get your teeth into the second part. This time, discover the wonders of debugging, comparisons, and casts. Also, feel free to use the comments to ask further questions about this tutorial or Unreal Engine 4 in general.
Picking up where we left off, let’s take a look at debugging, comparisons and casts.
There were some issues with our door example in Part One, which I glossed over for the sake of simplicity. Now, however, our door should serve as a useful example of how to debug blueprints.
The problem was that our door didn’t really open properly, as seen in this image:
Let’s figure out what’s wrong with some debugging.
There are many methods of debugging blueprints, of which Breakpoints are the most common. Setting a breakpoint stops execution of your game momentarily, allowing you to inspect the nodes of a blueprint graph. This is tremendously useful for squashing any troublesome bugs.
Breakpoint debug steps:
- Add a breakpoint.
- Play and execute the event (the game pauses and focuses on your breakpoint).
- Use the step button to go through the execution step by step.
After a few steps in our door example, we see that both of our events are being triggered repeatedly. We can also hover over any variables and parameters to examine their specific values at the time of the break.
Another method of debugging is to split your screen (or simply use two monitors), separating the blueprint window from the game window. This helps track what’s going on in the graph as you walk through your door. This way, we can see the exact point the execution reaches while we play the game, although we aren’t provided with any additional information.
Notice that the drop down menu next to the play button in the blueprint graph window needs to be set to our specific door in order for it to display any information about the door.
Both of these debugging methods help us trace the root problem with our door example: events are registering repeatedly, causing the door to behave erratically. One guess as to why this may be occurring, is that some native player character components are interfering with the door blueprint by forcing it to register more than one actor.
How can we single out an object or actor to ensure that it’s the correct target of a sequence? How can we ensure that any given object or actor is actually the intended type, in order to avoid problematic misidentifications? These are questions which can be answered using comparisons.
Comparisons are, just as the name implies, a way for us to compare objects in order to determine whether or not they are alike. UE4 determines the result of this comparison with a boolean value – either the objects are the same (a boolean true value) or they are different (a boolean false value), and we can then use this boolean as an indication of what to do with our door. In UE4, conditions are done through the branch node.
The node used for comparisons is called “Equals”. Note that there are several versions of the “Equals” node, as it can be used for almost all possible variable types.
Now that we have our Equals nodes, we want to make sure that they are configured correctly. Each event needs an equals node, taking the ‘other actor’ parameter and comparing it with the player controlled pawn – our First Person Character actor. While you can link the First Person Character actor through other ways, doing it this way ensures that even if we change the player actor to something else, the door condition will still hold true.
This solution wraps up nicely and leaves no room for error. But it is also somewhat limited: What if we also want to make potential enemies pass through the door?
Casting is a term originating from the computer science concept of polymorphism. In short, polymorphism is about class relationships, and how some classes may have a more generic version of themselves stored to use for implementing a variety of classes within the same skeleton. The generic class is called a superclass, whereas the class inheriting data from the superclass is called a subclass.
The classic example of this is that a Car subclass would have a more generic Vehicle superclass. In games, this idea is even more widespread: we could have a Weapon superclass able to shoot and reload, but what happens when the weapon shoots and reloads would be up to the subclass. An RPG subclass would naturally have a different implementation than a SMG subclass, although it would share attributes like ammo and functions such as shoot or reload. Subclasses still have their own independent functions alongside inherited functions.
How is any of this relevant to Blueprint? In short, a subclass inherited from a superclass may be targeted through its superclass. If you cast to a Weapon superclass, then any of Weapon’s subclasses can pass through as well.
Let’s tie all of this together: using the superclass of First Person Character Character, we could ensure that all classes inheriting from Character are able to use a door as well – including our currently nonexistent enemy characters.
There is a caveat: casts are performed during runtime. This means objects or actors which cast incorrectly could crash or otherwise break your game. For a more technical understanding of why casts should be used carefully, I recommend this article: http://stackoverflow.com/questions/4167304/why-should-casting-be-avoided
So far, we have only briefly touched upon the concept of polymorphism, but it is one of the most important concepts within an object oriented programming paradigm such as Blueprint, and a great tool for creating system architecture (including system design).
There is no article for polymorphism in UE4, and I’m tempted to write a comprehensive guide. In the meantime, you could take a look at this short video explaining the concept more thoroughly:
Video no longer available on youtube
In the third and final article in this series, we’ll implement a grenade weapon (using some polymorphy) and a grenade throwing mechanic using Bezier curves.
See you then!