unreal-engine-cpp-pro

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Unreal Engine C++ Pro

Unreal Engine C++ Pro

This skill provides expert-level guidelines for developing with Unreal Engine 5 using C++. It focuses on writing robust, performant, and standard-compliant code.
本 skill 提供了使用 C++ 进行 Unreal Engine 5 开发的专家级指南,重点是编写稳健、高性能且符合标准的代码。

When to Use

何时使用

Use this skill when:
  • Developing C++ code for Unreal Engine 5.x projects
  • Writing Actors, Components, or UObject-derived classes
  • Optimizing performance-critical code in Unreal Engine
  • Debugging memory leaks or garbage collection issues
  • Implementing Blueprint-exposed functionality
  • Following Epic Games' coding standards and conventions
  • Working with Unreal's reflection system (UCLASS, USTRUCT, UFUNCTION)
  • Managing asset loading and soft references
Do not use this skill when:
  • Working with Blueprint-only projects (no C++ code)
  • Developing for Unreal Engine versions prior to 5.x
  • Working on non-Unreal game engines
  • The task is unrelated to Unreal Engine development
在以下情况下使用本 skill:
  • 为 Unreal Engine 5.x 项目开发 C++ 代码
  • 编写 Actor、Component 或派生自 UObject 的类
  • 优化 Unreal Engine 中对性能至关重要的代码
  • 调试内存泄漏或垃圾回收问题
  • 实现向 Blueprint 暴露的功能
  • 遵循 Epic Games 的编码标准与约定
  • 使用 Unreal 的反射系统(UCLASS、USTRUCT、UFUNCTION)
  • 管理资产加载和软引用
在以下情况下不要使用本 skill:
  • 处理仅使用 Blueprint 的项目(无 C++ 代码)
  • 开发 Unreal Engine 5.x 之前的版本
  • 使用非 Unreal 游戏引擎进行开发
  • 任务与 Unreal Engine 开发无关

Core Principles

核心原则

  1. UObject & Garbage Collection:
    • Always use
      UPROPERTY()
      for
      UObject*
      member variables to ensure they are tracked by the Garbage Collector (GC).
    • Use
      TStrongObjectPtr<>
      if you need to keep a root reference outside of a UObject graph, but prefer
      addToRoot()
      generally.
    • Understand the
      IsValid()
      check vs
      nullptr
      .
      IsValid()
      handles pending kill state safely.
  2. Unreal Reflection System:
    • Use
      UCLASS()
      ,
      USTRUCT()
      ,
      UENUM()
      ,
      UFUNCTION()
      to expose types to the reflection system and Blueprints.
    • Minimize
      BlueprintReadWrite
      when possible; prefer
      BlueprintReadOnly
      for state that shouldn't be trampled by logic in UI/Level BPs.
  3. Performance First:
    • Tick: Disable Ticking (
      bCanEverTick = false
      ) by default. Only enable it if absolutely necessary. Prefer timers (
      GetWorldTimerManager()
      ) or event-driven logic.
    • Casting: Avoid
      Cast<T>()
      in hot loops. Cache references in
      BeginPlay
      .
    • Structs vs Classes: Use
      F
      structs for data-heavy, non-UObject types to reduce overhead.
  1. UObject 与垃圾回收:
    • 对
      UObject*
      成员变量始终使用
      UPROPERTY()
      ,以确保垃圾回收器(GC)能够跟踪它们。
    • 如果需要在 UObject 对象图之外保留根引用,请使用
      TStrongObjectPtr<>
      ;但通常更推荐使用
      addToRoot()
      。
    • 理解
      IsValid()
      检查与
      nullptr
      检查之间的区别。
      IsValid()
      能够安全处理 pending kill 状态。
  2. Unreal 反射系统:
    • 使用
      UCLASS()
      、
      USTRUCT()
      、
      UENUM()
      、
      UFUNCTION()
      将类型暴露给反射系统和 Blueprint。
    • 尽可能减少
      BlueprintReadWrite
      的使用;对于不应被 UI/Level BPs 中的逻辑覆盖的状态,优先使用
      BlueprintReadOnly
      。
  3. 性能优先:
    • Tick:默认禁用 Tick(
      bCanEverTick = false
      )。仅在绝对必要时启用。优先使用计时器(
      GetWorldTimerManager()
      )或事件驱动逻辑。
    • Casting:避免在热循环中调用
      Cast<T>()
      。在
      BeginPlay
      中缓存引用。
    • 结构体与类:对于数据密集型的非 UObject 类型,使用
      F
      结构体以降低开销。

Naming Conventions (Strict)

命名约定(严格)

Follow Epic Games' coding standard:
  • Templates: Prefix with
    T
    (e.g.,
    TArray
    ,
    TMap
    ).
  • UObject: Prefix with
    U
    (e.g.,
    UCharacterMovementComponent
    ).
  • AActor: Prefix with
    A
    (e.g.,
    AMyGameMode
    ).
  • SWidget: Prefix with
    S
    (Slate widgets).
  • Structs: Prefix with
    F
    (e.g.,
    FVector
    ).
  • Enums: Prefix with
    E
    (e.g.,
    EWeaponState
    ).
  • Interfaces: Prefix with
    I
    (e.g.,
    IInteractable
    ).
  • Booleans: Prefix with
    b
    (e.g.,
    bIsDead
    ).
遵循 Epic Games 的编码标准:
  • 模板:使用
    T
    作为前缀(例如
    TArray
    、
    TMap
    )。
  • UObject:使用
    U
    作为前缀(例如
    UCharacterMovementComponent
    )。
  • AActor:使用
    A
    作为前缀(例如
    AMyGameMode
    )。
  • SWidget:使用
    S
    作为前缀(Slate 控件)。
  • 结构体:使用
    F
    作为前缀(例如
    FVector
    )。
  • 枚举:使用
    E
    作为前缀(例如
    EWeaponState
    )。
  • 接口:使用
    I
    作为前缀(例如
    IInteractable
    )。
  • 布尔值:使用
    b
    作为前缀(例如
    bIsDead
    )。

Common Patterns

常见模式

1. Robust Component Lookup

1. 健壮的组件查找

Avoid
GetComponentByClass
in
Tick
. Do it in
PostInitializeComponents
or
BeginPlay
.
cpp
void AMyCharacter::PostInitializeComponents() {
    Super::PostInitializeComponents();
    HealthComp = FindComponentByClass<UHealthComponent>();
    check(HealthComp); // Fail hard in dev if missing
}
避免在
Tick
中调用
GetComponentByClass
。应在
PostInitializeComponents
或
BeginPlay
中执行。
cpp
void AMyCharacter::PostInitializeComponents() {
    Super::PostInitializeComponents();
    HealthComp = FindComponentByClass<UHealthComponent>();
    check(HealthComp); // Fail hard in dev if missing
}

2. Interface Implementation

2. 接口实现

Use interfaces to decouple systems (e.g., Interaction system).
cpp
// Interface call check
if (TargetActor->Implements<UInteractable>()) {
    IInteractable::Execute_OnInteract(TargetActor, this);
}
使用接口解耦系统(例如交互系统)。
cpp
// Interface call check
if (TargetActor->Implements<UInteractable>()) {
    IInteractable::Execute_OnInteract(TargetActor, this);
}

3. Async Loading (Soft References)

3. 异步加载(软引用)

Avoid hard references (
UPROPERTY(EditDefaultsOnly) TSubclassOf<AActor>
) for massive assets which force load orders. Use
TSoftClassPtr
or
TSoftObjectPtr
.
cpp
UPROPERTY(EditAnywhere, BlueprintReadWrite)
TSoftClassPtr<AWeapon> WeaponClassToLoad;

void AMyCharacter::Equip() {
    if (WeaponClassToLoad.IsPending()) {
        WeaponClassToLoad.LoadSynchronous(); // Or use StreamableManager for async
    }
}
避免对大型资产使用硬引用(
UPROPERTY(EditDefaultsOnly) TSubclassOf<AActor>
),因为硬引用会强制决定加载顺序。请使用
TSoftClassPtr
或
TSoftObjectPtr
。
cpp
UPROPERTY(EditAnywhere, BlueprintReadWrite)
TSoftClassPtr<AWeapon> WeaponClassToLoad;

void AMyCharacter::Equip() {
    if (WeaponClassToLoad.IsPending()) {
        WeaponClassToLoad.LoadSynchronous(); // Or use StreamableManager for async
    }
}

Debugging

调试

  • Logging: Use
    UE_LOG
    with custom categories.
    cpp
    DEFINE_LOG_CATEGORY_STATIC(LogMyGame, Log, All);
    UE_LOG(LogMyGame, Warning, TEXT("Health is low: %f"), CurrentHealth);
  • Screen Messages:
    cpp
    if (GEngine) GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, TEXT("Died!"));
  • Visual Logger: extremely useful for AI debugging. Implement
    IVisualLoggerDebugSnapshotInterface
    .
  • 日志记录:使用
    UE_LOG
    并定义自定义日志类别。
    cpp
    DEFINE_LOG_CATEGORY_STATIC(LogMyGame, Log, All);
    UE_LOG(LogMyGame, Warning, TEXT("Health is low: %f"), CurrentHealth);
  • 屏幕消息:
    cpp
    if (GEngine) GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, TEXT("Died!"));
  • Visual Logger:对 AI 调试极为有用。实现
    IVisualLoggerDebugSnapshotInterface
    。

Checklist before PR

PR 前检查清单

  • Does this Actor need to Tick? Can it be a Timer?
  • Are all
    UObject*
    members wrapped in
    UPROPERTY
    ?
  • Are hard references (TSubclassOf) causing load chains? Can they be Soft Ptrs?
  • Did you clean up verified delegates in
    EndPlay
    ?
  • 这个 Actor 是否需要 Tick?能否改用 Timer?
  • 是否所有
    UObject*
    成员都使用了
    UPROPERTY
    包裹?
  • 硬引用(TSubclassOf)是否造成了加载链?能否改为 Soft Ptr?
  • 是否已在
    EndPlay
    中清理并核验委托?

Limitations

限制

  • Use this skill only when the task clearly matches the scope described above.
  • Do not treat the output as a substitute for environment-specific validation, testing, or expert review.
  • Stop and ask for clarification if required inputs, permissions, safety boundaries, or success criteria are missing.
  • 仅当任务明确符合上述范围时使用本 skill。
  • 不要将输出视为替代针对具体环境的验证、测试或专家评审的手段。
  • 如果缺少必要的输入、权限、安全边界或成功标准,请停止操作并请求澄清。