unreal-cpp-gameplay

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Unreal C++ Gameplay

Unreal C++ 游戏玩法开发

Write correct UE5 gameplay C++: the reflection macros that connect C++ to the editor and Blueprints, the Gameplay Framework class roles, and module dependencies. Targets UE 5.4+.
编写正确的UE5游戏玩法C++代码:实现C++与编辑器及蓝图连接的反射宏、游戏玩法框架类的角色,以及模块依赖。适用于 UE 5.4+ 版本。

When to use

使用场景

  • Use when creating C++ gameplay classes (
    AActor
    ,
    APawn
    ,
    ACharacter
    ,
    AGameModeBase
    ,
    UActorComponent
    ), exposing properties/functions with
    UPROPERTY
    /
    UFUNCTION
    , setting up a GameMode's default classes, or adding a module dependency in
    *.Build.cs
    .
  • Use when the project has a
    Source/
    tree with
    *.h
    /
    *.cpp
    using
    UCLASS
    , and
    *.Build.cs
    .
When not to use: designer-facing visual logic →
unreal-blueprints
. Player input binding details →
unreal-enhanced-input
. AI logic →
unreal-behavior-trees
. This skill owns the C++ class/reflection foundation those build on.
  • 适用于创建C++游戏玩法类(
    AActor
    APawn
    ACharacter
    AGameModeBase
    UActorComponent
    )、通过
    UPROPERTY
    /
    UFUNCTION
    暴露属性/函数、设置GameMode的默认类,或在
    *.Build.cs
    中添加模块依赖时。
  • 适用于项目包含使用
    UCLASS
    Source/
    目录下
    *.h
    /
    *.cpp
    文件,以及
    *.Build.cs
    文件的场景。
不适用于: 面向设计师的可视化逻辑 → 请使用
unreal-blueprints
。玩家输入绑定细节 → 请使用
unreal-enhanced-input
。AI逻辑 → 请使用
unreal-behavior-trees
。本技能涵盖上述技能所依赖的C++类/反射基础。

Core workflow

核心工作流程

  1. Name with the right prefix.
    A
    = Actor-derived,
    U
    =
    UObject
    /component-derived,
    F
    = plain struct,
    E
    = enum,
    I
    = interface. The prefix must match the base class.
  2. Declare the class with reflection macros.
    UCLASS()
    above the class,
    GENERATED_BODY()
    as the first line in the body, and
    #include "ClassName.generated.h"
    as the last include in the header.
  3. Expose data with
    UPROPERTY
    (editor/Blueprint visibility and garbage-collection tracking) and behaviour with
    UFUNCTION
    (
    BlueprintCallable
    , etc.).
  4. Create components in the constructor with
    CreateDefaultSubobject<T>(TEXT("Name"))
    and set the
    RootComponent
    .
  5. Know the framework roles:
    AGameModeBase
    sets the rules + default classes;
    APawn
    /
    ACharacter
    is the controllable body;
    APlayerController
    is the player's will;
    UActorComponent
    is reusable behaviour.
  6. Add module dependencies to
    *.Build.cs
    (e.g.
    EnhancedInput
    ) or unresolved-symbol link errors follow.
  7. Verify by compiling (Live Coding
    Ctrl+Alt+F11
    for function bodies; full rebuild for header/UPROPERTY changes) and checking the class/properties appear in the editor.
  1. 使用正确的前缀命名
    A
    = 继承自Actor的类,
    U
    = 继承自
    UObject
    /组件的类,
    F
    = 普通结构体,
    E
    = 枚举,
    I
    = 接口。前缀必须与基类匹配。
  2. 使用反射宏声明类。类上方添加
    UCLASS()
    ,类体第一行添加
    GENERATED_BODY()
    ,头文件中最后一个引用必须是
    #include "ClassName.generated.h"
  3. 使用
    UPROPERTY
    暴露数据
    (支持编辑器/蓝图可见性及垃圾回收追踪),使用
    UFUNCTION
    暴露行为(如
    BlueprintCallable
    等)。
  4. 在构造函数中创建组件,使用
    CreateDefaultSubobject<T>(TEXT("Name"))
    并设置
    RootComponent
  5. 了解框架角色
    AGameModeBase
    设置规则及默认类;
    APawn
    /
    ACharacter
    是可控制的实体;
    APlayerController
    代表玩家的操作意志;
    UActorComponent
    是可复用的行为组件。
  6. *.Build.cs
    中添加模块依赖
    (例如
    EnhancedInput
    ),否则会出现未解析符号的链接错误。
  7. 验证代码:编译(函数体可使用实时编码
    Ctrl+Alt+F11
    ;头文件/UPROPERTY更改需完全重建),并检查类/属性是否在编辑器中显示。

Patterns

代码示例

1. Minimal Actor class (header + source)

1. 最小Actor类(头文件 + 源文件)

cpp
// Pickup.h
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "Pickup.generated.h"          // MUST be the last include

UCLASS()
class MYGAME_API APickup : public AActor   // MYGAME_API = your module's export macro
{
    GENERATED_BODY()
public:
    APickup();

    // EditAnywhere = tweak per-instance & on the CDO; BlueprintReadWrite = BP get/set.
    UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Pickup")
    int32 ScoreValue = 10;

    // UPROPERTY on a UObject* pointer is what keeps it from being garbage-collected.
    UPROPERTY(VisibleAnywhere)
    TObjectPtr<UStaticMeshComponent> Mesh;   // UE5: TObjectPtr instead of raw UStaticMeshComponent*

    UFUNCTION(BlueprintCallable, Category = "Pickup")
    void Collect();

protected:
    virtual void BeginPlay() override;
};
cpp
// Pickup.cpp
#include "Pickup.h"
#include "Components/StaticMeshComponent.h"

APickup::APickup()
{
    Mesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("Mesh"));
    RootComponent = Mesh;                     // the mesh is this actor's root
}

void APickup::BeginPlay() { Super::BeginPlay(); }   // always call Super
void APickup::Collect()   { Destroy(); }
cpp
// Pickup.h
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "Pickup.generated.h"          // 必须是最后一个引用

UCLASS()
class MYGAME_API APickup : public AActor   // MYGAME_API = 你的模块导出宏
{
    GENERATED_BODY()
public:
    APickup();

    // EditAnywhere = 可在实例及CDO上调整;BlueprintReadWrite = 蓝图可读写。
    UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Pickup")
    int32 ScoreValue = 10;

    // UObject*指针上的UPROPERTY用于防止被垃圾回收。
    UPROPERTY(VisibleAnywhere)
    TObjectPtr<UStaticMeshComponent> Mesh;   // UE5: 使用TObjectPtr替代原始UStaticMeshComponent*

    UFUNCTION(BlueprintCallable, Category = "Pickup")
    void Collect();

protected:
    virtual void BeginPlay() override;
};
cpp
// Pickup.cpp
#include "Pickup.h"
#include "Components/StaticMeshComponent.h"

APickup::APickup()
{
    Mesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("Mesh"));
    RootComponent = Mesh;                     // 该网格体是此Actor的根组件
}

void APickup::BeginPlay() { Super::BeginPlay(); }   // 务必调用父类方法
void APickup::Collect()   { Destroy(); }

2. GameMode wiring its default classes

2. GameMode配置默认类

cpp
// MyGameMode.cpp — set in the constructor so the engine spawns your classes.
AMyGameMode::AMyGameMode()
{
    DefaultPawnClass      = AMyCharacter::StaticClass();
    PlayerControllerClass = AMyPlayerController::StaticClass();
}
cpp
// MyGameMode.cpp — 在构造函数中设置,以便引擎生成你的类。
AMyGameMode::AMyGameMode()
{
    DefaultPawnClass      = AMyCharacter::StaticClass();
    PlayerControllerClass = AMyPlayerController::StaticClass();
}

3. Module dependency in Build.cs

3. Build.cs中的模块依赖

csharp
// MyGame.Build.cs
PublicDependencyModuleNames.AddRange(new string[]
{
    "Core", "CoreUObject", "Engine", "InputCore", "EnhancedInput"
});
csharp
// MyGame.Build.cs
PublicDependencyModuleNames.AddRange(new string[]
{
    "Core", "CoreUObject", "Engine", "InputCore", "EnhancedInput"
});

Pitfalls

常见陷阱

  • generated.h
    not last / missing
    — compile errors like "Cannot find generated header" or "Expected an include". It must be the final include in the header.
  • Forgetting
    GENERATED_BODY()
    — UHT (Unreal Header Tool) errors; it must be the first thing inside the class body.
  • Raw
    UObject*
    without
    UPROPERTY
    — the garbage collector doesn't see it and may destroy it out from under you. Track every UObject pointer with
    UPROPERTY
    (use
    TObjectPtr
    in UE5).
  • Header/UPROPERTY edits with Live Coding — Live Coding handles function bodies, but changes to
    UCLASS
    /
    UPROPERTY
    /headers need a full editor restart + rebuild.
  • Wrong class prefix — naming an Actor
    UFoo
    (or a component
    AFoo
    ) breaks UHT; match the prefix to the base type.
  • Unresolved external symbol at link — the module providing the API isn't in
    Build.cs
    PublicDependencyModuleNames
    .
  • Not calling
    Super::
    in overridden
    BeginPlay
    /
    Tick
    /etc. skips engine setup.
  • generated.h
    未放在最后/缺失
    —— 出现类似“无法找到生成的头文件”或“预期包含文件”的编译错误。它必须是头文件中的最后一个引用。
  • 忘记添加
    GENERATED_BODY()
    —— 出现UHT(Unreal Header Tool)错误;它必须是类体中的第一行内容。
  • 未添加
    UPROPERTY
    的原始
    UObject*
    —— 垃圾回收器无法识别该指针,可能会在你不知情的情况下销毁对象。使用
    UPROPERTY
    追踪每个UObject指针(UE5中使用
    TObjectPtr
    )。
  • 使用实时编码修改头文件/UPROPERTY —— 实时编码仅处理函数体,
    UCLASS
    /
    UPROPERTY
    /头文件的更改需要完全重启编辑器并重建项目。
  • 错误的类前缀 —— 将Actor命名为
    UFoo
    (或将组件命名为
    AFoo
    )会破坏UHT;前缀必须与基类类型匹配。
  • 链接时出现未解析外部符号 —— 提供API的模块未添加到
    Build.cs
    PublicDependencyModuleNames
    中。
  • 未调用
    Super::
    —— 重写
    BeginPlay
    /
    Tick
    等方法时跳过父类调用会导致引擎初始化不完整。

References

参考资料

  • For
    UActorComponent
    creation/attachment, the
    UPROPERTY
    garbage-collection ownership rules (
    TObjectPtr
    ,
    TArray<TObjectPtr<>>
    ,
    AddToRoot
    ), and a replication primer, read
    references/components-and-gc.md
    .
  • Primary docs: "Unreal Engine CPP Quick Start" and "Gameplay Framework" (
    https://dev.epicgames.com/documentation/en-us/unreal-engine/gameplay-framework-in-unreal-engine
    ).
  • 关于
    UActorComponent
    的创建/附着、
    UPROPERTY
    垃圾回收所有权规则(
    TObjectPtr
    TArray<TObjectPtr<>>
    AddToRoot
    )以及复制入门知识,请阅读
    references/components-and-gc.md
  • 官方文档:“Unreal Engine CPP快速入门”和“游戏玩法框架”(
    https://dev.epicgames.com/documentation/en-us/unreal-engine/gameplay-framework-in-unreal-engine
    )。

Related skills

相关技能

  • unreal-blueprints
    — exposing C++ to designers; BP/C++ interop.
  • unreal-enhanced-input
    — binding input in a C++ Pawn/Character.
  • unreal-behavior-trees
    — C++ AI tasks driven from a behaviour tree.
  • unreal-blueprints
    —— 向设计师暴露C++功能;蓝图/C++交互。
  • unreal-enhanced-input
    —— 在C++ Pawn/Character中绑定输入。
  • unreal-behavior-trees
    —— 由行为树驱动的C++ AI任务。