跨层传递:结构体、枚举与资产引用
暴露单个变量容易,跨层传递复杂数据才是细节所在。
结构体:USTRUCT(BlueprintType)
USTRUCT(BlueprintType)
struct FDamageInfo
{
GENERATED_BODY()
UPROPERTY(EditAnywhere, BlueprintReadWrite)
float Amount = 0.f;
UPROPERTY(EditAnywhere, BlueprintReadWrite)
FName DamageType; // 物理/火焰/冰...
UPROPERTY(EditAnywhere, BlueprintReadWrite)
AActor* Instigator; // 伤害来源
};
蓝图里就能把它当一个值传递(Break/Make 节点自动生成)。注意:结构体不要包含 TMap/TSet,蓝图不支持;结构体之间不要互相循环引用。
枚举:UENUM(BlueprintType)
UENUM(BlueprintType)
enum class EEnemyState : uint8
{
Idle UMETA(DisplayName = "待机"),
Chase UMETA(DisplayName = "追击"),
Attack UMETA(DisplayName = "攻击"),
Dead UMETA(DisplayName = "死亡")
};
UMETA(DisplayName) 给中文显示名——蓝图的 Combobox 里就是中文了。给策划看的东西,尽量有中文 DisplayName。
类引用与软引用
// 硬引用:加载此类时,引用的资产也被加载
UPROPERTY(EditDefaultsOnly, Category=" Combat")
TSubclassOf<AActor> ProjectileClass; // "要生成哪种投射物"
// 软引用:按需加载(第 4 章详谈)
UPROPERTY(EditDefaultsOnly, Category="Combat")
TSoftClassPtr<AActor> BigBossClass;
| 引用类型 | C++ 写法 | 加载时机 | 适用 |
|---|---|---|---|
| 硬引用 | TSubclassOf<T> / UObject* |
立即 | 常用资源 |
| 软引用 | TSoftClassPtr / TSoftObjectPtr |
手动 Load | 大资源、低频资源 |
数据资产的公开
UCLASS(BlueprintType) // 让 DataAsset 也能被蓝图直接读写
class USkillAsset : public UPrimaryDataAsset
{
public:
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Skill")
float Cooldown = 1.f;
...
};
蓝图里拖一个 SkillAsset 到节点,直接读 Cooldown。这是"策划改数值不动代码"闭环的最后一环。
一个反面教材
曾有个项目用 FString 装一切:"伤害类型"是个字符串,到处 FString::Format,一个月后没人记得该填 "Fire" 还是 "fire"。正确做法:能用枚举绝不用字符串—— EDamageType 在编辑器里是下拉框,填错从机制上就不可能。
本章小结
- 结构体 / 枚举暴露前加
BlueprintType;枚举用UMETA(DisplayName)给中文名。 TMap/TSet不暴露,改用结构体数组或按 Key 查询的函数。- 类引用
TSubclassOf、软引用TSoftClassPtr分清"立即加载/按需加载"。 - DataAsset 加
BlueprintType,让蓝图直接读配置,闭环配置流。
