首页 > 其他分享 >UE4之LoadingScreen机制

UE4之LoadingScreen机制

时间:2024-06-20 23:31:59浏览次数:22  
标签:Win64 UE4Editor C++ dll LoadingScreen DebugGame UE4 机制 Line

1. 当IsMoviePlayerEnabled()为false或使用nullrhi来运行游戏时,会使用FNullGameMoviePlayer(空MoviePlayer)来跑

2. FDefaultGameMoviePlayer为实现LoadingScreen的核心类,包括视频数据流(IMovieStreamer)、UI界面(SWindow)、多线程更新(SlateLoadingThread)

3. 各个平台(Android、iOS、Windows)实现了自己的IMovieStreamer,用于解码视频文件,一个IMovieStreamer对应一个视频文件。

    各平台上的IMovieStreamer对象伴随FXXXMoviePlayerModule平台模块的加载来创建和注册到FDefaultGameMoviePlayer对象中,卸载来反注册和删除

TSharedPtr<FXXXMediaPlayerStreamer> XXXMovieStreamer; // 全局智能指针对象

class FXXXMoviePlayerModule : public IModuleInterface
{
    /** IModuleInterface implementation */
    virtual void StartupModule() override
    {
        FXXXMediaPlayerStreamer* Streamer = new FXXXMediaPlayerStreamer;
        XXXMovieStreamer = MakeShareable(Streamer);
            
        FCoreDelegates::RegisterMovieStreamerDelegate.Broadcast(XXXMovieStreamer);
    }

    virtual void ShutdownModule() override
    {
        if (XXXMovieStreamer.IsValid())
        {
            FCoreDelegates::UnRegisterMovieStreamerDelegate.Broadcast(XXXMovieStreamer);
        }

        XXXMovieStreamer->Cleanup();
        XXXMovieStreamer.Reset();
    }

};

 

一些MoviePlayer相关的函数:

/*** UnrealEngine\Engine\Source\Runtime\MoviePlayer\Public\MoviePlayer.h ***/
/** Creates the movie player */
MOVIEPLAYER_API void CreateMoviePlayer();

/** Destroys the movie player */
MOVIEPLAYER_API void DestroyMoviePlayer();

/** Gets the movie player singleton for the engine. */
MOVIEPLAYER_API IGameMoviePlayer* GetMoviePlayer();

MOVIEPLAYER_API IGameMoviePlayer& GetMoviePlayerRef();

/** Returns true if the movie player is enabled. */
bool MOVIEPLAYER_API IsMoviePlayerEnabled();

 

FSlateLoadingSynchronizationMechanism::SlateThreadRunMainLoop()

/** UnrealEngine\Engine\Source\Runtime\MoviePlayer\Private\MoviePlayerThreading.cpp **/
void FSlateLoadingSynchronizationMechanism::SlateThreadRunMainLoop()
{
    ThreadSuspendedEvent = FPlatformProcess::GetSynchEventFromPool();
    ThreadResumedEvent = FPlatformProcess::GetSynchEventFromPool();

    double LastTime = FPlatformTime::Seconds();

    bool bWasSuspendedLastFrame = false;

    while (IsSlateMainLoopRunning())
    {
        if (IsSuspended.GetValue() == 0)
        {
            if (bWasSuspendedLastFrame)
            {
                bWasSuspendedLastFrame = false;
                ThreadResumedEvent->Trigger();
            }

            {
                double CurrentTime = FPlatformTime::Seconds();
                double DeltaTime = CurrentTime - LastTime;

                // 60 fps max
                const double MaxTickRate = 1.0 / 60.0f;

                const double TimeToWait = MaxTickRate - DeltaTime;

                if (TimeToWait > 0)
                {
                    FPlatformProcess::Sleep(TimeToWait);
                    CurrentTime = FPlatformTime::Seconds();
                    DeltaTime = CurrentTime - LastTime;
                }

                if (FSlateApplication::IsInitialized() && !IsSlateDrawPassEnqueued())
                {
                    FSlateRenderer* MainSlateRenderer = FSlateApplication::Get().GetRenderer();
                    FScopeLock ScopeLock(MainSlateRenderer->GetResourceCriticalSection());

                    WidgetRenderer->DrawWindow(DeltaTime);

                    SetSlateDrawPassEnqueued();
                }

                LastTime = CurrentTime;
            }
        }
        else if (!bWasSuspendedLastFrame)
        {
            bWasSuspendedLastFrame = true;
            ThreadSuspendedEvent->Trigger();
        }
        else
        {
            FPlatformProcess::SleepNoStats(0.001f);
        }
    }
    
    while (IsSlateDrawPassEnqueued())
    {
        FPlatformProcess::Sleep(1.f / 60.f);
    }
    
    bMainLoopRunning = false;

    FPlatformProcess::ReturnSynchEventToPool(ThreadSuspendedEvent);
    ThreadSuspendedEvent = nullptr;
    FPlatformProcess::ReturnSynchEventToPool(ThreadResumedEvent);
    ThreadResumedEvent = nullptr;
}

 

 

FMoviePlayerWidgetRenderer::DrawWindow()

/** UnrealEngine\Engine\Source\Runtime\MoviePlayer\Private\DefaultGameMoviePlayer.cpp **/
void FMoviePlayerWidgetRenderer::DrawWindow(float DeltaTime)
{
    if (GDynamicRHI && GDynamicRHI->RHIIsRenderingSuspended())
    {
        // This avoids crashes if we Suspend rendering whilst the loading screen is up
        // as we don't want Slate to submit any more draw calls until we Resume.
        return;
    }

    const float Scale = FSlateApplication::Get().GetApplicationScale() * MainWindow->GetDPIScaleFactor();
    FVector2D DrawSize = VirtualRenderWindow->GetClientSizeInScreen() / Scale;

    FSlateApplication::Get().Tick(ESlateTickType::Time);

    FGeometry WindowGeometry = FGeometry::MakeRoot(DrawSize, FSlateLayoutTransform(Scale));

    VirtualRenderWindow->SlatePrepass(WindowGeometry.Scale);

    FSlateRect ClipRect = WindowGeometry.GetLayoutBoundingRect();

    HittestGrid->SetHittestArea(VirtualRenderWindow->GetPositionInScreen(), VirtualRenderWindow->GetViewportSize());
    HittestGrid->Clear();

    // Get the free buffer & add our virtual window
    FSlateDrawBuffer& DrawBuffer = SlateRenderer->GetDrawBuffer();
    FSlateWindowElementList& WindowElementList = DrawBuffer.AddWindowElementList(VirtualRenderWindow);

    WindowElementList.SetRenderTargetWindow(MainWindow);

    int32 MaxLayerId = 0;
    {
        FPaintArgs PaintArgs(nullptr, *HittestGrid, FVector2D::ZeroVector, FSlateApplication::Get().GetCurrentTime(), FSlateApplication::Get().GetDeltaTime());

        // Paint the window
        MaxLayerId = VirtualRenderWindow->Paint(    // TSharedRef<class SVirtualWindow> VirtualRenderWindow  注:SVirtualWindow : public SWindow
            PaintArgs,
            WindowGeometry, ClipRect,
            WindowElementList,
            0,
            FWidgetStyle(),
            VirtualRenderWindow->IsEnabled());
    }

    SlateRenderer->DrawWindows(DrawBuffer);  // 不LoadingScreen时,该逻辑跑在GameThread上

    DrawBuffer.ViewOffset = FVector2D::ZeroVector;
}

 

正常情况下,UI界面的更新是在GameThread中处理的

>    UE4Editor-SlateRHIRenderer.dll!FSlateRHIRenderer::DrawWindows_Private(FSlateDrawBuffer & WindowDrawBuffer={...}) Line 1501    C++
     UE4Editor-Slate.dll!FSlateApplication::PrivateDrawWindows(TSharedPtr<SWindow,0> DrawOnlyThisWindow={...}) Line 1389    C++
     UE4Editor-Slate.dll!FSlateApplication::DrawWindows() Line 1088    C++
     UE4Editor-Slate.dll!FSlateApplication::TickAndDrawWidgets(float DeltaTime) Line 1663    C++
     UE4Editor-Slate.dll!FSlateApplication::Tick(ESlateTickType TickType) Line 1517    C++
     UE4Editor-Win64-DebugGame.exe!FEngineLoop::Tick() Line 5051    C++
     [Inline Frame] UE4Editor-Win64-DebugGame.exe!EngineTick() Line 63    C++
     UE4Editor-Win64-DebugGame.exe!GuardedMain(const wchar_t * CmdLine=0x00000105e0b897c0) Line 174    C++
     UE4Editor-Win64-DebugGame.exe!WinMain(HINSTANCE__ * hInInstance=0x000000000000000a, HINSTANCE__ * hPrevInstance=0x0000000000000000, char * __formal=0x0000000000000000, int nCmdShow=0) Line 275    C++
     [Inline Frame] UE4Editor-Win64-DebugGame.exe!invoke_main() Line 102    C++
     UE4Editor-Win64-DebugGame.exe!__scrt_common_main_seh() Line 288    C++
     kernel32.dll!BaseThreadInitThunk()    Unknown
     ntdll.dll!RtlUserThreadStart()    Unknown

 

当GameThread长时间忙于其他事情时,为了防止UI界面卡死,可以将UI界面的更新切换到LoadingScreen线程来跑

>    UE4Editor-SlateRHIRenderer.dll!FSlateRHIRenderer::DrawWindows_Private(FSlateDrawBuffer & WindowDrawBuffer={...}) Line 1699    C++
     UE4Editor-MoviePlayer.dll!FMoviePlayerWidgetRenderer::DrawWindow(float DeltaTime=-1.78076227e-33) Line 1018    C++
     UE4Editor-MoviePlayer.dll!FSlateLoadingSynchronizationMechanism::SlateThreadRunMainLoop() Line 180    C++
     UE4Editor-MoviePlayer.dll!FSlateLoadingThreadTask::Run() Line 258    C++
     UE4Editor-Core.dll!FRunnableThreadWin::Run() Line 90    C++
     UE4Editor-Core.dll!FRunnableThreadWin::GuardedRun() Line 27    C++
     kernel32.dll!BaseThreadInitThunk()    Unknown
     ntdll.dll!RtlUserThreadStart()    Unknown

 

游戏启动引擎初始化时

     ntdll.dll!NtCreateSection()    Unknown
     ntdll.dll!LdrpMapDllNtFileName()    Unknown
     ntdll.dll!LdrpMapDllFullPath()    Unknown
     ntdll.dll!LdrpProcessWork()    Unknown
     ntdll.dll!LdrpLoadDllInternal()    Unknown
     ntdll.dll!LdrpLoadDll()    Unknown
     ntdll.dll!LdrLoadDll()    Unknown
     KernelBase.dll!LoadLibraryExW()    Unknown
>    UE4Editor-Core.dll!FWindowsPlatformProcess::LoadLibraryWithSearchPaths(const FString & FileName={...}, const TArray<FString,TSizedDefaultAllocator<32>> & SearchPaths={...}) Line 1889    C++
     UE4Editor-Core.dll!FWindowsPlatformProcess::GetDllHandle(const wchar_t * FileName=0x000001808bb62980) Line 91    C++
     UE4Editor-Core.dll!FModuleManager::LoadModuleWithFailureReason(const FName InModuleName={...}, EModuleLoadResult & OutFailureReason=Success) Line 506    C++
     UE4Editor-Projects.dll!FModuleDescriptor::LoadModulesForPhase(ELoadingPhase::Type LoadingPhase=PreDefault, const TArray<FModuleDescriptor,TSizedDefaultAllocator<32>> & Modules={...}, TMap<FName,enum EModuleLoadResult,FDefaultSetAllocator,TDefaultMapHashableKeyFuncs<FName,enum EModuleLoadResult,0>> & ModuleLoadErrors={...}) Line 561    C++
     UE4Editor-Projects.dll!FPluginManager::TryLoadModulesForPlugin(const FPlugin & Plugin={...}, const ELoadingPhase::Type LoadingPhase) Line 1321    C++
     UE4Editor-Projects.dll!FPluginManager::LoadModulesForEnabledPlugins(const ELoadingPhase::Type LoadingPhase=PreDefault) Line 1395    C++
     UE4Editor-Win64-DebugGame.exe!FEngineLoop::LoadStartupModules() Line 3866    C++
     UE4Editor-Win64-DebugGame.exe!FEngineLoop::PreInitPostStartupScreen(const wchar_t * CmdLine=0x00007ff7e95d2b28) Line 3245    C++
     [Inline Frame] UE4Editor-Win64-DebugGame.exe!FEngineLoop::PreInit(const wchar_t *) Line 3649    C++
     [Inline Frame] UE4Editor-Win64-DebugGame.exe!EnginePreInit(const wchar_t *) Line 43    C++
     UE4Editor-Win64-DebugGame.exe!GuardedMain(const wchar_t * CmdLine=0x00000180d04997c0) Line 128    C++
     UE4Editor-Win64-DebugGame.exe!WinMain(HINSTANCE__ * hInInstance=0x000000000000000a, HINSTANCE__ * hPrevInstance=0x0000000000000000, char * __formal=0x0000000000000000, int nCmdShow=0) Line 275    C++
     [Inline Frame] UE4Editor-Win64-DebugGame.exe!invoke_main() Line 102    C++
     UE4Editor-Win64-DebugGame.exe!__scrt_common_main_seh() Line 288    C++
     kernel32.dll!BaseThreadInitThunk()    Unknown
     ntdll.dll!RtlUserThreadStart()    Unknown

 

在FEngineLoop::PreInitPostStartupScreen()函数中主动调用GetMoviePlayer()->PlayMovie()来启动LoadingScreen线程

     UE4Editor-Core.dll!FRunnableThread::Create(FRunnable * InRunnable=0x0000026db4397f00, const wchar_t * ThreadName=0x0000026db441f160, unsigned int InStackSize=0, EThreadPriority InThreadPri=TPri_Normal, unsigned __int64 InThreadAffinityMask=18446744073709551615, EThreadCreateFlags InCreateFlags=None) Line 542    C++
>    [Inline Frame] UE4Editor-MoviePlayer.dll!FSlateLoadingSynchronizationMechanism::Initialize() Line 63    C++
     UE4Editor-MoviePlayer.dll!FDefaultGameMoviePlayer::PlayMovie() Line 386    C++
     UE4Editor-Win64-DebugGame.exe!FEngineLoop::PreInitPostStartupScreen(const wchar_t * CmdLine=0x00007ff7e95d2b28) Line 3212    C++
     [Inline Frame] UE4Editor-Win64-DebugGame.exe!FEngineLoop::PreInit(const wchar_t *) Line 3649    C++
     [Inline Frame] UE4Editor-Win64-DebugGame.exe!EnginePreInit(const wchar_t *) Line 43    C++
     UE4Editor-Win64-DebugGame.exe!GuardedMain(const wchar_t * CmdLine=0x0000026df8c597c0) Line 128    C++
     UE4Editor-Win64-DebugGame.exe!WinMain(HINSTANCE__ * hInInstance=0x000000000000000a, HINSTANCE__ * hPrevInstance=0x0000000000000000, char * __formal=0x0000000000000000, int nCmdShow=0) Line 275    C++
     [Inline Frame] UE4Editor-Win64-DebugGame.exe!invoke_main() Line 102    C++
     UE4Editor-Win64-DebugGame.exe!__scrt_common_main_seh() Line 288    C++
     kernel32.dll!BaseThreadInitThunk()    Unknown
     ntdll.dll!RtlUserThreadStart()    Unknown

 

在后续FEngineLoop::Init()函数中调用GetMoviePlayer()->WaitForMovieToFinish()来结束LoadingScreen线程

>    UE4Editor-MoviePlayer.dll!FSlateLoadingSynchronizationMechanism::DestroySlateThread() Line 81    C++
     UE4Editor-MoviePlayer.dll!FDefaultGameMoviePlayer::WaitForMovieToFinish(bool bAllowEngineTick=false) Line 443    C++
     UE4Editor-Win64-DebugGame.exe!FEngineLoop::Init() Line 4061    C++
     [Inline Frame] UE4Editor-Win64-DebugGame.exe!EngineInit() Line 53    C++
     UE4Editor-Win64-DebugGame.exe!GuardedMain(const wchar_t * CmdLine=0x0000026df8c597c0) Line 156    C++
     UE4Editor-Win64-DebugGame.exe!WinMain(HINSTANCE__ * hInInstance=0x000000000000000a, HINSTANCE__ * hPrevInstance=0x0000000000000000, char * __formal=0x0000000000000000, int nCmdShow=0) Line 275    C++
     [Inline Frame] UE4Editor-Win64-DebugGame.exe!invoke_main() Line 102    C++
     UE4Editor-Win64-DebugGame.exe!__scrt_common_main_seh() Line 288    C++
     kernel32.dll!BaseThreadInitThunk()    Unknown
     ntdll.dll!RtlUserThreadStart()    Unknown

 

LoadMap设置了LoadingScreen时

FDefaultGameMoviePlayer::Initialize()时,会注册PreLoadMap的代理,使得在加载地图之前开始执行PlayMovie()来启动LoadingScreen线程

     UE4Editor-Core.dll!FRunnableThread::Create(FRunnable * InRunnable=0x0000019c2e75edf0, const wchar_t * ThreadName=0x0000019c2e9f4ee0, unsigned int InStackSize=0, EThreadPriority InThreadPri=TPri_Normal, unsigned __int64 InThreadAffinityMask=18446744073709551615, EThreadCreateFlags InCreateFlags=None) Line 551    C++
>    [Inline Frame] UE4Editor-MoviePlayer.dll!FSlateLoadingSynchronizationMechanism::Initialize() Line 63    C++
     UE4Editor-MoviePlayer.dll!FDefaultGameMoviePlayer::PlayMovie() Line 386    C++
     UE4Editor-StreamingPauseRendering.dll!FStreamingPauseRenderingModule::BeginStreamingPause(FViewport * GameViewport=0x0000019c305c4460) Line 160    C++
     [Inline Frame] UE4Editor-Engine.dll!TDelegate<void __cdecl(FViewport *),FDefaultDelegateUserPolicy>::Execute(FViewport * <Params_0>) Line 580    C++
     UE4Editor-Engine.dll!UEngine::BlockTillLevelStreamingCompleted(UWorld * InWorld=0x0000019c32148b80) Line 13969    C++
     UE4Editor-Engine.dll!AGameMode::HandleMatchHasStarted() Line 242    C++
     UE4Editor-Engine.dll!AGameMode::SetMatchState(FName NewState={...}) Line 368    C++
     UE4Editor-Engine.dll!AGameMode::StartMatch() Line 216    C++
     UE4Editor-Engine.dll!UWorld::BeginPlay() Line 4616    C++
     UE4Editor-Engine.dll!UEngine::LoadMap(FWorldContext & WorldContext={...}, FURL URL={...}, UPendingNetGame * Pending=0xffffffffffffffff, FString & Error={...}) Line 13880    C++
     UE4Editor-Engine.dll!UEngine::Browse(FWorldContext & WorldContext={...}, FURL URL={...}, FString & Error={...}) Line 12928    C++
     UE4Editor-Engine.dll!UEngine::TickWorldTravel(FWorldContext & Context={...}, float DeltaSeconds) Line 13126    C++
     UE4Editor-Engine.dll!UGameEngine::Tick(float DeltaSeconds=11.7816048, bool bIdleMode=false) Line 1863    C++
     UE4Editor-Win64-DebugGame.exe!FEngineLoop::Tick() Line 4939    C++
     [Inline Frame] UE4Editor-Win64-DebugGame.exe!EngineTick() Line 63    C++
     UE4Editor-Win64-DebugGame.exe!GuardedMain(const wchar_t * CmdLine=0x0000019bc60d97c0) Line 174    C++
     UE4Editor-Win64-DebugGame.exe!WinMain(HINSTANCE__ * hInInstance=0x000000000000000a, HINSTANCE__ * hPrevInstance=0x0000000000000000, char * __formal=0x0000000000000000, int nCmdShow=0) Line 275    C++
     [Inline Frame] UE4Editor-Win64-DebugGame.exe!invoke_main() Line 102    C++
     UE4Editor-Win64-DebugGame.exe!__scrt_common_main_seh() Line 288    C++
     kernel32.dll!BaseThreadInitThunk()    Unknown
     ntdll.dll!RtlUserThreadStart()    Unknown

 

在PostLoadMap时执行WaitForMovieToFinish()来结束LoadingScreen线程

>    UE4Editor-MoviePlayer.dll!FSlateLoadingSynchronizationMechanism::DestroySlateThread() Line 81    C++
     UE4Editor-MoviePlayer.dll!FDefaultGameMoviePlayer::WaitForMovieToFinish(bool bAllowEngineTick=false) Line 443    C++
     [Inline Frame] UE4Editor-MoviePlayer.dll!Invoke(void(FDefaultGameMoviePlayer::*)(UWorld *)) Line 65    C++
     [Inline Frame] UE4Editor-MoviePlayer.dll!UE4Tuple_Private::TTupleBase<TIntegerSequence<unsigned int>>::ApplyAfter(void(FDefaultGameMoviePlayer::*)(UWorld *) &) Line 299    C++
     UE4Editor-MoviePlayer.dll!TBaseRawMethodDelegateInstance<0,FDefaultGameMoviePlayer,void __cdecl(UWorld *),FDefaultDelegateUserPolicy>::ExecuteIfSafe(UWorld * <Params_0>) Line 469    C++
     UE4Editor-Engine.dll!TMulticastDelegate<void __cdecl(UWorld *),FDefaultDelegateUserPolicy>::Broadcast(UWorld * <Params_0>=0x0000019c1d957580) Line 955    C++
     UE4Editor-Engine.dll!UEngine::LoadMap(FWorldContext & WorldContext={...}, FURL URL={...}, UPendingNetGame * Pending=0xffffffffffffffff, FString & Error={...}) Line 13885    C++
     UE4Editor-Engine.dll!UEngine::Browse(FWorldContext & WorldContext={...}, FURL URL={...}, FString & Error={...}) Line 12928    C++
     UE4Editor-Engine.dll!UEngine::TickWorldTravel(FWorldContext & Context={...}, float DeltaSeconds) Line 13126    C++
     UE4Editor-Engine.dll!UGameEngine::Tick(float DeltaSeconds=0.0333334021, bool bIdleMode=false) Line 1863    C++
     UE4Editor-Win64-DebugGame.exe!FEngineLoop::Tick() Line 4939    C++
     [Inline Frame] UE4Editor-Win64-DebugGame.exe!EngineTick() Line 63    C++
     UE4Editor-Win64-DebugGame.exe!GuardedMain(const wchar_t * CmdLine=0x0000019bc60d97c0) Line 174    C++
     UE4Editor-Win64-DebugGame.exe!WinMain(HINSTANCE__ * hInInstance=0x000000000000000a, HINSTANCE__ * hPrevInstance=0x0000000000000000, char * __formal=0x0000000000000000, int nCmdShow=0) Line 275    C++
     [Inline Frame] UE4Editor-Win64-DebugGame.exe!invoke_main() Line 102    C++
     UE4Editor-Win64-DebugGame.exe!__scrt_common_main_seh() Line 288    C++
     kernel32.dll!BaseThreadInitThunk()    Unknown
     ntdll.dll!RtlUserThreadStart()    Unknown

 

FDefaultGameMoviePlayer中OnPreLoadMap和OnPostLoadMap函数

/** UnrealEngine\Engine\Source\Runtime\MoviePlayer\Private\DefaultGameMoviePlayer.cpp **/
void FDefaultGameMoviePlayer::OnPreLoadMap(const FString& LevelName)
{
    FCoreUObjectDelegates::PostLoadMapWithWorld.RemoveAll(this);

    if( PlayMovie() )
    {
        FCoreUObjectDelegates::PostLoadMapWithWorld.AddRaw(this, &FDefaultGameMoviePlayer::OnPostLoadMap );
    }
}

void FDefaultGameMoviePlayer::OnPostLoadMap(UWorld* LoadedWorld)
{
    if (!LoadingScreenAttributes.bAllowEngineTick)
    {
        // If engine tick is enabled, we don't want to tick here and instead want to run from the WaitForMovieToFinish call in LaunchEngineLoop
        WaitForMovieToFinish();
    }
}

 

LoadMap没有设置LoadingScreen时

LoadMap时FStreamingPauseRenderingModule会执行PlayMovie()和WaitForMovieToFinish()

 

右下角会有三个点的UI动画表现(throbber),详见:UnrealEngine\Engine\Source\Runtime\Slate\Private\Widgets\Images\SThrobber.cpp

// FDefaultGameMoviePlayer::PlayMovie()
>    UE4Editor-MoviePlayer.dll!FDefaultGameMoviePlayer::PlayMovie() Line 385    C++
     UE4Editor-StreamingPauseRendering.dll!FStreamingPauseRenderingModule::BeginStreamingPause(FViewport * GameViewport=0x0000026e34448d80) Line 160    C++
     [Inline Frame] UE4Editor-Engine.dll!TDelegate<void __cdecl(FViewport *),FDefaultDelegateUserPolicy>::Execute(FViewport * <Params_0>) Line 580    C++
     UE4Editor-Engine.dll!UEngine::BlockTillLevelStreamingCompleted(UWorld * InWorld=0x0000026e23952080) Line 13969    C++
     UE4Editor-Engine.dll!AGameMode::HandleMatchHasStarted() Line 242    C++
     UE4Editor-Engine.dll!AGameMode::SetMatchState(FName NewState={...}) Line 368    C++
     UE4Editor-Engine.dll!AGameMode::StartMatch() Line 216    C++
     UE4Editor-Engine.dll!UWorld::BeginPlay() Line 4616    C++
     UE4Editor-Engine.dll!UEngine::LoadMap(FWorldContext & WorldContext={...}, FURL URL={...}, UPendingNetGame * Pending=0xffffffffffffffff, FString & Error={...}) Line 13880    C++
     UE4Editor-Engine.dll!UEngine::Browse(FWorldContext & WorldContext={...}, FURL URL={...}, FString & Error={...}) Line 12928    C++
     UE4Editor-Engine.dll!UEngine::TickWorldTravel(FWorldContext & Context={...}, float DeltaSeconds) Line 13126    C++
     UE4Editor-Engine.dll!UGameEngine::Tick(float DeltaSeconds=104.692589, bool bIdleMode=false) Line 1863    C++
     UE4Editor-Win64-DebugGame.exe!FEngineLoop::Tick() Line 4939    C++
     [Inline Frame] UE4Editor-Win64-DebugGame.exe!EngineTick() Line 63    C++
     UE4Editor-Win64-DebugGame.exe!GuardedMain(const wchar_t * CmdLine=0x0000026df8c597c0) Line 174    C++
     UE4Editor-Win64-DebugGame.exe!WinMain(HINSTANCE__ * hInInstance=0x000000000000000a, HINSTANCE__ * hPrevInstance=0x0000000000000000, char * __formal=0x0000000000000000, int nCmdShow=0) Line 275    C++
     [Inline Frame] UE4Editor-Win64-DebugGame.exe!invoke_main() Line 102    C++
     UE4Editor-Win64-DebugGame.exe!__scrt_common_main_seh() Line 288    C++
     kernel32.dll!BaseThreadInitThunk()    Unknown
     ntdll.dll!RtlUserThreadStart()    Unknown


// FDefaultGameMoviePlayer::WaitForMovieToFinish()
>    UE4Editor-MoviePlayer.dll!FDefaultGameMoviePlayer::WaitForMovieToFinish(bool bAllowEngineTick=false) Line 436    C++
     UE4Editor-StreamingPauseRendering.dll!FStreamingPauseRenderingModule::EndStreamingPause() Line 173    C++
     [Inline Frame] UE4Editor-Engine.dll!TDelegate<void __cdecl(void),FDefaultDelegateUserPolicy>::Execute() Line 580    C++
     UE4Editor-Engine.dll!UEngine::BlockTillLevelStreamingCompleted(UWorld * InWorld=0x0000026e23952080) Line 13973    C++
     UE4Editor-Engine.dll!AGameMode::HandleMatchHasStarted() Line 242    C++
     UE4Editor-Engine.dll!AGameMode::SetMatchState(FName NewState={...}) Line 368    C++
     UE4Editor-Engine.dll!AGameMode::StartMatch() Line 216    C++
     UE4Editor-Engine.dll!UWorld::BeginPlay() Line 4616    C++
     UE4Editor-Engine.dll!UEngine::LoadMap(FWorldContext & WorldContext={...}, FURL URL={...}, UPendingNetGame * Pending=0xffffffffffffffff, FString & Error={...}) Line 13880    C++
     UE4Editor-Engine.dll!UEngine::Browse(FWorldContext & WorldContext={...}, FURL URL={...}, FString & Error={...}) Line 12928    C++
     UE4Editor-Engine.dll!UEngine::TickWorldTravel(FWorldContext & Context={...}, float DeltaSeconds) Line 13126    C++
     UE4Editor-Engine.dll!UGameEngine::Tick(float DeltaSeconds=104.692589, bool bIdleMode=false) Line 1863    C++
     UE4Editor-Win64-DebugGame.exe!FEngineLoop::Tick() Line 4939    C++
     [Inline Frame] UE4Editor-Win64-DebugGame.exe!EngineTick() Line 63    C++
     UE4Editor-Win64-DebugGame.exe!GuardedMain(const wchar_t * CmdLine=0x0000026df8c597c0) Line 174    C++
     UE4Editor-Win64-DebugGame.exe!WinMain(HINSTANCE__ * hInInstance=0x000000000000000a, HINSTANCE__ * hPrevInstance=0x0000000000000000, char * __formal=0x0000000000000000, int nCmdShow=0) Line 275    C++
     [Inline Frame] UE4Editor-Win64-DebugGame.exe!invoke_main() Line 102    C++
     UE4Editor-Win64-DebugGame.exe!__scrt_common_main_seh() Line 288    C++
     kernel32.dll!BaseThreadInitThunk()    Unknown
     ntdll.dll!RtlUserThreadStart()    Unknown

 

主循环Tick中调用FDefaultGameMoviePlayer::WaitForMovieToFinish

>    UE4Editor-MoviePlayer.dll!FDefaultGameMoviePlayer::WaitForMovieToFinish(bool bAllowEngineTick=true) Line 436    C++
     UE4Editor-Win64-DebugGame.exe!FEngineLoop::Tick() Line 4963    C++
     [Inline Frame] UE4Editor-Win64-DebugGame.exe!EngineTick() Line 63    C++
     UE4Editor-Win64-DebugGame.exe!GuardedMain(const wchar_t * CmdLine=0x0000026df8c597c0) Line 174    C++
     UE4Editor-Win64-DebugGame.exe!WinMain(HINSTANCE__ * hInInstance=0x000000000000000a, HINSTANCE__ * hPrevInstance=0x0000000000000000, char * __formal=0x0000000000000000, int nCmdShow=0) Line 275    C++
     [Inline Frame] UE4Editor-Win64-DebugGame.exe!invoke_main() Line 102    C++
     UE4Editor-Win64-DebugGame.exe!__scrt_common_main_seh() Line 288    C++
     kernel32.dll!BaseThreadInitThunk()    Unknown
     ntdll.dll!RtlUserThreadStart()    Unknown

 

标签:Win64,UE4Editor,C++,dll,LoadingScreen,DebugGame,UE4,机制,Line
From: https://www.cnblogs.com/kekec/p/11593225.html

相关文章

  • Redis 缓存应用、淘汰机制
    (四)Redis缓存应用、淘汰机制 合集-Redis(4) 1.(一)LinuxCentOSRedis安装05-082.(二)Redis数据类型与结构05-173.(三)Redis线程与IO模型06-054.(四)Redis缓存应用、淘汰机制06-20收起 1、缓存应用一个系统中不同层面数据访问速度不一样,以计算机为例,CPU、内存......
  • 【YOLOv8改进】STA(Super Token Attention) 超级令牌注意力机制 (论文笔记+引入代码)
    摘要视觉Transformer在许多视觉任务上展示了卓越的性能。然而,它在浅层捕获局部特征时可能会面临高度冗余的问题。因此,使用了局部自注意力或早期阶段的卷积来减少这种冗余,但这牺牲了捕获长距离依赖的能力。一个挑战随之而来:在神经网络的早期阶段,我们是否能高效且有效地进行全局上......
  • 隔离机制、锁机制、三大范式
    【一】隔离机制【1】数据库读现象的本质是数据库在高并发场景下多个同时执行的事务带来的影响。【2】数据库三大读现象在数据库中,不同的事务隔离级别可能会导致脏读(DirtyRead)、不可重复读(Non-repeatableRead)和幻读(PhantomRead)等问题的出现。【3】脏读(1)概述事务1和......
  • Java学习基础笔记——反射机制
    第十五章反射15.1反射机制15.1.1 Java反射机制可以完成15.1.2 反射的优缺点15.2Class类15.2.1基本介绍15.2.2Class类常用方法15.2.3获取Class类对象6种方式15.3类加载15.3.1基本说明15.3.2类加载时机15.4反射获取类的结构信息15.5反射调用性能......
  • Redis的持久化机制和缓存预热
    Redis的持久化机制Redis是一个内存数据库,它的数据存放在内存中,但是如果关闭服务、机器关机或者断电的话,内存中的所有数据都会慢慢消失消失。内存数据消失的原因:因为内存中的数据是半导体晶体管开关,这种开关高度依赖电源,当电源断电后,无法再控制晶体管的开关状态。这时候电容发挥......
  • 易基因:MeRIP-seq等揭示RNA m6A去甲基化酶调控植物雄性不育的分子机制 | 科研速递
    大家好,这里是专注表观组学十余年,领跑多组学科研服务的易基因。水稻是全球重要的农作物,也是单子叶植物模型。在水稻中,N6-甲基腺苷(m6A)mRNA修饰对植物的发育和胁迫响应至关重要。OsFIP37作为m6A甲基化复合体的核心组分,其缺乏会导致雄性不育,强调了m6A在雄性生育中的重要性。m6A是......
  • 服务器雪崩的应对策略之----熔断机制
    熔断机制(CircuitBreaker)是一种保护系统稳定性的重要手段。它的主要目的是防止系统在依赖的服务出现问题时,继续发送请求,从而保护系统免受进一步的影响。熔断机制通过监控请求的成功和失败率,在检测到故障率超过预设阈值时,自动切换到熔断状态,停止对故障服务的请求。熔断状态一......
  • (四)Redis 缓存应用、淘汰机制
    1、缓存应用一个系统中不同层面数据访问速度不一样,以计算机为例,CPU、内存和磁盘这三层的访问速度从几十ns到100ns,再到几ms,性能的差异很大,如果每次CPU处理数据时都要到磁盘读取数据,系统运行速度会大大降低。所以,计算机系统中,默认有两种缓存:(1)CPU里面的末级缓存,即LLC,用来......
  • spring 使用 事件机制
    概述在编写代码的时候,比如我删除一篇文章,这个时候,如果我想做些额外的逻辑,这是就需要修改删除部分的代码。spring提供了事件机制更优雅的实现这个,用户只需要实现事件监听即可。代码实现注入发布者publicclassKnowledgeBaseServiceimplementsApplicationEventPublisherAwar......
  • 大脑如何通过DNA损伤与修复机制来巩固记忆?
    近日《自然》杂志刊登了一篇重磅论文,揭示了记忆形成过程中的一个关键机制——大脑如何通过DNA损伤和修复机制来巩固记忆。这一发现为我们理解记忆形成提供了全新的视角,也可能为治疗某些记忆障碍疾病提供新的思路。记忆是我们大脑中非常重要的功能之一,它使我们能够存储过去......