unreal-engine-cpp-pro
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseUnreal Engine C++ Pro
Unreal Engine C++ 专家指南
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
核心原则
-
UObject & Garbage Collection:
- Always use for
UPROPERTY()member variables to ensure they are tracked by the Garbage Collector (GC).UObject* - Use if you need to keep a root reference outside of a UObject graph, but prefer
TStrongObjectPtr<>generally.addToRoot() - Understand the check vs
IsValid().nullptrhandles pending kill state safely.IsValid()
- Always use
-
Unreal Reflection System:
- Use ,
UCLASS(),USTRUCT(),UENUM()to expose types to the reflection system and Blueprints.UFUNCTION() - Minimize when possible; prefer
BlueprintReadWritefor state that shouldn't be trampled by logic in UI/Level BPs.BlueprintReadOnly
- Use
-
Performance First:
- Tick: Disable Ticking () by default. Only enable it if absolutely necessary. Prefer timers (
bCanEverTick = false) or event-driven logic.GetWorldTimerManager() - Casting: Avoid in hot loops. Cache references in
Cast<T>().BeginPlay - Structs vs Classes: Use structs for data-heavy, non-UObject types to reduce overhead.
F
- Tick: Disable Ticking (
-
UObject 与垃圾回收:
- 所有成员变量务必使用
UObject*包裹,确保被垃圾回收器(GC)追踪。UPROPERTY() - 若需要在UObject图之外保留根引用,可使用,但通常优先使用
TStrongObjectPtr<>。addToRoot() - 理解检查与
IsValid()的区别:nullptr可安全处理待销毁(pending kill)状态。IsValid()
- 所有
-
Unreal反射系统:
- 使用、
UCLASS()、USTRUCT()、UENUM()将类型暴露给反射系统与Blueprint。UFUNCTION() - 尽可能减少使用;对于不应被UI/关卡Blueprint逻辑修改的状态,优先使用
BlueprintReadWrite。BlueprintReadOnly
- 使用
-
性能优先:
- Tick函数:默认禁用Tick(),仅在绝对必要时启用。优先使用定时器(
bCanEverTick = false)或事件驱动逻辑。GetWorldTimerManager() - 类型转换:避免在热循环中使用,在
Cast<T>()中缓存引用。BeginPlay - 结构体 vs 类:对于数据密集型、非UObject类型,使用前缀的结构体以减少开销。
F
- Tick函数:默认禁用Tick(
Naming Conventions (Strict)
命名规范(严格遵循)
Follow Epic Games' coding standard:
- Templates: Prefix with (e.g.,
T,TArray).TMap - UObject: Prefix with (e.g.,
U).UCharacterMovementComponent - AActor: Prefix with (e.g.,
A).AMyGameMode - SWidget: Prefix with (Slate widgets).
S - Structs: Prefix with (e.g.,
F).FVector - Enums: Prefix with (e.g.,
E).EWeaponState - Interfaces: Prefix with (e.g.,
I).IInteractable - Booleans: Prefix with (e.g.,
b).bIsDead
遵循Epic Games的编码标准:
- 模板:前缀为(例如:
T、TArray)。TMap - UObject:前缀为(例如:
U)。UCharacterMovementComponent - AActor:前缀为(例如:
A)。AMyGameMode - SWidget:前缀为(Slate组件)。
S - 结构体:前缀为(例如:
F)。FVector - 枚举:前缀为(例如:
E)。EWeaponState - 接口:前缀为(例如:
I)。IInteractable - 布尔值:前缀为(例如:
b)。bIsDead
Common Patterns
常见模式
1. Robust Component Lookup
1. 可靠的组件查找
Avoid in . Do it in or .
GetComponentByClassTickPostInitializeComponentsBeginPlaycpp
void AMyCharacter::PostInitializeComponents() {
Super::PostInitializeComponents();
HealthComp = FindComponentByClass<UHealthComponent>();
check(HealthComp); // Fail hard in dev if missing
}避免在中使用,应在或中执行。
TickGetComponentByClassPostInitializeComponentsBeginPlaycpp
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 () for massive assets which force load orders. Use or .
UPROPERTY(EditDefaultsOnly) TSubclassOf<AActor>TSoftClassPtrTSoftObjectPtrcpp
UPROPERTY(EditAnywhere, BlueprintReadWrite)
TSoftClassPtr<AWeapon> WeaponClassToLoad;
void AMyCharacter::Equip() {
if (WeaponClassToLoad.IsPending()) {
WeaponClassToLoad.LoadSynchronous(); // Or use StreamableManager for async
}
}避免对大型资源使用硬引用(),这会强制加载顺序。应使用或。
UPROPERTY(EditDefaultsOnly) TSubclassOf<AActor>TSoftClassPtrTSoftObjectPtrcpp
UPROPERTY(EditAnywhere, BlueprintReadWrite)
TSoftClassPtr<AWeapon> WeaponClassToLoad;
void AMyCharacter::Equip() {
if (WeaponClassToLoad.IsPending()) {
WeaponClassToLoad.LoadSynchronous(); // Or use StreamableManager for async
}
}Debugging
调试
- Logging: Use with custom categories.
UE_LOGcppDEFINE_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_LOGcppDEFINE_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!")); - 可视化日志:对AI调试极为有用,实现接口。
IVisualLoggerDebugSnapshotInterface
Checklist before PR
提交PR前检查清单
- Does this Actor need to Tick? Can it be a Timer?
- Are all members wrapped in
UObject*?UPROPERTY - Are hard references (TSubclassOf) causing load chains? Can they be Soft Ptrs?
- Did you clean up verified delegates in ?
EndPlay
- 该Actor是否需要Tick?能否改用定时器?
- 所有成员是否都用
UObject*包裹?UPROPERTY - 硬引用(TSubclassOf)是否导致加载链问题?能否改为软指针?
- 是否已在中清理已验证的委托?
EndPlay