Skip to content

Latest commit

 

History

History
170 lines (134 loc) · 6.16 KB

C++ Actor.md

File metadata and controls

170 lines (134 loc) · 6.16 KB

2020-12-30_17:02:30

C++ Actor

This is a minimal templates for a C++ Actor called MyActor.

Create MyActor.h in the target module's Public directory. Create MyActor.cpp in the target module's Private directory.

MyActor.h:

// This is an include guard, to prevent the heade file's content from being included
// multiple times in a single translational unit.
#pragma once

// We'll be inheriting from the AActor class, so we need its definition.
#include "GameFramework/Actor.h"

// Every header file that contains classes deriving from Unreal Engine classes
// get a corresponding .generated.h file, which must be included in the header
// file and it must be the last #include.
#include "MyActor.generated.h"

// UCLASS is used to mark the following class as an Unreal Engine class. One may
// add class specifiers inside the parenthesis. This mark is required for the
// reflection system to pick up the class.
UCLASS()
// All classes that inherit from AActor must prefix their name with A.
class AMyActor : public AActor
{
public:
    // GENERATED_BODY is a macro that is generated by Unreal Header Tool and is
    // defined in the corresponding .generated.h file.
    GENERATED_BODY()
};

[[2020-03-09_21:34:05]] UCLASS
[[2020-12-30_17:24:55]] Class specifiers

MyActor.cpp:

#include "MyActor.h"

The above is enough to build and use the Actor, but it doesn't do much. Create an instance by dragging it from Content Browser > C++ Classes into the level. It doesn't even have a Root Component so nothing is shown, not even the white marker sphere. This Actor doesn't have a position. It will show up in the World Outliner.

The following is an example which uses a few more features.

MyActor.h:

#pragma once

#include "GameFramework/Actor.h"

#include "MyActor.generated.h"

// We forward-declare the names of classes that we will hold pointers to, so that the
// number of included header files is kept at a minimum.
class UStaticMeshComponent;

// The Blueprintable class specifier makes it possible to create Blueprint classes
// that inherit from this C++ class.
UCLASS(Blueprintable)
class AMyActor : public AActor
{
public:
    GENERATED_BODY()

    // A member variable decorated with the UPROPERTY macro is exposed to the reflection
    // system. BlueprintReadWrite means that we can both read and write this value from
    // a Blueprint Visual Script. EditAnywhere means that we can edit this value in the
    // Details Panel of both the Blueprint Editor on a Blueprint subclass of this type,
    // and when a particular instance of this class is selected in the Level Editor.
    // The Category specify the category, or section, within the Detals Panel where this
    // property will show up.
    UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "MyGame")
    float MyFloat;

    // BlueprintReadOnly means that Blueprint Visual Scripts can read the value of this
    // property, but not change it. VisibleAnywhere means that we can see the value in
    // the Details Panel, but not change it, in both the Blueprint Editor and for specific
    // instances in the Level Editor.
    UPROPERTY(BlueprintReadOnly, VisibleAnywhere, Category = "MyGame")
    int32 MyInt;

    // EditInstanceOnly means that we cannot set a default value in the Blueprint Editor,
    // but we can set the value on each instance of the class.
    UPROPERTY(EditInstanceOnly, Category = "MyGame")
    AMyActor* Next;

    // We can own components with raw pointeres as long as we marked it with UPROPERTY. The
    // garbage collection system will keep the pointed-to object alive only for as long as
    // it's needed.
    UPROPERTY(VisibleAnywhere, BlueprintReadWrite)
    UStaticMeshComponent* Mesh;

    // UFUNCTION exposes the member function to the reflection system.
    // BlueprintCallable exposes the member function to Blueprint Visual Scripts.
    UFUNCTION(BlueprintCallable)
    void LinkAfter(AMyActor* Predecessor);

    // BlueprintPure signals that the member function does not affect the owning object in
    // any way. Consider making such functions C++ const as well. They become expression
    // nodes, as opposed to execution nodes, in Blueprint Visual Scripts.
    UFUNCTION(BlueprintPure)
    int32 RoundedMyFloat() const;

    // BlueprintImplementableEvent means that a Blueprint subclass will implement the member
    // function, there is no C++ implementation.
    UFUNCTION(BlueprintCallable, BlueprintImplementableEvent)
    void OnNewNext();

    // The Tick function is called on every tick, i.e., frame, if PrimaryActorTick.bCanEverTick
    // has been set to true.
    virtual void Tick(float DeltaTime) override;

    // BeginPlay is called at the start of each instance's lifetime, either at the start of
    // the game, or when the instance is spawned during runtime.
    virtual void BeginPlay() override;
};

MyActor.cpp:

#include "MyActor.h"

#include <Components/StaticMeshComponent.h>

AMyActor::AMyActor()
{
    // By setting bCanEverTick to true we request that the Tick callback is called.
    // This comes with a performance penaly, so try to avoid it.
    PrimaryActorTick.bCanEverTick = true;

    // Create a new mesh component. We use CreateDefaultSubobject because we are in the
    // constructor and we assing the returned pointer to a UPROPERTY member variable of
    // this class. The parameter is the label for the component, the name it will have
    // in the Blueprint Editor.
    Mesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("Mesh"));

    // Make the new component the root of the USceneComponent hierarchy for this Actor.
    SetRootComponent(Mesh);
}

void AMyActor::Tick(float DeltaTime)
{
    // Most virtual member function require that the call the base class implementation
    // as well. If you get an error message similar to "Could not route call to ..." during
    // runtime then you probably forgot a Super::-call.
    Super::Tick(DeltaTime);

    // Do your per-tick work here.
}

void AMyActor::BeginPlay()
{
    // Most virtual member function require that the call the base class implementation
    // as well.
    Super::BeginPlay();
}

[[2020-03-09_21:48:56]] UFUNCTION