GamePlay世界框架图
AWorldSetting
世界设定,每个关卡单独有一个世界设定(并非整个游戏世界共享一个世界设定)
在WorldSetting可以设置这个世界各种属性,尤其是我们经常用到的 GameMode
AGamdeModeBase
包含了一个关卡开始诞生的各种Actor对象模板(APawn,AHUD,APlayerController,AGameStateBase等等)
ALevelScriptActor
关卡Actor, 差不多等同于关卡蓝图,如果你是C++偏执党,不想直接在关卡蓝图用蓝图编辑逻辑的话,可以继承ALevelScriptActor类,然后在这个ALevelScriptActor子类编写
ULevel
也是关卡类,不过不继承Actor,而是UObject,起到把AWordSetting和ALevelScriptActor管理起来的作用,成为真正的关卡
ULevel保存了Actors数组,也就是该关卡的所有Actor
/** Array of all actors in this level, used by FActorIteratorBase and derived classes */
TArray<AActor*> Actors;
UWorld
整个世界(目前只谈游戏世界),统领所有的游戏关卡,一个游戏世界中拥有很多关卡。
所有UWorld中包含了ULevel数组:
/** Array of levels currently in this world. Not serialized to disk to avoid hard references. */
UPROPERTY(Transient)
TArray<class ULevel*> Levels;
此外,游戏世界还包含了AGameModeBase, AGameStateBase, UGameInstance等游戏性的类。
UGameInstance
游戏实例,整个游戏一直存在的类对象,里面保存各种对象的生命周期可以跨越所有的关卡不被GC,也就是在切换关卡时,UGameInstance里的变量也不会GC。
整个世界的遍历
AActor的遍历
(1)用TActorIterator迭代器,其中模板类必须是AActor或者AActor的子类,获取整个世界的该类对象
UWorld* pWorld = GetWorld();
if (NULL == pWorld)
return;
for (TActorIterator<AActor> it(pWorld); it; ++it)
{
UE_LOG(LogTemp, Warning, TEXT("actor name is %s"), *it->GetName());
}
像UGameplayStatics库里面提供的各种获取Actor的接口GetAllActorsOfClass,GetAllActorsWithInterface,GetAllActorsWithTag等等都是使用TActorIterator来遍历Actor的。
(2)依据上面我们对ULevel,UWorld的理解,对UWorld的每一个Level的Actor数组进行遍历:
TArray<ULevel*> arrayLevel = pWorld->GetLevels();
for (int indexLevel = 0; indexLevel < arrayLevel.Num(); ++indexLevel)
{
ULevel* pLevel = arrayLevel[indexLevel];
if (pLevel)
{
TArray<AActor*> arrayActor = pLevel->Actors;
for (int indexActor = 0; indexActor < arrayActor.Num(); ++indexActor)
{
UE_LOG(LogTemp, Warning, TEXT("actor name is %s"), *arrayActor[indexActor]->GetName());
}
}
}
UObject的遍历
遍历所有UObject有类似TActorIterator的迭代器,叫做TObjectIterator,这个迭代器可以遍历所有UObject和UObject的子类对象,包括刚才提到的Actor类等等。不过在编辑器模式下迭代得到的UObject并非单单是游戏的世界里的UObject,也包含编辑器世界等等的UObject。
for (TObjectIterator<AActor> it; it; ++it)
{
UE_LOG(LogTemp, Warning, TEXT("actor name is %s"), *it->GetName());
}
遍历AController,APlayerController,APawn等等
有时候我们经常想遍历整个游戏中的如APawn,AController对象,我们除了上面的接口外,还可以直接使用
UWorld帮我们提前定义好的迭代器
比如游戏中APawn的遍历:
for (FConstPawnIterator it = pWorld->GetPawnIterator(); it; ++it)
{
APawn* pPawn = it->Get();
if (pPawn)
{
UE_LOG(LogTemp, Warning, TEXT("pPawn name is %s"), *pPawn->GetName());
}
}
像获取世界第一个APlayerController其实也是调用了迭代器,
APlayerController* UWorld::GetFirstPlayerController() const
{
APlayerController* PlayerController = NULL;
if( GetPlayerControllerIterator() )
{
PlayerController = GetPlayerControllerIterator()->Get();
}
return PlayerController;
}