即使开放世界已然成为现今游戏趋势,切换关卡过程中的读条仍是很难避免的,譬如进入房屋、传送到其他世界等等。
于是就引入了loadingscreen这一需求。
loadingscreen顾名思义就是加载过程中通过其他线程显示的画面,可以是真读条(显示当前进度),也可以仅仅转着圈,循环播放某段视频。
我们首先需要新建c++类MyGameInstance继承自GameInstance,并在项目设置中将其设为当前使用的
这里我先创建了一个继承自MyGameInstance的蓝图,叫bp_MyGameInstance。
开始写代码之前,还有这些准备工作:
1.在projectname.build.cs文件中增加"MoviePlayer","UMG", "Slate", "SlateCore"几项
PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore", "HeadMountedDisplay", "MoviePlayer", "UMG", "Slate", "SlateCore"});
2.在projectname.h中包含一些头文件
#include "Runtime/UMG/Public/UMG.h" #include "Runtime/UMG/Public/UMGStyle.h" #include "Runtime/UMG/Public/Slate/SObjectWidget.h" #include "Runtime/UMG/Public/IUMGModule.h" #include "Runtime/UMG/Public/Blueprint/UserWidget.h" #include "Runtime/MoviePlayer/Public/MoviePlayer.h" #include "Runtime/SlateCore/Public/Widgets/SWidget.h"
然后重写gameinstance中的这个函数
virtual void Init() override; void UMyGameInstance::Init() { UGameInstance::Init(); FCoreUObjectDelegates::PreLoadMap.AddUObject(this, &UMyGameInstance::BeginLoadingScreen); FCoreUObjectDelegates::PostLoadMap.AddUObject(this, &UMyGameInstance::EndLoadingScreen); }
接下来这两个函数
UFUNCTION() virtual void BeginLoadingScreen(const FString& MapName); UFUNCTION() virtual void EndLoadingScreen();
void UMyGameInstance::BeginLoadingScreen(const FString& MapName) { loadlevel_count++; if (!IsRunningDedicatedServer()) { FLoadingScreenAttributes LoadingScreen; LoadingScreen.bAutoCompleteWhenLoadingCompletes = false; LoadingScreen.bMoviesAreSkippable = true;//任意键打断如果加载完成 LoadingScreen.bWaitForManualStop = true;// LoadingScreen.PlaybackType = EMoviePlaybackType::MT_Looped; //不知道怎么destroy.. inWidget = CreateWidget<UUserWidget>(this, WidgetTemplate);//应该有垃圾回收 TSharedPtr<SWidget> WidgetPtr = inWidget->TakeWidget(); LoadingScreen.WidgetLoadingScreen = WidgetPtr; LoadingScreen.MoviePaths.Add("squad_intro_movie"); GetMoviePlayer()->SetupLoadingScreen(LoadingScreen); } } void UMyGameInstance::EndLoadingScreen() { if (!IsRunningDedicatedServer()) { } }
上文中的squad_intro_movie其实是Content\Movies目录下的squad_intro_movie.mp4文件,不需要后缀名,要注意不是将其拖到编辑器中,而是把mp4文件复制到实际工程文件目录里。
而WidgetTemplate则是mygameinstance暴露到蓝图的用于Loadingscreen的控件类,
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = UI) TSubclassOf<UUserWidget> WidgetTemplate; UUserWidget* inWidget = NULL;
inWidget才是真正被create出来的控件对象,虽然每次loading都新create了一次,但是ue4对控件应该有自己的垃圾回收机制。
至于控件蓝图,需要从mygameinstance中获取当前loading是否完成
UFUNCTION(BlueprintPure, Category = MyGameInstance) bool myisloadingfinished(); bool UMyGameInstance::myisloadingfinished() { return GetMoviePlayer()->IsLoadingFinished(); }
我的loadingscreen控件蓝图目前只包含三样东西:
加载过程中throbber(就是那个点点点)显示,而“请按任意键继续”的文本隐藏;
加载完成时反之。
textblock的visibility函数:
点点点的visibility函数:
要注意的是点击视口中运行并不能看到效果,需要选择独立窗口运行。
然后就大功告成啦!!!这里借用了一下squad的小视频