UE4 启动过程 WinMain ... 点击play...
参照官方文档流程图
用源码编译的UE4(4.22) 打断点逐步Follow......
Engine\Source\Runtime\Launch\Private\Windows\LaunchWindows.cpp
int32 WINAPI WinMain( _In_ HINSTANCE hInInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ char*, _In_ int32 nCmdShow )
ErrorLevel = GuardedMain( CmdLine, hInInstance, hPrevInstance, nCmdShow );
}
Engine\Source\Runtime\Launch\Private\Launch.cpp
#if PLATFORM_WINDOWS
int32 GuardedMain( const TCHAR* CmdLine, HINSTANCE hInInstance, HINSTANCE hPrevInstance, int32 nCmdShow )
#else
int32 GuardedMain( const TCHAR* CmdLine )
#endif
int32 ErrorLevel = EnginePreInit( CmdLine );
#if WITH_EDITOR
if (GIsEditor)
ErrorLevel = EditorInit(GEngineLoop);
}
Engine\Source\Editor\UnrealEd\Private\UnrealEdGlobals.cpp
int32 EditorInit( IEngineLoop& EngineLoop )
int32 ErrorLevel = EngineLoop.Init();
}
Engine\Source\Runtime\Launch\Private\LaunchEngineLoop.cpp
int32 FEngineLoop::Init()
SCOPED_BOOT_TIMING("GEngine->Start()");
GEngine->Start();
}
继续看 int32 GuardedMain() 函数
Engine\Source\Runtime\Launch\Private\Launch.cpp
#if PLATFORM_WINDOWS
int32 GuardedMain( const TCHAR* CmdLine, HINSTANCE hInInstance, HINSTANCE hPrevInstance, int32 nCmdShow )
#else
int32 GuardedMain( const TCHAR* CmdLine )
#endif
int32 ErrorLevel = EnginePreInit( CmdLine );
#if WITH_EDITOR
if (GIsEditor)
ErrorLevel = EditorInit(GEngineLoop);
//这里继续
while( !GIsRequestingExit )
EngineTick();
}
...
#if PLATFORM_WINDOWS || PLATFORM_MAC || PLATFORM_UNIX
FEngineLoop GEngineLoop;
* Ticks the engine loop
void EngineTick( void )
GEngineLoop.Tick();
}
Engine\Source\Runtime\Launch\Private\LaunchEngineLoop.cpp
void FEngineLoop::Tick()
// main game engine tick (world, game objects, etc.)
GEngine->Tick(FApp::GetDeltaTime(), bIdleMode);
}
Engine\Source\Editor\UnrealEd\Private\UnrealEdEngine.cpp
UCLASS(config=Engine, transient)
class UNREALED_API UUnrealEdEngine : public UEditorEngine, public FNotifyHook
void UUnrealEdEngine::Tick(float DeltaSeconds, bool bIdleMode)
Super::Tick( DeltaSeconds, bIdleMode );
}
Engine\Source\Editor\UnrealEd\Private\EditorEngine.cpp
UEditorEngine::Tick( float DeltaSeconds, bool bIdleMode )
// kick off a "Play From Here" if we got one
if (bIsPlayWorldQueued)
StartQueuedPlayMapRequest();
}
当点击play时,tick便会检测到,执行StartQueuedPlayMapRequest()函数
Engine\Source\Editor\UnrealEd\Private\PlayLevel.cpp
void UEditorEngine::StartQueuedPlayMapRequest()
// Launch standalone PIE session
if (bPlayOnLocalPcSession)
else if(bPlayUsingLauncher)
{...}
PlayInEditor( GetEditorWorldContext().World(), bWantSimulateInEditor );
}
void UEditorEngine::PlayInEditor( UWorld* InWorld, bool bInSimulateInEditor, FPlayInEditorOverrides Overrides )
if (bInSimulateInEditor || (PlayNetMode == EPlayNetMode::PIE_Standalone && PlayNumberOfClients <= 1 && !bSupportsOnlinePIE) || !CanRunUnderOneProcess)
UGameInstance* const GameInstance = CreatePIEGameInstance(PIEInstance, bInSimulateInEditor, bAnyBlueprintErrors, bStartInSpectatorMode, false, bUseVRPreviewForPlayWorld, PIEStartTime);
}
UGameInstance* UEditorEngine::CreatePIEGameInstance(int32 InPIEInstance, bool bInSimulateInEditor, bool bAnyBlueprintErrors, bool bStartInSpectatorMode, bool bRunAsDedicated, bool bPlayStereoscopic, float PIEStartTime)
UGameInstance* GameInstance = NewObject<UGameInstance>(this, GameInstanceClass);
const FGameInstancePIEResult InitializeResult = GameInstance->InitializeForPlayInEditor(InPIEInstance, GameInstanceParams);
}
Engine\Source\Runtime\Engine\Private\GameInstance.cpp
FGameInstancePIEResult UGameInstance::InitializeForPlayInEditor(int32 PIEInstanceIndex, const FGameInstancePIEParameters& Params)
Init();
void UGameInstance::Init()
if (!IsRunningCommandlet())
UClass* SpawnClass = GetOnlineSessionClass();
OnlineSession = NewObject<UOnlineSession>(this, SpawnClass);
if (OnlineSession)
OnlineSession->RegisterOnlineDelegates();
}
返回 UEditorEngine::CreatePIEGameInstance(........) 函数 (Engine\Source\Editor\UnrealEd\Private\PlayLevel.cpp )
UGameInstance* UEditorEngine::CreatePIEGameInstance(int32 InPIEInstance, bool bInSimulateInEditor, bool bAnyBlueprintErrors, bool bStartInSpectatorMode, bool bRunAsDedicated, bool bPlayStereoscopic, float PIEStartTime)
{ ...
UGameInstance* GameInstance = NewObject<UGameInstance>(this, GameInstanceClass);
const FGameInstancePIEResult InitializeResult = GameInstance->InitializeForPlayInEditor(InPIEInstance, GameInstanceParams);
//返回这里
const FGameInstancePIEResult StartResult = GameInstance->StartPlayInEditorGameInstance(NewLocalPlayer, GameInstanceParams);
}
Engine\Source\Runtime\Engine\Private\GameInstance.cpp
FGameInstancePIEResult UGameInstance::StartPlayInEditorGameInstance(ULocalPlayer* LocalPlayer, const FGameInstancePIEParameters& Params)
// for clients, just connect to the server
if (PlayNetMode == PIE_Client)
{... }
// we're going to be playing in the current world, get it ready for play
UWorld* const PlayWorld = GetWorld();
if (!PlayWorld->SetGameMode(URL))
// Setting the game mode failed so bail
return FGameInstancePIEResult::Failure(NSLOCTEXT("UnrealEd", "Error_FailedCreateEditorPreviewWorld", "Failed to create editor preview world."));
PlayWorld->BeginPlay();
}
其中 PlayWorld->SetGameMode(URL) 设置了AuthorityGameMode属性, UWorld::BeginPlay() 会用到:
Engine\Source\Runtime\Engine\Private\World.cpp
bool UWorld::SetGameMode(const FURL& InURL)
if( IsServer() && !AuthorityGameMode )
AuthorityGameMode = GetGameInstance()->CreateGameModeForURL(InURL);
if( AuthorityGameMode != NULL )
return true;
UE_LOG(LogWorld, Error, TEXT("Failed to spawn GameMode actor."));
return false;
return false;
}
void UWorld::BeginPlay()
AGameModeBase* const GameMode = GetAuthGameMode();
if (GameMode)
GameMode->StartPlay();
if (GetAISystem())
GetAISystem()->StartPlay();
}
Engine\Source\Runtime\Engine\Private\GameModeBase.cpp
void AGameModeBase::StartPlay()
GameState->HandleBeginPlay();
}
Engine\Source\Runtime\Engine\Private\GameStateBase.cpp
void AGameStateBase::HandleBeginPlay()
bReplicatedHasBegunPlay = true;
GetWorldSettings()->NotifyBeginPlay();
GetWorldSettings()->NotifyMatchStarted();
}
Engine\Source\Runtime\Engine\Private\WorldSettings.cpp
/**
* Called from GameStateBase, calls BeginPlay on all actors
void AWorldSettings::NotifyBeginPlay()
UWorld* World = GetWorld();
if (!World->bBegunPlay)
for (FActorIterator It(World); It; ++It)
SCOPE_CYCLE_COUNTER(STAT_ActorBeginPlay);
It->DispatchBeginPlay();
World->bBegunPlay = true;
* Called from GameStateBase, used to notify native classes of match startup (such as level scripting)