使用虚幻引擎中的C++导论(三)
第一,这篇是我翻译的虚幻4官网的新手编程教程,原文传送门,有的翻译不太好,但大体意思差不多,请支持我O(∩_∩)O谢谢。
第二,某些细节操作,这篇文章省略了,如果有不懂的,去看其他教程。
第三,没有C++编程经验,但有其他OOP语言经验的朋友。要先了解C++的基础。
继续深入研究
好了,很显然你想要知道更多。让我们更深入的了解虚幻引擎是怎么工作的。
虚幻反射系统
Blog Post: Unreal Property System (Reflection)
游戏类使用特殊的标记,在我们继续讲解之前,让我们了解一些虚幻属性系统的基础知识。虚幻4引擎使用其自身的反射机制实现动态特性,诸如,垃圾回收机制,序列化,网络复制,蓝图/C++通信。这些特性是可选的,意味着你可以正确的把这些功能组合进你的类型,否则虚幻会忽略它们,而不是对他们产生反射数据。下面是基础标记的大致概括。
- UCLASS() - 让虚幻为类生产反射数据,这个类必须继承UObject。
- USTRUCT() - 让虚幻为结构体生产反射数据。
- GENERATED_BODY() - 为该类生产必要的样本代码
- UPROPERTY() - 通过UPROPERTY标记,让UCLASS 类或者USTRUCT 结构体的成员变量可用。UPROPERTY 标记有很多种用法。它允许变量可以复制、序列化、被蓝图访问。它同样被用于垃圾回收机制,去回收UCLASS 类。
- UFUNCTION() - 通过UPROPERTY标记,让UCLASS 类或者USTRUCT 结构体的成员变量可用。UFUNCTION 标记可以让方法被蓝图访问调用,并作为远程过程调用协议(RPC)的类方法,等等。
下面是个使用UCLASS标签的例子:
#include "MyObject.generated.h"
UCLASS(Blueprintable)
class UMyObject : public UObject
{
GENERATED_BODY()
public:
MyUObject();
UPROPERTY(BlueprintReadOnly, EditAnywhere)
float ExampleProperty;
UFUNCTION(BlueprintCallable)
void ExampleFunction();
};
若文件包含“MyClass.generated.h”。虚幻引擎会生产反射信息并且注入这个文件。在你的文件类型中,必须包含这个头文件。
你还可以注意到,我们同样加了特定的标志。我已经添加了一些较为常见的示范。这允许我们指定我们类型有的某种行为。
- Blueprintable - 类可以被蓝图扩展。
- BlueprintReadOnly - 属性只能被蓝图读取,不能修改。
- Category - 定义虚幻编辑器中细节面板上属性所在的分类。用于组织属性需要。
- BlueprintCallable - 方法可被蓝图调用。
有太多特定的标志,下面的链接可以看到这些标志的详细内容。
对象/Actor 迭代器
对于迭代UObject 类型和其子类的所有实例,对象迭代器 是非常有用的工具。
// Will find ALL current UObjects instances
for (TObjectIterator<UObject> It; It; ++It)
{
UObject* CurrentObject = *It;
UE_LOG(LogTemp, Log, TEXT("Found UObject named: %s"), *CurrentObject.GetName());
}
你可以限定查找的范围通过为迭代器提供更多特定类型,假设你有一个类叫UMyClass,它继承UObject,你可以像下面的代码一样查询到所有实例:
for (TObjectIterator<UMyClass> It; It; ++It)
{
// ...
}
警告:在PIE(Play In Editor,即在编辑器中点击“Play”按钮)中使用迭代器会发生意外的结果。在编辑器装载时,对象迭代器将为你的世界实例,返回所有已经生成的UObjects 对象,除了那些只是正在使用的编辑器(材质,animation等编辑器?)。
Actor迭代器与对象迭代器有很多共同点,但是它仅支持继承AActor的对象。Actor迭代器没有下文所述的问题,并且将只能返回近期的游戏世界实例对象。
当生成一个Actor迭代器时,你需要一个指针指向世界实例UWorld,很多UObject 类,比如,APlayerController类支持GetWorld()方法来帮助开发者。如果你不确定这个类是否实现了GetWorld()方法 ,你可以在一个UObject 类中使用ImplementsGetWorld() 方法检查。
APlayerController* MyPC = GetMyPlayerControllerFromSomewhere();
UWorld* World = MyPC->GetWorld();
// Like object iterators, you can provide a specific class to get only objects that are
// or derive from that class
for (TActorIterator<AEnemy> It(World); It; ++It)
{
// ...
}
(由于AActor 继承UObject,你可以用TObjectIterator 在很多AActor中查找实例,只是需要小心PIE)