UE4 C++ 使用GameInstance实现简单加载界面调用

7 篇文章 0 订阅

SeamTravel可以保存数据,但如果再TravelMap里放上加载界面效果极差,又希望把加载功能尽量做小且可以使用UMG,所以不使用AsyncLoadSystem,异步线程太麻烦。结合网络文章写了一个简单测试版。

零、主要思想

0.1、通过GameInstance的PreLoad广播+PostLoad广播实现界面自动创建与销毁

0.2、使用中的MoviePlayer实现UMG在Slate线程显示加载界面,而不再被主线程阻塞

0.3、只完成最简单的加载界面逻辑,且尽量描述啰嗦

0.4、 参考文档

CSDN
https://www.cnblogs.com/wzj998/p/7066657.html

官方视频,介绍了MoviePlayer和SeamTravel
https://www.bilibili.com/video/BV1XE41147dQ

一、前期准备

1.1、必要模块加载在这里插入图片描述

1.2、自己创建一个C++的GameInstance

二、c++部分代码

2.1、.h

// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "CoreMinimal.h"
#include "Engine/GameInstance.h"
#include "MyGameInstance.generated.h"

class UUserWidget;
/**
 * 
 */
UCLASS()
class HMXX_01_API UMyGameInstance : public UGameInstance
{
	GENERATED_BODY()
public:
	UMyGameInstance();

	//主要任务是绑定关卡加载前后的广播,用于自动执行BeginLoad和EndLoad
	virtual void Init() override;

	//显示加载屏幕
	UFUNCTION()
		virtual void BeginLoadingScreen(const FString& MapName);
	
	//隐藏加载屏幕
	UFUNCTION()
		virtual void EndLoadingScreen(UWorld* LoadedWorld);

protected:
	//加载界面的类,蓝图中自定义
	UPROPERTY(EditDefaultsOnly)
		TSubclassOf<UUserWidget> LoadingWidgetClass;

	//加载界面指针
	UPROPERTY()
		UUserWidget* LoadingWidget;
};

2.2 .cpp

#include "MyGameInstance.h"
#include "Blueprint/UserWidget.h"
#include "Runtime/MoviePlayer/Public/MoviePlayer.h"



UMyGameInstance::UMyGameInstance()
	:Super(),LoadingWidgetClass(nullptr),LoadingWidget(nullptr)
{

}

void UMyGameInstance::Init()
{
	Super::Init();

	//直接绑定地图加载前后的广播事件
	FCoreUObjectDelegates::PreLoadMap.AddUObject(this, &UMyGameInstance::BeginLoadingScreen);
	FCoreUObjectDelegates::PostLoadMapWithWorld.AddUObject(this, &UMyGameInstance::EndLoadingScreen);
}

void UMyGameInstance::BeginLoadingScreen(const FString& MapName)
{
	UE_LOG(LogTemp, Log, TEXT("BeginLoadingScreen"));

	//如果当前不是独立服务器的话,单机游戏可以忽略该判断
	if (!IsRunningDedicatedServer())
	{
		//这是UE4自带的加载屏幕类型
		FLoadingScreenAttributes LoadingScreen;

		//对其进行属性配置
		//当加载完成时是否自动结束播放
		LoadingScreen.bAutoCompleteWhenLoadingCompletes = true;

		//添加我们的UMG
		//根据Class创建我们的UMG
		LoadingWidget = CreateWidget<UUserWidget>(this, LoadingWidgetClass);
		//获取到UMG对应的共享指针
		TSharedPtr<SWidget> WidgetPtr = LoadingWidget->TakeWidget();
		//正式设置
		LoadingScreen.WidgetLoadingScreen = WidgetPtr;



		// 播放影片相关,我没用到
		// 如果加载完成是否可以任意键打断影片播放
		//LoadingScreen.bMoviesAreSkippable = false;
		// 等待到影片播放结束
		//LoadingScreen.bWaitForManualStop = true;
		// 视频播放类型
		//LoadingScreen.PlaybackType = EMoviePlaybackType::MT_Looped;
		// 视频播放路径
		// 下方路径对应:Content\Movies目录下的squad_intro_movie.mp4文件
		//LoadingScreen.MoviePaths.Add("squad_intro_movie");



		//放MovePlayer里播放
		GetMoviePlayer()->SetupLoadingScreen(LoadingScreen);
	}

		
}

void UMyGameInstance::EndLoadingScreen(UWorld* LoadedWorld)
{
	UE_LOG(LogTemp, Log, TEXT("EndLoadingScreen"));
	//删除UMG
	if (!IsRunningDedicatedServer())
	{
		if (LoadingWidget)
		{
			//从父组件移除
			LoadingWidget->RemoveFromParent();
			//标记删除
			LoadingWidget->MarkPendingKill();
		}
	}
}

三、创建自己的UMG

3.1、简易UMG

在这里插入图片描述

3.2基于MyGameInstance创建的蓝图,配置UMG,并在Editor选项卡下将GameInstance设置为该蓝图

在这里插入图片描述

四、以独立窗口方式运行,直接出效果。

!!!注意: 编辑器模式下运行不会出效果
在这里插入图片描述

  • 1
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
好的,下面是用UE4 C++编写异步加载关卡的基本步骤: 1. 创建一个继承自AActor的C++类,这个类将被用来加载关卡。 2. 在.h文件中,添加一个函数声明,用于异步加载关卡。函数原型为:`void LoadLevelAsync(const FString& LevelName);` 3. 在.cpp文件中,实现`LoadLevelAsync`函数。首先,使用`FStreamableManager`类的`LoadLevelAsync`函数来异步加载关卡。这个函数需要两个参数:要加载的关卡名称和一个回调函数,在关卡加载完成后自动调用。 4. 在回调函数中,将加载的关卡传递给一个由你创建的函数,该函数将关卡添加到世界中。 5. 最后,在你的游戏中,调用`LoadLevelAsync`函数来异步加载关卡。 下面是一个简单的代码示例: ```cpp // MyLevelLoader.h #pragma once #include "CoreMinimal.h" #include "GameFramework/Actor.h" #include "MyLevelLoader.generated.h" UCLASS() class MYGAME_API AMyLevelLoader : public AActor { GENERATED_BODY() public: AMyLevelLoader(); UFUNCTION(BlueprintCallable, Category = "Level Loading") void LoadLevelAsync(const FString& LevelName); private: void OnLevelLoaded(ULevel* LoadedLevel); FStreamableManager LevelLoader; }; // MyLevelLoader.cpp #include "MyLevelLoader.h" AMyLevelLoader::AMyLevelLoader() { PrimaryActorTick.bCanEverTick = false; } void AMyLevelLoader::LoadLevelAsync(const FString& LevelName) { LevelLoader.LoadLevelAsync(LevelName, FStreamableDelegate::CreateUObject(this, &AMyLevelLoader::OnLevelLoaded)); } void AMyLevelLoader::OnLevelLoaded(ULevel* LoadedLevel) { if (LoadedLevel) { UWorld* World = GetWorld(); if (World) { World->AddLevelToWorld(LoadedLevel); } } } ``` 在你的游戏中,可以创建AMyLevelLoader实例并调用`LoadLevelAsync`来异步加载关卡。例如: ```cpp AMyLevelLoader* LevelLoader = GetWorld()->SpawnActor<AMyLevelLoader>(); LevelLoader->LoadLevelAsync("MyLevel"); ``` 这里,我们异步加载了名为"MyLevel"的关卡。当关卡加载完成时,`OnLevelLoaded`函数会自动被调用,并将关卡添加到世界中。 希望这可以帮助你开始编写异步加载关卡的代码!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值