with one click
unreal-cpp
写 Unreal C++/蓝图时使用。UObject/GC、反射宏、Tick 性能、蓝图边界。
Install with Codex or Claude Copy this prompt, paste it into Codex, Claude, or another assistant, and let it review the skill page and install it for you.
Menu
写 Unreal C++/蓝图时使用。UObject/GC、反射宏、Tick 性能、蓝图边界。
Install with Codex or Claude Copy this prompt, paste it into Codex, Claude, or another assistant, and let it review the skill page and install it for you.
Based on SOC occupation classification
做 Cocos Creator 多机型/多分辨率适配时使用。Canvas、Widget、安全区。
Cocos Creator 用 AssetBundle 做分包/远程资源时使用。加载、释放、依赖、缓存。
优化 Cocos Creator 渲染性能时使用。合批、图集、动静分离、Label。
给 Cocos Creator 原生包做热更新时使用。version manifest、增量、校验、回滚。
写 Cocos Creator 动效/动画时使用。tween、Animation、Spine、性能与清理。
做 Cocos Creator 大量条目列表时使用。虚拟列表、节点复用。
| name | unreal-cpp |
| description | 写 Unreal C++/蓝图时使用。UObject/GC、反射宏、Tick 性能、蓝图边界。 |
| category | gamedev |
| tags | ["unreal","cpp","蓝图"] |
规则: 所有持有 UObject 派生类(Actor、Component、Asset 等)的成员变量,必须加 UPROPERTY();弱引用用 TWeakObjectPtr;原生裸指针不做持有。
为什么——真实会犯的错:
在 .h 里写了 AEnemy* CachedEnemy; 没加 UPROPERTY(),开发期看起来没问题,进入关卡切换或 GC 整理周期后,引擎把 CachedEnemy 回收了,下一帧 CachedEnemy->TakeDamage(...) 直接崩溃。Crash log 里只有 Access violation,根本看不出是 GC 问题,排查半天。
怎么做:
UPROPERTY()(至少空括号),让 GC 追踪引用计数。TWeakObjectPtr<AEnemy>,使用前先 IsValid()。UPROPERTY(),GC 周期内不会出问题。new UObject() 也不要手动调,用 NewObject<T>() 或 SpawnActor<T>()。规则: UCLASS/UFUNCTION/UPROPERTY 只在真正需要反射、蓝图互操时标注;不把所有东西都往蓝图暴露。
为什么——真实会犯的错:
把所有函数都加 BlueprintCallable、所有变量都加 EditAnywhere,编译时间膨胀,蓝图节点列表被几百个无意义函数污染,策划误用了不该在蓝图调的内部函数,出现生命周期顺序问题。另一个常见错误:忘记在 UFUNCTION() 里标 BlueprintImplementableEvent 却在 C++ 里给了函数体,导致链接错误,新手往往不知道该怎么修。
怎么做:
BlueprintCallable;只给蓝图重写的函数加 BlueprintImplementableEvent 或 BlueprintNativeEvent。BlueprintImplementableEvent 的 C++ 函数不能有函数体;BlueprintNativeEvent 的实现写在 FuncName_Implementation 里。EditAnywhere/BlueprintReadWrite;运行时内部状态加 Transient 或不标。规则: Actor/Component 创建时默认设 PrimaryActorTick.bCanEverTick = false;确实需要逐帧逻辑再开,并评估能否用 Timer 或事件替代。
为什么——真实会犯的错:
场景里生成了 300 个 ABullet,每颗子弹的 Tick 里做了一次 LineTrace,帧率掉到 20 fps,Profiler 里看到几百条 ABullet::TickComponent 占满 CPU。这些子弹大多数时间都在直线飞行,根本不需要每帧 LineTrace——改成 SetActorTickInterval(0.05f) 或抛给 Projectile Movement Component 之后帧率立刻回来了。
怎么做:
PrimaryActorTick.bCanEverTick = false 作为默认值。GetWorldTimerManager().SetTimer(),比 Tick 里减计数更清晰。PrimaryActorTick.TickInterval 降低频率;或在运行时 SetActorTickEnabled(false) 关掉不活跃对象的 Tick。规则: 性能敏感、核心计算逻辑放 C++;数值调参、流程编排、视觉表现留蓝图;不在蓝图里写复杂循环或频繁调用的重计算。
为什么——真实会犯的错:
策划在蓝图里写了一段「扫描半径内所有敌人并按距离排序」的逻辑,用蓝图 ForLoop + GetAllActorsOfClass,每帧执行,场景有 200 个敌人时帧率腰斩。换成 C++ 用空间查询 OverlapMultiByChannel 之后性能恢复正常。另一个方向的错误:程序把所有技能参数写死在 C++ 里,策划调个伤害值要重新编译,浪费大量来回时间。
怎么做:
UPROPERTY(EditDefaultsOnly) 把 C++ 的可调参数暴露给蓝图默认值编辑,而不是写死常量。规则: 严格遵守 Unreal 命名前缀(A/U/F/E/I),头文件只包含真正依赖的头,模块间依赖在 .Build.cs 里显式声明。
为什么——真实会犯的错:
在 FPlayerData 前面忘了加 F,写成 PlayerData,和蓝图变量名冲突,反射系统报警告且行为诡异。另一个常见事故:在 .h 里 #include "Engine.h" 图省事,导致增量编译时几乎所有 .cpp 都重编,编译时间从 30 秒变 5 分钟。还有在 A 模块直接 #include B 模块的私有头而不在 .Build.cs 添加依赖,本地能编过,CI 上缺头文件报错。
怎么做:
A;继承 UObject → U;纯 C++ 结构体 → F;枚举 → E;接口 → I。依赖方.Build.cs 的 PublicDependencyModuleNames 或 PrivateDependencyModuleNames 里添加被依赖模块,不能靠传递依赖碰运气。// ❌ 反例 — 裸指针没有 UPROPERTY,GC 随时可能回收;Tick 默认开着
UCLASS()
class AWeapon : public AActor
{
GENERATED_BODY()
public:
AWeapon();
ACharacter* OwnerCharacter; // ❌ 裸指针,GC 不追踪,随时野指针崩溃
virtual void Tick(float DeltaTime) override; // ❌ 什么都不做却每帧执行
};
AWeapon::AWeapon()
{
// 没有关 Tick,默认开着
}
void AWeapon::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
// 空的,白白占 CPU
}
// ✅ 正例 — UPROPERTY 保护引用;默认关 Tick;需要周期逻辑用 Timer
UCLASS()
class AWeapon : public AActor
{
GENERATED_BODY()
public:
AWeapon();
UPROPERTY()
ACharacter* OwnerCharacter; // ✅ GC 追踪,销毁时自动置 null
UPROPERTY(EditDefaultsOnly, Category="Combat")
float FireCooldown = 0.5f; // ✅ 参数暴露给蓝图,策划可调
UFUNCTION(BlueprintCallable, Category="Combat")
void StartFire();
private:
FTimerHandle FireTimerHandle;
void OnFireTick();
};
AWeapon::AWeapon()
{
PrimaryActorTick.bCanEverTick = false; // ✅ 默认关,不浪费 CPU
}
void AWeapon::StartFire()
{
GetWorldTimerManager().SetTimer(
FireTimerHandle, this, &AWeapon::OnFireTick,
FireCooldown, true); // ✅ Timer 替代 Tick,频率可控
}
UPROPERTY(),没有裸指针持有。PrimaryActorTick.bCanEverTick = false,或有明确理由开启 Tick。UPROPERTY(EditDefaultsOnly) 暴露,没有写死常量。BlueprintImplementableEvent 的 C++ 函数无函数体;BlueprintNativeEvent 的实现在 _Implementation 里。#include "Engine.h" 或其他大而全的万能头。.Build.cs 显式声明。