关于 unreal-engine-cpp-pro
面向 Unreal Engine 5.x 开发者的 C++ 指导技能,涵盖引擎规范、对象生命周期、性能和常见实现模式,适用于开发与维护项目。
主要功能
- 01UObject 生命周期与垃圾回收
- 02反射系统与 Blueprint 暴露
- 03Tick 与性能指导
- 04Epic 命名规范
- 05资源加载与软引用
适用场景
- 01实现 Actor 和 Component
- 02排查垃圾回收问题
- 03优化性能关键代码
- 04向 Blueprint 暴露 C++ 功能
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ sickn33/ agentic-awesome-skills --skill unreal-engine-cpp-pro安装后在 Claude Code 中输入/unreal-engine-cpp-pro确认已加载。
附带文件examples/ExampleActor.cppexamples/ExampleActor.h
详细介绍
Unreal Engine C++ 专业指南
本技能提供使用 C++ 开发 Unreal Engine 5 项目的专家级指南,重点介绍如何编写健壮、高性能且符合标准的代码。
适用场景
在以下情况下使用本技能:
- 为 Unreal Engine 5.x 项目开发 C++ 代码
- 编写 Actor、Component 或 UObject 派生类
- 优化 Unreal Engine 中对性能要求较高的代码
- 调试内存泄漏或垃圾回收问题
- 实现可通过 Blueprint 访问的功能
- 遵循 Epic Games 的编码标准和约定
- 使用 Unreal 的反射系统(UCLASS、USTRUCT、UFUNCTION)
- 管理资源加载和软引用
在以下情况下不要使用本技能:
- 仅使用 Blueprint 开发项目(不涉及 C++ 代码)
- 为早于 5.x 的 Unreal Engine 版本开发
- 使用非 Unreal 游戏引擎开发
- 任务与 Unreal Engine 开发无关
核心原则
-
UObject 与垃圾回收:
- 始终为
UObject*成员变量使用UPROPERTY(),确保垃圾回收器(GC)跟踪这些变量。 - 在反射式 UObject 对象图之外使用作用域内的强引用时,谨慎使用
TStrongObjectPtr<>;不要常规地手动将对象设为根对象。手动调用AddToRoot()时,必须认真管理生命周期,并配对调用RemoveFromRoot()。 - 理解
IsValid()检查与nullptr的区别。IsValid()可以安全处理待销毁状态。
- 始终为
-
Unreal 反射系统:
- 使用
UCLASS()、USTRUCT()、UENUM()、UFUNCTION()将类型暴露给反射系统和 Blueprint。 - 尽可能减少
BlueprintReadWrite的使用;对于不应被 UI/Level BP 中的逻辑随意修改的状态,优先使用BlueprintReadOnly。
- 使用
-
性能优先:
- Tick:默认禁用 Tick(
bCanEverTick = false)。只有绝对必要时才启用。优先使用计时器(GetWorldTimerManager())或事件驱动逻辑。 - 类型转换:避免在热点循环中使用
Cast<T>()。在BeginPlay中缓存引用。 - 结构体与类:对于数据量大且非 UObject 的类型,使用
F结构体以降低开销。
- Tick:默认禁用 Tick(
命名约定(严格遵守)
遵循 Epic Games 的编码标准:
- 模板:以
T为前缀(例如TArray、TMap)。 - UObject:以
U为前缀(例如UCharacterMovementComponent)。 - AActor:以
A为前缀(例如AMyGameMode)。 - SWidget:以
S为前缀(Slate 控件)。 - 结构体:以
F为前缀(例如FVector)。 - 枚举:以
E为前缀(例如EWeaponState)。 - 接口:以
I为前缀(例如IInteractable)。 - 布尔值:以
b为前缀(例如bIsDead)。
常见模式
1. 稳健的组件查找
避免在 Tick 中使用 GetComponentByClass。应在 PostInitializeComponents 或 BeginPlay 中执行查找。
void AMyCharacter::PostInitializeComponents() {
Super::PostInitializeComponents();
HealthComp = FindComponentByClass<UHealthComponent>();
check(HealthComp); // Fail hard in dev if missing
}
2. 接口实现
使用接口解耦系统(例如交互系统)。
// Interface call check
if (IsValid(TargetActor) && TargetActor->Implements<UInteractable>()) {
IInteractable::Execute_OnInteract(TargetActor, this);
}
3. 软引用(同步示例)
对于会强制产生加载顺序的大型资源,避免使用硬引用(UPROPERTY(EditDefaultsOnly) TSubclassOf<AActor>)。应使用 TSoftClassPtr 或 TSoftObjectPtr。
UPROPERTY(EditAnywhere, BlueprintReadWrite)
TSoftClassPtr<AWeapon> WeaponClassToLoad;
void AMyCharacter::Equip() {
if (WeaponClassToLoad.IsPending()) {
WeaponClassToLoad.LoadSynchronous(); // Or use StreamableManager for async
}
}
调试
- 日志:使用带有自定义类别的
UE_LOG。DEFINE_LOG_CATEGORY_STATIC(LogMyGame, Log, All); UE_LOG(LogMyGame, Warning, TEXT("Health is low: %f"), CurrentHealth); - 屏幕消息:
if (GEngine) GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, TEXT("Died!")); - 可视化日志:对 AI 调试极为有用。实现
IVisualLoggerDebugSnapshotInterface。
PR 前检查清单
- 这个 Actor 需要 Tick 吗?可以改用 Timer 吗?
- 所有
UObject*成员是否都使用UPROPERTY包装? - 硬引用(TSubclassOf)是否会导致加载链?可以改用软指针吗?
- 是否已在
EndPlay中清理已验证的委托?
限制
- 仅当任务明确符合上述范围时,才使用此技能。
- 不要将输出视为针对特定环境进行验证、测试或专家审查的替代方案。
- 如果缺少必需的输入、权限、安全边界或成功标准,请停止并要求澄清。
这些 Actor 文件仅供示例参考,需要替换 MYGAME_API、生成项目头文件,并在目标引擎中构建。LoadSynchronous() 可能会阻塞游戏线程;对于对延迟敏感的路径,请使用目标版本的流式异步加载 API。在支持的情况下,优先使用经过反射的 TObjectPtr 成员。Epic 对象指针指南。
评论
支持 Markdown