# Actor生命周期

参考文档:

Gameplay框架预览 Actors生命周期

可以把Actor看成是Level中的基本单位。

Actor的体系如下:

ActorHierarchy

# 代码追踪

下面是在UE4中调试代码来追踪Actor的生命周期,注意如果出现下面错误:

The Breakpoint will not currently be hit. No executable code associated with this line

需要下载该引擎对应的调试符号。

# 引擎启动

下面是拿4.26引擎来做的调试:引擎启动会执行:

  1. 执行UE4主入口程序Engine\Source\Runtime\Launch\Private\Windows\LaunchWindows.cpp中的WinMain函数。
  2. 执行Engine\Source\Runtime\Launch\Private\Launch.cpp中的GuardedMain。
  3. 执行Engine\Source\Editor\UnrealEd\Private\UnrealEdGlobals.cpp中的EditorInit。
  4. 执行Engine\Source\Runtime\Launch\Private\LaunchEngineLoop.cpp中的FEngineLoop::Init()。
  5. 执行Engine\Source\Editor\UnrealEd\Private\UnrealEdEngine.cpp中的Init。
  6. 执行Engine\Source\Editor\UnrealEd\Private\EditorEngine.cpp中的Init。

# Actor生命周期

  1. 当在UE4编辑器中点击Play时,旧版本会执行EditorEngine中的PlayInEditor(),从4.25开始,这个入口被废弃了,取而代之的是StartPlayInEditorSession(),在这个里面加断点。
  2. 在UEditorEngine::CreateInnerProcessPIEGameInstance中:
    1. 来生成GameInstance实例。
    2. GameInstance实例会调用InitializeForPlayInEditor来初始化编辑器。
      1. 获取WorldContext,如果没有则创建一个。
      2. 通过复制来创建一个PIE World。
      3. 如果创建成功则给新World赋予当前GameInstance,并添加到WorldContext中去。
    3. GameInstance->StartPlayInEditorGameInstance。开始在EditorGameInstance中运行。
      1. PlayWorld->SetGameMode(URL):初始化GameMode。如果GameWorldSetting中设置了,则使用该GameMode,如果没有则使用默认的。
      2. PlayWorld->CreateAISystem():创建AI系统。
      3. PlayWorld->InitializeActorsForPlay(URL):初始化Actors。
        1. AreActorsInitialized():判断Actor是否被初始化了。
          1. 初始化网络Actors。
          2. ULevel::RouteActorInitialize():初始化Actor以及它们身上的components。
            1. Actor::PreInitializeComponents():预初始化组件,如果是PlayerController,则打开输入,其他则要手动打开并Register才行。
            2. Actor->InitializeComponents():初始化组件。
            3. AActor::PostInitializeComponents():如果组件要复制的话进行网络复制。
      4. FNavigationSystem::AddNavigationSystemToWorld():生成导航系统。
      5. PlayWorld->BeginPlay():开始游戏
        1. GetAuthGameMode():获取服务器GameMode。
        2. GameMode->StartPlay():使用GameMode开始游戏。执行BeginPlay。
          1. GameState->HandleBeginPlay()
            1. GetWorldSettings()->NotifyBeginPlay()
              1. It->DispatchBeginPlay(bFromLevelLoad);
                1. BeginPlay();
                  1. RegisterAllActorTickFunctions():注册Tick事件。
                  2. 处理组件中的BeginPlay。
                  3. ReceiveBeginPlay():执行蓝图中的BeginPlay。
        3. GetAISystem()->StartPlay():AI系统开始工作。

# Actor生成流程

下面来看下使用SpawnActor的执行流程:

  1. AActor::GetWorld():获取当前World实例。
  2. UWorld::SpawnActor():开始生成
    1. check( CurrentLevel ); 检查是否是当前关卡。
    2. if( Class->HasAnyClassFlags(CLASS_Deprecated) ):当前类是否是丢弃的。
    3. if( Class->HasAnyClassFlags(CLASS_Abstract) ):当前类是否是抽象类(UClass(Abstract))。
    4. if( !Class->IsChildOf(AActor::StaticClass()) ):当前类是否是一个Actor。
    5. if (SpawnParameters.Template != NULL && SpawnParameters.Template->GetClass() != Class):模板类不匹配生成类。
    6. if (bIsRunningConstructionScript && !SpawnParameters.bAllowDuringConstructionScript):是否在构造脚本中运行。
    7. if (LevelToSpawnIn == NULL):查看要生成Actor的Level。
    8. if (SpawnParameters.bNoFail):检测周围是否有其他碰撞,如果有的话可选择生成或不生成。
    9. NewObject<AActor>():使用NewObject来生成类。
    10. LevelToSpawnIn->Actors.Add( Actor ):将Actor添加到当前Level的Actors容器中。
    11. Actor->PostSpawnInitialize():生成Actor后初始化过程。获取创建时间,设置网络规则,设置Owner。它的一般流程如下:
      1. Actor sets up the basics.
      2. Actor gets PreInitializeComponents()
      3. Actor constructs itself, after which its components should be fully assembled
      4. Actor components get OnComponentCreated
      5. Actor components get InitializeComponent
      6. Actor gets PostInitializeComponents() once everything is set up
    12. AddNetworkActor( Actor ):添加网络的Actor。

# Actor销毁流程

下面是Actor的销毁过程:

  1. IsPendingKillPending():是否被标记为被销毁状态。
  2. World->DestroyActor( this, bNetForce, bShouldModifyLevel ):通过当前世界来进行销毁。
    1. if (ThisActor->IsPendingKillPending()):判断是否已经标记为被销毁。
    2. UWorld::IsGameWorld():判断是否为GameWorld。
    3. 判断当前是否能销毁网络Actor,只有服务端能销毁网络Actor。
    4. IStreamingManager::Get().NotifyActorDestroyed( ThisActor ):通知Actor被销毁。
    5. ThisActor->Destroyed():告诉Actor它是否要被销毁。
      1. RouteEndPlay(EEndPlayReason::Destroyed):进行销毁。
        1. EndPlay(EndPlayReason);
          1. ReceiveEndPlay(EndPlayReason):组件执行EndPlay。
    6. ThisActor->GetAttachedActors(AttachedActors):获取AttachedActor。
    7. 判定我们被销毁的Actor是否绑定到其他Actor上边,如果是的话Detach。
    8. ThisActor->ClearComponentOverlaps():删除自己的组件。
    9. 通知网络,当前Actor已经被销毁。
    10. RemoveActor( ThisActor, bShouldModifyLevel ):把Actor从Actor列表中移除。
    11. ThisActor->UnregisterAllComponents():清除Actor的所有组件。
    12. 标记Actor为Pending Kill。
    13. 注销Actor的Tick函数。