In this series we'll be diving into the basics and learn the building blocks to get started with Unreal Engine.
Ultimately we'll be building the example first person shooter that you see here and that comes with Unreal as a template in order to understand how everything is put together.
First lets break down some basic terminology that Unreal uses.
A Pawn is the base class of all Actors that can be controlled by players or AI. A Pawn is the physical representation of a player within the world.
An Actor is an object that can be placed into a level. It's a generic class that supports 3D transformations such as translation, rotation, and scale. Actors can also be thought of as containers that hold special types of Objects called Components.
A Component is a special type of Object that Actors can attach to themselves as sub-objects. These are useful for sharing common behaviors, such as the ability to display a visual representation, play sounds.
Jumping into our project we'll open our C++ character class to understand how these building blocks are used. In our Character header file we see that our UEFpsTestCharacter class inherits from ACharacter. We know that ACharacter is an Actor class because of the `A` prefix.
Ctrl + click into the ACharacter class and we see that APawn is inherited by ACharacter. We can see in the Pawn header file on line 31 that this is the base class for all actors that can be possessed by a player as we mentioned previously.
Back in our UEFpsTestCharacter.h file we see different components. We see USkeletalMeshComponents for the first person body and the skeletalMeshComponent to hold a gun.
We also see USceneComponents and UCameraComponent which we will attach our camera to so the player can see from the perspective of the character.
Next we'll dive into the building blocks for controlling the rules and states of the game.
The PlayerState is an individual player’s state such as score and health.
PlayerController - interface between the Pawn and the human player controlling it. The PlayerController essentially represents the human player's actions.
The PlayerController persists throughout the game, while the Pawn can be transient. For example, in deathmatch style gameplay, you may die and respawn, so you would get a new Pawn but your PlayerController would be the same.
GameState - Tracks the game information. Such as game duration, state of each player, score, etc.
For example if you wanted to track the game state of a counter strike match. We would track which round we’re on, number of rounds each team has won, time left in current round, whether bomb has been planted and so on.
GameMode - Combines GameState, PlayerController, PlayerState, Default Pawn, HUD. Determines the rules of the game.
Extending our previous example of counter strike, our GameMode would determine the rules for whether we’re playing bomb defusal, hostage rescue, or team deathmatch.
Two types of macros exists. Object-like macros and function-like macros. In C++ macros are treated as a token and are substituted early in the compilation process. Ex: repeating sections of code can be abstracted into a preprocessor macro.
Unreal Reflection System - ability of a program to examine itself at runtime.
There is a great UE4 blog post by Michael Noland that describes in detail how the reflection program works. The link is included in the description. https://www.unrealengine.com/en-US/blog/unreal-property-system-reflection
With our reflection system in place we can discuss a few of the most common UE4 Macros. The majority of these macros are used for passing meta data to the Unreal Header Tool (UHT).
*UPROPERTY* - allows a variable to be replicated, serialized, and accessed from blueprints.
*UFUNCTION* - allows a C++ function to be exposed via the UE reflection system and ultimately called from blueprints.
UCLASS - generates reflection data for a class. The class must derive from UObject.
GENERATED_BODY - UE4 replaces this with all the necessary boilerplate code that gets generated for the type.
As you get started with UE4's C++ you can utilize the C++ cheat sheet from UECasts at https://uecasts.com/resources/unreal-engine-c-plus-plus-cheat-sheet. You'll find the most common UPROPERTIES and UFUNCTIONS as well as other naming and coding standard tips.
Back in our UEFpsTestCharacter.h file we can see the macros we just discussed. First our UCLASS with the metadata setting config=Game as well as our GENERATED_BODY() macro that will create all the boilerplate needed for our class based on it's type of ACharacter.
Now we see multiple UPROPERTY's specificying `VisibleDefaultsOnly` which means it's visible in all property windows for archetypes but can't be edited.
A few other properties like `BlueprintReadOnly` which allows us to read the value in blueprints but not modify it.
We also see `Category = Camera` and `Category = Mesh`. This exposes the variable under the Camera or Mesh category within Blueprint Editor UI. Categories can also be nested with the pipe `|` operator.
Jumping further down we can see our UFUNCTION macro. This exposes the `CaclulateDamage` function to be called from blueprints.
Categories help you find our properties when editing our classes. Under `details > Camera` we see `Base turn rate` and `base look up rate` which we can see defined in our Character header file as visible but read only. We can also see our `gunOffset` variable is under the gameplay section as defined by our UPROPERTY.
Live Coding (Experimental)
A great new feature in Unreal Engine is the LiveCoding feature. Which allows you to update code and see changes immediately in the editor even while running the game in the viewport.
A few limitations do exist. Currently as of UE 4.24 it is only supported on Windows.
LiveCoding allows you to modify code that controls logic it does not allow you to modify data created by code. Which means anything in header files and thus UPROPERTY's or UFUNCTION's can not be modified via LIveCoding and requires a engine rebuild. In order to recompile and apply the patch we'll use the hotkeys `Ctrl + Alt + F11`.
First to enable LiveCoding ensure that you're running the UE Editor from your IDE. For visual studio we'll click `Local Windows Debugger` to start the editor for our project.
Once the editor is loaded. Click the Compile dropdown and enable Live Coding (Experimental).
Once enabled hop back to Visual Studio and we'll test out live coding with a simple logging to the screen.
In our Character header file I've previously added the `#include "Engine/Engine.h"`. If we click into this file and scroll to the very bottom we will see a global pointer for Unreal Engine called `GEngine`. This can be null so whenver you're using it you need to ensure it's valid and not null.
Back in the Character.cpp file in the OnFire method we'll add simple logging logic to see how LiveCoding works. Again since GEngine may be null we'll add a null check and then use the `AddOnScreenDebugMessage` method. Passing `-1` to ensure we always have a new message instead of overwriting existing messages, with a display time of 2 seconds, the color set to White, and finally the message of `"Hello from live coding"`.
Now using our hotkey combo `Ctrl + Alt + F11` we'll build a patch with the latest changes that will automatically load in the UE editor. Clicking play we can see our messages in the top left of the screen. Next while the game is still playing we'll update the message and again use our hotkey combo to build a patch. Once patched we can see our message now shows the latest message we modified in real time.
Now that we have an understanding of the basic building blocks in Unreal Engine we'll tackle creating the FPS demo from scratch in the next video.