参考文章:
http://api.unrealengine.com/CHN/Programming/Introduction/index.html
- 属性从载入过程被初始化后,才会对每秒伤害数值进行计算。虚幻编辑器中的运行时变更并非原因所在。因为目标对象在编辑器中被更改时引擎将对其进行通知,所以该问题拥有简单的解决方法。以下代码显示派生值在编辑器中发生变化时进行计算所需要添加的钩。
void AMyActor::PostInitProperties()
{
Super::PostInitProperties();
CalculateValues();
}
void AMyActor::CalculateValues()
{
DamagePerSecond = TotalDamage / DamageTimeInSeconds;
}
#if WITH_EDITOR
void AMyActor::PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent)
{
CalculateValues();
Super::PostEditChangeProperty(PropertyChangedEvent);
}
#endif
- PostInitProperties() 调用链挂钩即可基于设计师设置的数值创建默认值。
- PostEditChangeProperty() 法存在于编辑器特有的 #ifdef 中。
这是为了用游戏必需的代码进行游戏构建,并删除使可执行文件容量无谓变大的多余代码。
UFUNCTION(BlueprintCallable, Category="Damage")
void CalculateValues();
UFUNCTION() 宏把 C++ 函数对反射系统公开。BlueprintCallable 选项将其对蓝图虚拟机公开。每个对蓝图公开的函数都需要与其相关的类型,右键单击快捷菜单才能正常使用。下图显示了类型对快捷菜单的影响。
UFUNCTION(BlueprintImplementableEvent, Category="Damage")
void CalledFromCpp();
UFUNCTION(BlueprintNativeEvent, Category="Damage")
void CalledFromCpp();
void AMyActor::CalledFromCpp_Implementation()
{
}
这几个方法没有完全理解它的作用,以后需要使用的时候再来学习
游戏性类:对象、Actor 和组件
多数游戏性类派生自 4 个主要类型。它们是 UObject、AActor、UActorComponent 和 UStruct。
虚幻对象(UObject)
虚幻引擎中的基础构建块被称作 UObject。此类结合 UClass 提供引擎中最重要的若干基础服务:
- 属性和方法反射
- 属性序列化
- 垃圾回收
- 按命名查找 UObject
- 可配置属性数值
- 属性和方法网络支持
派生自 UObject 的每个类拥有一个为其创建的单例 UClass,此对象包含关于类实例的所有元数据。UObject 和 UClass 是游戏性对象在其生命期中执行所有操作的根源。区分 UClass 和 UObject 的最佳方式:UClass 描述 UObject 实例的组成、可用于序列化的属性、网络等。多数的游戏性开发不会直接从 UObject 进行派生,而从 AActor 和 UActorComponent 进行派生。编写游戏性代码无需了解 UClass/UObject 的工作细节。但了解这些系统的存在也会有所帮助。
AActor
AActor 是作为游戏体验一部分的对象。AActor 将被设计师放置在关卡中,或通过游戏性系统在运行时创建。所有可放入关卡的对象均延展自此类。范例有 AStaticMeshActor、ACameraActor 和 APointLight actor。AActor 派生自 UObject,因此可使用上一部分列出的所有标准功能。可通过游戏性代码(C++ 或蓝图)显式销毁 AActor。
AActor 拥有一系列事件,可在生命周期中进行调用。以下列表是说明生命周期的简化事件集。
- BeginPlay - 对象首次出现在游戏进程中时调用
- Tick - 每帧调用一次,在一段时间内执行操作
- EndPlay - 对象离开游戏进程时调用
我们拥有一个用于 actor 生成的方法 - UWorld::SpawnActor()。一旦 actor 成功生成后,它的 BeginPlay() 方法将被调用,下一帧将出现 Tick()。一旦 actor 的生命期完结,即可调用 Destroy() 将其销毁。在此过程中将调用 EndPlay(),在此可设置自定义销毁逻辑。控制 actor 存在时长的另一个选项是使用寿命成员。可在对象的构建函数中设置时间段,或通过运行时的其他代码进行设置。时间量耗尽后,actor 将自动调用 Destroy()。
基础标记:
- UCLASS() 告知虚幻引擎生成类的反射数据。类必须派生自 UObject。
- USTRUCT() 告知虚幻引擎生成结构体的反射数据。
- GENERATED_BODY() UE4 使用它替代为类型生成的所有必需样板文件代码。
- UPROPERTY() 使 UCLASS 或 USTRUCT 的成员变量可用作 UPROPERTY。UPROPERTY 用途广泛。它允许变量被复制、被序列化,并可从蓝图中进行访问。垃圾回收器还使用它们来追踪对 UObject 的引用数。
- UFUNCTION() 使 UCLASS 或 USTRUCT 的类方法可用作 UFUNCTION。UFUNCTION 允许类方法从蓝图中被调用,并在其他资源中用作 RPC。
UPROPERTY()标记:
- Blueprintable 此类可由蓝图延展。
- BlueprintReadOnly 此属性只可从蓝图读取,不可写入。
- Category 定义此属性出现在编辑器 Details 视图下的部分。用于组织。
- BlueprintCallable 可从蓝图调用此函数。
命名规范
- 派生自 Actor 的类前缀为 A,如 AController。
- 派生自 对象 的类前缀为 U,如 UComponent。
- 枚举 的前缀为 E,如 EFortificationType。
- 接口 类的前缀通常为 I,如 IAbilitySystemInterface。
- 模板 类的前缀为 T,如 TArray。
- 派生自 SWidget(Slate UI)的类前缀为 S,如 SButton。
- 其余类的前缀均为 字母 F ,如 FVector。
UE4中的数字类型
- int8/uint8 :8 位带符号/不带符号 整数
- int16/uint16 :16 位带符号/不带符号 整数
- int32/uint32 :32 位带符号/不带符号 整数
- int64/uint64 :64 位带符号/不带符号整数
字符串
FString :
FString 是一个可变字符串,类似于 std::string。
FText :
FText 与 FString 相似,但用于本地化文本。
FName
FName 将经常反复出现的字符串保存为辨识符,以便在对比时节约内存和 CPU 时间。
TCHAR
TCHARs 用于存储不受正在使用的字符集约束的字符。
容器
容器也是类,它们的主要功能是存储数据集。常见的类有 TArray、TMap 和 TSet。它们的大小均为动态,因此可变为所需的任意大小。
TArray
在这三个容器中,虚幻引擎 4 使用的主要容器是 TArray。它的作用和 std::vector 相似,但却多出许多功能。以下是一些常规操作:
TArray<AActor*> ActorArray = GetActorArrayFromSomewhere();
// 告知当前 ActorArray 中保存的元素(AActors)数量。
int32 ArraySize = ActorArray.Num();
// TArrays 从零开始(第一个元素在索引 0 处)
int32 Index = 0;
// 尝试获取在给定索引处的元素
TArray* FirstActor = ActorArray[Index];
// 在阵列末端添加一个新元素
AActor* NewActor = GetNewActor();
ActorArray.Add(NewActor);
// 只有元素不在阵列中时,才在阵列末端添加元素
ActorArray.AddUnique(NewActor); // 不会改变阵列,因为 NewActor 已被添加
// 移除阵列中所有 NewActor 实例
ActorArray.Remove(NewActor);
// 移除特定索引处的元素
// 索引上的元素将被下调一格,以填充空出的位置
ActorArray.RemoveAt(Index);
// RemoveAt 的高效版,但无法保持元素的排序
ActorArray.RemoveAtSwap(Index);
// 移除阵列中的所有元素
ActorArray.Empty();
TMap
- TMap 是键值对的合集,与 std::map 相似。TMap 可基于元素的键快速寻找、添加、并移除元素。只要键拥有为其定义的 GetTypeHash 函数(稍后对此进行了解),即可使用任意类型的键。
- 假设您创建了一个基于网格的桌面游戏,需要保存并询问每个方格上的块。通过 TMap 即可轻松完成。如棋盘尺寸较小且保持不变,还存在更加高效的处理方式。但出于范例的缘故,暂且谈到这里吧!
TSet
TSet 保存唯一值的合集,与 std::set 相似。TArray 通过 AddUnique 和 Contains 方法可用作集。然而 TSet 可更快实现这些操作,但无法像 TArray 那样将它们用作 UPROPERTY。TSet 不会像 TArray 那样将元素编入索引。