Skip to content

Unreal Engine 4 Camera part 1: Create a basic C++ class

This article is the first part of the series on creating a C++ powerful camera for Unreal Engine 4. In this tutorial you are going to create your first C++ class, learn about variables, create components in C++, and load resources from the disk.

Making a basic camera blueprint

The strategy is at first to create a basic camera blueprint, then to replicate the same steps and logic in C++. The blueprint will act as some kind of model, guiding you to write the code.

Let’s get started. In Unreal Engine make a new Blueprint TopDown project you’ll name TopCamera. If your keyboard is not a QWERTY you need to set the correct keys in axis mapping in the input page of Project Settings.

Create a new Pawn blueprint in the Camera folderIn the Content Browser create a Camera folder and a new Pawn blueprint in it. Name it B_PlayerCamera.

Double click the B_PlayerCamera blueprint. In the Components panel add a Static Mesh, name it CameraTarget and move it to the root.

With CameraTarget selected head to the Details panel and assign Shape_Sphere to its Static Mesh property, and set its Collision Preset to NoCollision.

What this blueprint taught you?

You quickly made a very basic blueprint, it was simplistic but it was useful. The first thing you can learn from it is the exact sequence of steps you had to perform: create a blueprint, create a StaticMesh component and give it a name, set it as the root of the blueprint, assign a Shape_Sphere for its shape, and set its Collision Preset. Let’s just replicate all those steps one by one in a C++ class.

Don’t miss any important update, subscribe to the newsletter. I hate spam as much as you do, and I’ll never share your data.

Create the C++ Camera class

In the File menu click on New C++ Class. Select Pawn and click Next. Name your class C_PlayerCamera, click on Public, and click Create Class. After a bit of compiling, the class files open in Visual Studio.

You now have 2 files: the C_PlayerCamera.h header file containing the class declaration, and the C_PlayerCamera.cpp source file containing the class implementation. If you take a look at the implementation file, you’ll see the following function quite at the top:

// Sets default values
AC_PlayerCamera::AC_PlayerCamera()
{
    // Set this pawn to call Tick() every frame. You can turn this off to improve performance if you don't need it.
    PrimaryActorTick.bCanEverTick = true;
}

As the comment suggests, this is where we are going to define the default values for the class, along with everything related to initialization.

This function is called a constructor, and it’s the equivalent of the Construction Script blueprint in Unreal Engine. That’s the perfect place to create the components and set their default values.

Add the CameraTarget component

Find the right information

You know where to type the code, now you need to find out what to type. It’s time to collect clues. Let’s have a look at the blueprint you created earlier. Hoover the mouse above the CameraTarget component. The pop-up contains the name of the name of the C++ class you need to create: StaticMeshComponent.

Let’s go to Unreal Engine search page and search for “StaticMeshComponent”. The first result should lead you to the UStaticMeshComponent API documentation containing all variables and functions of StaticMeshComponent class and parents. Very handy, so keep this page open in a tab of your web browser, you may come back to it often.

Go back to the search page and search for “Creating Components”. You’ll find the Creating and Attaching Components guide which is covering a lot about creating components with C++. The step 4 of this page indicates that you need to use CreateDefaultSubobject function in order to create a component (note: this is not the only way, we’ll talk more about that later).

Create the CameraTarget component

With all the information you collected you are now ready to type your own code. At the end of the constructor add the following code:

// StaticMesh root component
UStaticMeshComponent* CameraTarget = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("CameraTarget"));
//       (4)                (5)                   (1)                   (2)                   (3)

You called CreateDefaultSubobject(1) instructing to create an object from the class UStaticMeshComponent(2) named CameraTarget(3), and you’ll keep a reference to this created object in a pointer(4) named CameraTarget(5).

Let’s focus on the left part of the equal sign for a second: UStaticMeshComponent* CameraTarget. What you are doing here is to declare a variable. A variable is storage for data, and it’s composed by a data type and an identifier.

The data type is the first word: UStaticMeshComponent (we’ll disregard the “*” for now) and is specifying the kind of data being stored. Is it a number I can compute, or a string of characters I can read out loud? In our case its a class named UStaticMeshComponent.

The identifier is the name of the variable: CameraTarget in our case, and this is the name you’ll be using in your code to retrieve and use the contained data.

You can read more about variable in this documentation and this wikipedia page.

Add the include directive

So you was creating an object from a class named UStaticMeshComponent, but at this point the program doesn’t know anything about this class. You need to provide a declaration for this class. I invite you to read about #include and header in C++ if you need more understanding about it.

At the top of your file, just after the line #include “C_PlayerCamera.h” add the following code:

#include "Runtime/Engine/Classes/Components/StaticMeshComponent.h"

Set CameraTarget as the root of the blueprint

Next you need to assign CameraTarget as the root object of the blueprint, the way to do this is described in the same chapter of the Creating and Attaching Components guide. Here is the code:

RootComponent = static_cast<USceneComponent*>(CameraTarget);

If you don’t already know, static_cast keyword is a type-casting instruction. Type-casting is an advance topic in programming, and you need to know a bit about classes, objects, pointers, inheritance, and such. It’s not really important for us right now so you can skip this, but if you really feel like learning about it you can start by this documentation.

Assign a sphere shape to CameraTarget

This part is a bit complex, because you need to manually load the shape asset from the StarterContent before you can assign it to CameraTarget . This is a 3 steps process: load the shape, verify the shape was loaded, and assign the shape.

Load the shape

Loading assets is done with FObjectFinder function (that’s an info you get from the chapter 5 of the Creating and Attaching Components guide). You obviously need to know the disk path for the Shape_Sphere asset. Go back to the Content Browser, navigate to the StarterContent/Shapes, right click on Shape_Sphere, then click Copy Reference. Here you have the path in the clipboard, ready to be pasted in your code.

Set the path in a local variable named assetPath, and load the asset. Here is the code to load the shape:

// Load Shape_Sphere from the StarterContent
FString assetPath = FString(TEXT("/Game/StarterContent/Shapes/Shape_Sphere.Shape_Sphere"));
static ConstructorHelpers::FObjectFinder<UStaticMesh> shapeSphereAsset(*assetPath);

Keep in mind it is not good practice to hard-code a path in your code that way, but for the scope of this tutorial we’ll proceed like this. You’ll fix this later.

If your IDE (Visual Studio) is correctly configured, you should see a red underline under ConstructorHelpers. This is a good reminder that you need to include a declaration for the ConstructorHelpers class. So hop to the top of the file, and add the following line of code:

#include "Runtime/CoreUObject/Public/UObject/ConstructorHelpers.h"

Verify the shape was loaded

From the chapter 5 of the Creating and Attaching Components guide, you notice that you must call the Succeeded() function from the FObjectFinder structure you just created. Let’s also instruct the program to display an error message in the logs if the loading fails:

// Assign the shape to ourStaticMesh
if (shapeSphereAsset.Succeeded())
{
  // PLACEHOLDER: assign the shape
}
// Log an error if the path cannot be found
else
{
  UE_LOG(LogScript, Error, TEXT("%s%s"), TEXT("Cannot load shape asset from path: "), *assetPath);
}

Assign the shape

You can now assign the loaded Shape_Sphere to CameraTarget , just replace the placeholder from the previous chapter with the following code:

CameraTarget->SetStaticMesh(shapeSphereAsset.Object);

Set CameraTarget preset to NoCollision

This is the code to set NoCollision to CameraTarget. Add it at the end of the constructor:

CameraTarget->SetCollisionProfileName(TEXT("NoCollision"));

Final look

After reordering parts of the code to enhance readability, this is how your file should looks like:

#include "C_PlayerCamera.h"
#include "Runtime/CoreUObject/Public/UObject/ConstructorHelpers.h"
#include "Runtime/Engine/Classes/Components/StaticMeshComponent.h"

// Sets default values
AC_PlayerCamera::AC_PlayerCamera()
{
    // Set this pawn to call Tick() every frame. You can turn this off to improve performance if you don't need it.
    PrimaryActorTick.bCanEverTick = true;

    // Load Shape_Sphere from the StarterContent
    FString assetPath = FString(TEXT("/Game/StarterContent/Shapes/Shape_Sphere.Shape_Sphere"));
    static ConstructorHelpers::FObjectFinder<UStaticMesh> shapeSphereAsset(*assetPath);

    // StaticMesh root component
    UStaticMeshComponent* CameraTarget = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("CameraTarget"));
    RootComponent = static_cast<USceneComponent*>(CameraTarget);
    CameraTarget->SetCollisionProfileName(TEXT("NoCollision"));

    // Assign the shape to ourStaticMesh
    if (shapeSphereAsset.Succeeded())
    {
        CameraTarget->SetStaticMesh(shapeSphereAsset.Object);
    }
    // Log an error if the path cannot be found
    else
    {
        UE_LOG(LogScript, Error, TEXT("%s%s"), TEXT("Cannot load shape asset from path: "), *assetPath);
    }
}

To wrap up everything you need to compile. In Visual Studio open the Build menu and click Build Solution. This step is necessary every time you modify the code so the changes can be integrated in Unity Editor.

Conclusion

By creating a small blueprint with just a Static Mesh component you’ve learned the necessary steps to replicate in C++. You also know where and how to search for code documentation and examples, and you’ve learned about variables, constructors, includes, header and source files in C++.

In the next chapter you will fix a bug you just created, and the you’ll create more components.


Published inTutorials

Be First to Comment

    Leave a Reply

    Your email address will not be published. Required fields are marked *