note_01 函数返回引用
函数返回引用与返回指针本质一样都是返回地址, 否则函数将返回数据的拷贝
ps: 不要将局部(函数中)创建的引用作为函数返回值
// 全局变量
int val = 10;
// 定义函数返回引用
int& RetValRef()
{
return val;
}
// 将函数作为左值使用时(使用引用接收返回值),返回地址
// 本质上发生 int* const v1 = &val;
int& v1 = RetValRef();
// 引用 v1 作为左值可修改 val 的值
v1 = 20;
// 将函数作为右值使用时,返回该地址指向的值
// 本质上发生调用解引用 *val 对 v2 进行赋值
int v2 = RetValRef();
UFUNCTION 和 委托想返回 UStruct 类型的地址, 只能使用返回引用的方式.简单点说就是结构体在蓝图中要么是值传递要么是引用.
多播委托在返回结构体引用时, 不支持 non-const references
但 UClass 可以这两种情况都可以返回裸指针
// FLevelUpInfo is USTRUCT type
UFUNCTION()
// Inappropriate '*' on variable of type 'FLevelUpInfo'
FLevelUpInfo* GetLevelUpInfoByXP(int32 XP);
// OK
FLevelUpInfo& GetLevelUpInfoByXP(int32 XP);
// UClass可以返回裸指针
UFUNCTION()
AActor* GetEnemyActor();
// 多播委托在返回结构体引用时, 不支持 non-const references
// NewValue 如果不加 const 要报错, 但 MyActor 返回指针 OK
DECLARE_DYNAMIC_MULTICAST_DELEGATE_ThreeParams(FSomeDelegate, const FAttributeInfoData&, Data, AActor*, MyActor, const FVector&, NewValue);
note_02 IsValid
IsValid 既判断 nullptr 又判断是否准备被销毁(等待垃圾回收)
// Enemy 有可能会被销毁时使用 IsValid
if(IsValid(Enemy)) {...}
// 如果只是简单的 Proerty 等可使用
if(MaterialInstance) {...}
note_03 BlueprintCallable 函数的引用参数作为输入PIN
对于非 const 引用的参数在蓝图节点中默认将作为输出 Pin
// TargetLocation 将作为输入 pin
UFUNCTION(BlueprintCallable)
void SpawnProjectile(FVector& TargetLocation);
若要将 TargetLocation 作为输入 Pin, 可使用下面方法
// 将 TargetLocation 定义为 const
UFUNCTION(BlueprintCallable)
void SpawnProjectile(const FVector& TargetLocation);
// 或,使用宏
UFUNCTION(BlueprintCallable)
void SpawnProjectile(UPARM(ref) FVector& TargetLocation);
note_04 接口
对于无返回值的接口可以在 Event Graph 中实现 (类似 custom event),对于有返回值的接口需要通过 Override Function 来实现.
在蓝图中调用接口时可像静态函数一样调用 (不需要Cast),如果 Target 未实现该函数则会略过该函数的调用
/**
* 定义为 BlueprintImplementableEvent 的函数
* 表明该方法将只能在蓝图中实现,不能在 C++ 中实现
* 函数不能加 virtual,会导致编译报错
* 使用 const 将引用参数变更为输入 PIN (否则会作为输出 PIN)
* 接口中的 BlueprintCallable 表明该函数将作为静态函数可在蓝图中直接调用
*/
UFUNCTION(BlueprintImplementableEvent, BlueprintCallable)
void DoMotionWarp(const FVector& FacingTarget);
/**
* 定义为 BlueprintNativeEvent 的函数
* 表明即可在蓝图中实现, 也可在 C++ 中定义默认实现
* 函数不能加 virtual,会导致编译报错
* 在 C++ 中实现该函数需要加上 _Implementation
*/
UFUNCTION(BlueprintNativeEvent, BlueprintCallable)
void SetCombatTarget(AActor* InCombatTarget);
在 C++ 中调用 BlueprintNativeEvent 接口,需要调用 Native C++ 实现的版本
// 判断是否实现接口
if (Actor->Implements<UCombatInterface>())
{
// 调用 Native C++ 的实现
if (!ICombatInterface::Execute_IsDead(Actor))
{
OutActors.AddUnique(Actor);
}
}
在接口中使用 BlueprintNativeEvent 返回引用时发现报错(返回类型不匹配)
// 报错
UFUNCTION(BlueprintNativeEvent, BlueprintCallable)
TArray<FTaggedMontage>& GetAttackMontages();
// 改这样实现
UFUNCTION(BlueprintNativeEvent, BlueprintCallable)
void GetAttackTaggedMontages(TArray<FTaggedMontage>& OutTaggedMontages);
note_05 QUICK TIPS
Ctrl + 0~10 创建摄像机 Bookmark
Ctrl + MMB Drag 切换视图 Front / Top …
Ctrl + LMB 操控X轴 / Ctrl + RMB 操控Y轴 / Ctrl + LMB&RMB 操控Z轴
Ctrl + E 编辑选中物体
Ctrl + MMB 临时修改物体轴点
Shift + Click PIN 连接节点
Alt + Click PIN or Wire 移除连接
K 保存模拟状态, 退出模拟或PIE之后不恢复, 只对静态物体起效
Ctrl + P 打开资源窗口 “Open Asset”
note_06 Delegate 小坑
DYNAMIC delegate 参数需要加名称
/* DYNAMIC delegate 参数需要加名称 */
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FOnFloatValueChangedSignature, float, Value);
非 DYNAMIC delegate 参数不能加名称, 否则报错 ‘参数过多’
/* 推荐参考官方定义方式 */
DECLARE_MULTICAST_DELEGATE_OneParam(FOnFloatValueChangedNative, float /* NewValue */);
note_07 智能指针
Shared Pointers, Weak Pointers, and Unique Pointers 不能用于 UObject 的类型
UObject 使用虚幻自己的反射系统管理