UE5.5后world partition下level instance的加载机制
playerzhou
无回复
在5.5之前,对于level instance的加载机制见https://dev.epicgames.com/documentation/en-us/unreal-engine/level-instancing-in-unreal-engine ,当level instance使用了ofpa机制时,cook时会把level里的actor打散进cell中,表现与场景中普通actor一致,若未使用ofpa机制,则是以一整个完整的level为单位进行加载
但在5.5之后,对于未使用ofpa的level,在保存前,使用
void UWorld::GetExtendedAssetRegistryTagsForSave(const ITargetPlatform* TargetPlatform, TArray<FAssetRegistryTag>& OutTags) const
{
Super::GetExtendedAssetRegistryTagsForSave(TargetPlatform, OutTags);
if (!PersistentLevel->IsUsingExternalActors())
{
TArray<FString> ActorsMetaData;
for (AActor* Actor : PersistentLevel->Actors)
{
if (IsValid(Actor) && Actor->SupportsExternalPackaging())
{
FWorldPartitionActorDescUtils::FActorDescInitParams ActorDescInitParams(Actor);
ActorsMetaData.Add(ActorDescInitParams.ToString());
}
}
if (ActorsMetaData.Num())
{
static FName NAME_ActorsMetaData(TEXT("ActorsMetaData"));
const FString ActorsMetaDataStr = FString::Join(ActorsMetaData, TEXT(";"));
OutTags.Add(UObject::FAssetRegistryTag(NAME_ActorsMetaData, ActorsMetaDataStr, UObject::FAssetRegistryTag::TT_Hidden));
}
}
}
为level的package增加ActorsMetaData
数据,将actor的信息存在package内,world partition持有的actordesccontainer初始化时
void UActorDescContainer::Initialize(const FInitializeParams& InitParams)
{
// 省略上文
// Gather external actors
{
TRACE_CPUPROFILER_EVENT_SCOPE(GetExternalAssets);
FARFilter Filter;
Filter.bRecursivePaths = true;
Filter.bIncludeOnlyOnDiskAssets = true;
Filter.PackagePaths.Add(*ContainerExternalActorsPath);
FExternalPackageHelper::GetSortedAssets(Filter, ExternalAssets);
}
// Gather non-external actors
{
TRACE_CPUPROFILER_EVENT_SCOPE(GetInternalAssets);
FARFilter Filter;
Filter.bIncludeOnlyOnDiskAssets = true;
Filter.PackageNames.Add(ContainerPackageName);
TArray<FAssetData> WorldAssetData;
AssetRegistry.GetAssets(Filter, WorldAssetData);
// Transform world assets
static FName NAME_ActorsMetaData(TEXT("ActorsMetaData"));
for (const FAssetData& AssetData : WorldAssetData)
{
FString ActorsMetaDataStr;
if (AssetData.GetTagValue(NAME_ActorsMetaData, ActorsMetaDataStr))
{
TArray<FString> ActorsMetaData;
if (ActorsMetaDataStr.ParseIntoArray(ActorsMetaData, TEXT(";")))
{
InternalAssets.Append(ActorsMetaData);
}
}
}
}
}
// 省略下文
}
从ActorsMetaData
中提取actor数据,用于生成actor desc,之后cook时即可通过actor desc将level里的actor打散至cell中
至此,对于5.5之后版本创建的level来说,无论是否开启ofpa,当其作为level instance导入world partition场景中时,它都将使用Embedded Mode,将level拆散。
但对于5.5之前创建的level,由于缺少ActorsMetaData
,仍然使用Level Streaming Mode
,以完整的level为单位进行加载,并且只需重新保存即可为level生成ActorsMetaData
,从而使用Embedded Mode
来一发吐槽