《InsideUE4》GamePlay架构学习_WorldContext,GameInstance,Engine

本文介绍了UE4中WorldContext、GameInstance和Engine的概念及其作用。WorldContext负责管理World切换和Level旅行的上下文,GameInstance保存游戏全局信息,Engine则分化为UGameEngine和UEditorEngine,分别对应游戏运行和编辑器环境。GamePlayStatics为蓝图系统提供了方便的Level操作接口。
摘要由CSDN通过智能技术生成

WorldContext,GameInstance,Engine

前话

本次系列是关于知乎InsideUE系列的学习记录。原作链接如下:原文链接

WorldContext

前面对其他部分都花了大量时间来解释,那么World到底是什么。

首先游戏里不只有一个World,World有多种类型。比如不同的视图可以看作不同的World,编辑器也是一个World,运行后也是一个World。

简单来说,UE其实是一个平行宇宙世界观。

namespace EWorldType
{
    enum Type
	{
		None,		// An untyped world, in most cases this will be the vestigial worlds of streamed in sub-levels
		Game,		// The game world
		Editor,		// A world being edited in the editor
		PIE,		// A Play In Editor world
		Preview,	// A preview world for an editor tool
		Inactive	// An editor world that was loaded but not currently being edited in the level editor
	};
	UE_DEPRECATED(4.14, "EWorldType::Preview is deprecated. Please use either EWorldType::EditorPreview or EWorldType::GamePreview")
	const EWorldType::Type Preview = EWorldType::EditorPreview;
}

而UE用来管理和跟踪这些World的工具就是WorldContext
在这里插入图片描述

FWorldContext保存着ThisCurrentWorld来指向当前的World。而当需要从一个World切换到另一个World的时候(比如说当点击播放时,就是从Preview切换到PIE),FWorldContext就用来保存切换过程信息和目标World上下文信息。

一般就来说,对于独立运行的游戏,WorldContext只有唯一个。而对于编辑器模式,则是一个WorldContext给编辑器,一个WorldContext给PIE(Play In Editor)的World。一般UE会自己处理各个World之间的各种信息。

不仅如此,同时FWorldContext还保存着World里Level切换的上下文:

struct FWorldContext
{
    [...]
	TEnumAsByte<EWorldType::Type>	WorldType
	FSeamlessTravelHandler SeamlessTravelHandler;
	FName ContextHandle;
	
	/** URL to travel to for pending client connect */
	FString TravelURL;
	/** TravelType for pending client connects */
	uint8 TravelType;
	/** URL the last time we traveled */
	UPROPERTY()
	struct FURL LastURL;
	/** last server we connected to (for "reconnect" command) */
	UPROPERTY()
	struct FURL LastRemoteURL;
}

这里的TravelURLTravelType就是负责设定下一个Level的目标和转换过程。

// Traveling from server to server.
UENUM()
enum ETravelType
{
	/** Absolute URL. */
	TRAVEL_Absolute,
	/** Partial (carry name, reset server). */
	TRAVEL_Partial,
	/** Relative URL. */
	TRAVEL_Relative,
	TRAVEL_MAX,
};

void UEngine::SetClientTravel( UWorld *InWorld, const TCHAR* NextURL, ETravelType InTravelType )
{
	FWorldContext &Context = GetWorldContextFromWorldChecked(InWorld);
	// set TravelURL.  Will be processed safely on the next tick in UGameEngine::Tick().
	Context.TravelURL    = NextURL;
	Context.TravelType   = InTravelType;
    [...]
}

粗略的流程是UE在OpenLevel的时候, 先设置当前World的Context上的TravelURL,然后在UEngine::TickWorldTravel的时候判断TravelURL非空来真正执行Level的切换。

总而言之,WorldContext既负责World之间切换的上下文,也负责Level之间切换的操作信息。
 

GameInstance

在这里插入图片描述

GameInstance里会保存着当前的WorldConext和其他整个游戏的信息。这是一个层次更高的概念。

在Unity,存在一个Application对整个游戏进行管理,它都是玩家能直接接触到的最根源的操作类。

而UE的GameInstance因为继承于UObject,所以就拥有了动态创建的能力,我们可以通过指定GameInstanceClass来让UE创建使用我们自定义的GameInstance子类。所以不论是C++还是BP,我们通常会继承于GameInstance,然后在里面编写应用于整个游戏范围的逻辑。

是一个正在运行的游戏的高级别的管理对象,在游戏创建时生成,游戏实例关闭时销毁,一个游戏中可以有多个GameInstance;GameInstance在切换Level是不会被销毁。

Engine

在这里插入图片描述
此处UEngine分化出了两个子类:UGameEngine和UEditorEngine。众所周知,UE的编辑器也是UE用自己的引擎渲染出来的,采用的也是Slate那套UI框架。

UGameEngine.Init()来创建GameInstance。

所以本质上来说,UE的编辑器其实也是个游戏!我们是在编辑器这个游戏里面创造我们自己的另一个游戏。

话虽如此,但比较编辑器和游戏还是有一定差别的,所以UE会在不同模式下根据编译环境而采用不同的具体Engine类,而在基类UEngine里通过一个WorldList保存了所有的World。

  • Standlone Game:会使用UGameEngine来创建出唯一的一个GameWorld,因为也只有一个,所以为了方便起见,就直接保存了GameInstance指针。
  • 而对于编辑器来说,EditorWorld其实只是用来预览,所以并不拥有OwningGameInstance,而PlayWorld里的OwningGameInstance才是间接保存了GameInstance.

目前来说,因为UE还不支持同时运行多个World(当前只能一个,但可以切换),所以GameInstance其实也是唯一的。
提前说些题外话,虽然目前网络部分还没涉及到,但是当我们在Editor里进行MultiplePlayer的测试时,每一个Player Window里都是一个World。如果是DedicateServer模式,那DedicateServer也会是一个World。
最后实例化出来的UEngine实例用一个全局的GEngine变量来保存。至此,我们已经到了引擎的最根处:

//UnrealEngine\Engine\Source\Runtime\Engine\Private\UnrealEngine.cpp
ENGINE_API UEngine*	GEngine = NULL;

GamePlayStatics

既然我们在引擎内部C++层次已经有了访问World操作Level的能力,那么在暴露出的蓝图系统里,UE为了我们的使用方便,也在Engine层次为我们提供了便利操作蓝图函数库。

UCLASS ()
class UGameplayStatics : public UBlueprintFunctionLibrary 

我们在蓝图里见到的GetPlayerController、SpawActor和OpenLevel等都是来至于这个类的接口。这个类比较简单,相当于一个C++的静态类,只为蓝图暴露提供了一些静态方法。在想借鉴或者是查询某个功能的实现时,此处往往会是一个入口。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值