添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
相关文章推荐
奔跑的小虾米  ·  随机颜色矩阵 ...·  1 年前    · 
微醺的墨镜  ·  vs2019 找不到.net core ...·  1 年前    · 
UE4 启动过程 WinMain ... 点击play...

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)