UE踩坑记 日志

UE5.5通过FWorldPartitionActorDescInstance加载Actor

playerzhou 2 回复
  • UE5.5目前使用FWorldPartitionActorDescInstance来管理world partition下的actor信息和逻辑操作,原来的FWorldPartitionActorDesc仅储存数据

  • FWorldPartitionActorDescInstance::GetActor函数不会触发加载,仅用于获取已加载或处于异步加载状态的actor,但如果actor处于异步加载状态时,会触发FWorldPartitionActorDescInstance::FlushAsyncLoad等待加载完成

  • UE5.5删除了FWorldPartitionActorDescInstance::Load接口并将FWorldPartitionActorDesc::Load设为空函数,仅在private内提供了异步加载接口,理由如下

    • World Partition Actor Descriptors:
    • Make loading functions private to make sure all code requesting actors loading state changes in the editor goes through the loading contexts.
    • Actor descriptors can now load async when using the deferred context, in preparation of editor async loading through a new async context.
  • 因此外部无法直接通过FWorldPartitionActorDescInstance加载Actor,目前UE提供了两种加载接口FWorldPartitionLoadingContext::FImmediateFWorldPartitionLoadingContext::FDeferred,分别代表同步和异步加载

  • UE5.5可通过void FWorldPartitionLoadingContext::LoadAndRegisterActor(FWorldPartitionActorDescInstance* InActorDescInstance)直接加载actor,其实现如下

    • void FWorldPartitionLoadingContext::LoadAndRegisterActor(FWorldPartitionActorDescInstance* InActorDescInstance)
      {
      check(!InActorDescInstance->bIsRegisteringOrUnregistering);
      InActorDescInstance->bIsRegisteringOrUnregistering = true;
      
      ActiveContext->RegisterActor(InActorDescInstance);
      }
    • 其中默认情况下,采用同步加载:

    • FWorldPartitionLoadingContext::FImmediate FWorldPartitionLoadingContext::DefaultContext;
      FWorldPartitionLoadingContext::IContext* FWorldPartitionLoadingContext::ActiveContext = &DefaultContext;
  • UE在此基础上封装了类型typedef TWorldPartitionHandle<FWorldPartitionReferenceImpl> FWorldPartitionReference;,用于记录actor引用计数,并且可以根据引用计数加载和卸载actor

    • /**
      * FWorldPartitionReference will increment/decrement the hard reference count on the actor descriptor.
      * This will trigger actor loading/unloading when the hard reference counts gets to one/zero.
      */
  • 同时UE还提供了typedef TWorldPartitionHandle<FWorldPartitionHandleImpl> FWorldPartitionHandle;类型仅用于记录引用计数

    • /**
      * FWorldPartitionHandle will increment/decrement the soft reference count on the actor descriptor.
      * This won't trigger any loading, but will prevent cleanup of the actor descriptor when destroying an
      * actor in the editor.
      */
      typedef TWorldPartitionHandle FWorldPartitionHandle;
  • 因此可以通过FWorldPartitionReference ActorReference(WorldPartition, ActorDesc->GetGuid());来加载actor,在其构造函数中会记录引用计数,并触发加载任务,其内部也是调用FWorldPartitionLoadingContext::LoadAndRegisterActor实现的

  1. Yuqi

    大佬,我发现所有的这些WorldPartitionActorDesc或者LoadingContext都是WITH_EDITOR下的,也就是说利用WPHandle或者Reference加卸载actor在游戏运行时不可行,对吗?

    1. playerzhou

      world partition在运行时会把actor以cell为单位cook成streaming level,最终加载也是基于streaming level的,不再是ofoa了,再使用worldpartitionreference的话明显会有额外的开销,ue让worldpartitionreference仅在编辑器使用从逻辑上讲也是正常的选择

评论 playerzhou 撤销评论

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据