Gamasutra: The Art & Business of Making Gamesspacer
View All     RSS
April 28, 2017
arrowPress Releases






If you enjoy reading this site, you might also want to check out these UBM Tech sites:


 
Unreal Engine 4 Programming API Fundamentals
by Daniel Adamitskiy on 01/12/15 07:09:00 pm   Featured Blogs

2 comments Share on Twitter Share on Facebook    RSS

The following blog post, unless otherwise noted, was written by a member of Gamasutra’s community.
The thoughts and opinions expressed are those of the writer and not Gamasutra or its parent company.

 

Unreal Engine 4’s programming API can be quite challenging to tackle if you are new to the programming side of the engine or just new to the engine in general. In addition, finding the information needed to answer specific questions can sometimes be difficult because of the massive documentation and forum questions that may not fully answer your specific question or the lack thereof depending on the question. This article will help to alleviate some of the many questions that can come up in the early stages of learning the API.

A great place to start is by opening up one of Epic’s provided code templates. When you open it, a few things may stand out to you that are different from regular C++ coding standards such as:

  • .generated file included at the top of a header(.h) file
  • A PROJECTNAME_API within the class declaration
  • Prefixes to class names ( i.e. AClass, SClass, UClass )
  • Tons of Macros ( i.e. UCLASS( ), UPROPERTY( ), GENERATED_BODY( ) )

These are some of the more basic API things that every person that wants to code in the engine should know and understand before they dive into making games. So let’s break all of these down.

.generated Files

Starting from the top of the list, .generated files are separate files that Epic’s Unreal Build Tool will create and link to your class by including it within the header file. Essentially, each .generated file is a boilerplate that the tool will create. Note that just like the header comment at the top of each .generated files states, these files should not be manually changed. Instead, changes to the corresponding header file should be made. Once the changes are made, recompile the code so that the Unreal Build Tool can modify the file as needed. Now, not all classes will contain a .generated file. Only those that are created in the engine by the Add Code to Project button under the File menu will receive one as long as a base class is specified. Otherwise, a .generated file will not be created.

PROJECTNAME_API

Within some of the class declarations, it’s quite common to find a PROJECTNAME_API. If you hover over it, you’ll notice that it’s actually a #define. If you attempt to go to its definition however, an error should occur as Visual Studios cannot find the #define in a source code file. This is because it’s actually defined on the command line by the Unreal Build Tool. At compile time, one of three things will occur with said #define. In DLL modes, the #define will be declared as either a DLL import (__declspec(dllimport)) if there’s another module that is being compiled and depends on the current module, or DLL export (__declspec(dllexport)) if the current module is being compiled. If it’s in monolithic mode, it will be declared as empty.

Prefixes to Class Names

One of the many things that can catch your attention are the letters prefixing class names. If you go into the editor and add a new class in, you will occasionally find that a letter was added to the beginning of the class name due to Epic’s coding standard. As the coding standard describes:

  • Template classes are prefixed with the letter T.
  • Classes inheriting from UObject are prefixed with the letter U.
  • Classes inheriting from AActor are prefixed with the letter A.
  • Classes inheriting from SWidget are prefixed with the letter S.
  • Abstract interface classes are prefixed with the letter I.
  • Most other classes are typically prefixed with the letter F.

The engine will automatically add prefixes to classes that inherit from Object, Actor, and Widget when created. The remaining three are standards that Epic has set forth in order to ensure written code will stay consistent.

Macros

Macros can be found in many places within code. Some of the more important basic ones include:

  • UCLASS( )
  • USTRUCT( )
  • UINTERFACE( )
  • UFUNCTION( )
  • UPROPERTY( )

For those that have a good grasp on how general code structures work in C++, these structures work almost identically aside from a few minor additions. Essentially, using these macros helps to greatly simplify the process of declaring things such as classes, structures, interfaces, functions, and properties within gameplay classes. Declared directly before whatever the macro is referencing, they may left blank or filled in with in with varying specifiers and metadata. Potential macro declarations may include:

  • UCLASS( Blueprintable ) 

This exposes the corresponding class to be a base class when creating blueprints.

  • UFUNCTION( UnsafeDuringActorConstruction )

Signifies that the corresponding function is unsafe to call when this Actor is constructed.

  • UPROPERTY( EditAnywhere )

The corresponding property can be edited in a property window in the editor.

These cover only a few of the many options that UE4 offers. Due to the large amount of possible specifiers and metadata that can be contained within one of these macros, I will not go through every single one, but rather provide a link below to a page in UE4’s official documentation. This page briefly goes over some gameplay programming references and links to multiple pages that cover all possible specifiers and metadata.

Link: https://docs.unrealengine.com/latest/INT/Programming/UnrealArchitecture/Reference/index.html

The last set of macros that are necessary to understand when starting out with the API are:

  • GENERATED_BODY( )
  • GENERATED_UCLASS_BODY( )
  • GENERATED_USTRUCT_BODY( )
  • GENERATED_UINTERFACE_BODY( )
  • GENERATED_IINTERFACE_BODY( )

Each of these macros corresponds to one that was discussed earlier. Whenever a UCLASS( ) is declared, there needs to either be a GENERATED_BODY( ) or a GENERATED_UCLASS_BODY( ) directly following the class brackets. Understanding which macro to use depends on which version of the engine you are running. In the current 4.6 version and the coming 4.7 version, if the class requires a constructor, using a GENERATED_BODY( ) is the preferred method. You can also use GENERATED_UCLASS_BODY( ) which was primarily used in versions prior to 4.6 when needing a constructor, but this is being deprecated in 4.7. It’s important to note that using either of these two macros in 4.6 and the GENERATED_BODY( ) macro in 4.7 will require an overloaded constructor. This constructor will pass in and FObjectInitializer reference and should look very similar to this:

AClass::AClass(const FObjectInitializer& ObjectInitializer) : Super(ObjectInitializer)
{
}

The purpose of this overloaded constructor is to ensure that each instance of the class gets constructed with initialized properties. Much like a class, a USTRUCT( ) should contain a corresponding GENERATED_USTRUCT_BODY( ), however, structures do not require an overloaded constructor. The final two macros are used together to create an interface class. The GENERATED_UINTERFACE_BODY( ) interface will inherit from UInterace. The interface class is then created with GENERATED_IINTERFACE_BODY( ) contained inside of it. In addition, all of the interface properties and functions will go into this second class. Here is what it would look like in code:

#pragma once

#include "Interface.h"

// When creating the class in the editor, select Object as the base class.
#include "ClassInterface.generated.h"

UINTERFACE(MinimalAPI)
class UClassInterface : public UInterface
{
	GENERATED_UINTERFACE_BODY()
};

class PROJECTNAME_API IClassInterface
{
	GENERATED_IINTERFACE_BODY()

	// Place all interface properties and functions here.
};

While having only scratched the surface, the contents of this article should provide a good understanding of many of the fundamentals necessary to begin working with the Unreal Engine 4 programming API.


Related Jobs

Disruptor Beam
Disruptor Beam — FRAMINGHAM, Massachusetts, United States
[04.28.17]

Senior Data Analyst
Charles River Analytics
Charles River Analytics — Cambridge, Massachusetts, United States
[04.27.17]

Software Engineer
HERE
HERE — Carlsbad, California, United States
[04.27.17]

Senior C++ Engineer, 3D Rendering
Woodbury University
Woodbury University — Burbank, California, United States
[04.26.17]

Game Art and Design Adjunct Professor





Loading Comments

loader image