UE5中的UGameInstanceSubsystem

1、什么是 UGameInstanceSubsystem

UGameInstanceSubsystem 是一个可以附加到 UGameInstance 上的对象,它的生命周期和 UGameInstance 一样长。这意味着它在游戏启动时创建,并在整个游戏生命周期内保持存在,直到游戏结束。它在任何需要的地方都可以方便地被调用,比如在任何游戏对象、玩家控制器、关卡蓝图等地方都可获取并调用子系统的方法。

优点:

  1. 全局访问:由于 UGameInstanceSubsystem 的生命周期与 UGameInstance 一样长,因此可以在整个游戏中随时访问。这使得它非常适合用于管理全局状态或服务,例如:

    • 游戏设置和配置
    • 全局事件管理
    • 网络会话管理
    • 存档和加载系统
  2. 模块化设计:子系统提供了一种模块化的方式来分离不同的功能。这有助于保持代码的整洁和可维护性,因为每个子系统可以专注于特定的任务或服务。

  3. 生命周期管理:子系统的生命周期由引擎自动管理,你不需要手动创建或销毁它们。

  4. 依赖注入:子系统可以通过依赖注入的方式被其他类访问,从而简化了依赖管理。

注意事项:

  1. 初始化时机问题,UGameInstanceSubsystem的初始化非常早(比BeginPlay早)
  2. GameInstanceSubsystem对象的生命周期,正常来说他应该是游戏启动就生成,游戏结束就销毁,但是实践中发现在编辑器中结束播放时,只是调用了deinitialize(),没有销毁该游戏实例子系统的对象。

2、如何创建和使用

2.1 创建子系统类

首先,创建一个新的 C++ 类,继承自 UGameInstanceSubsystem

// MyGameInstanceSubsystem.h
#pragma once

#include "CoreMinimal.h"
#include "Subsystems/GameInstanceSubsystem.h"
#include "MyGameInstanceSubsystem.generated.h"

UCLASS()
class MYPROJECT_API UMyGameInstanceSubsystem : public UGameInstanceSubsystem
{
    GENERATED_BODY()
public:
    virtual void Initialize(FSubsystemCollectionBase& Collection) override;
    virtual void Deinitialize() override;
    
    // 可以蓝图调用,也可以C++里调
	UFUNCTION(BlueprintCallable, Category = "UMyGameInstanceSubsystem ")
    void DoSomething();
private:
    // 内部状态或资源
};
// MyGameInstanceSubsystem.cpp
#include "MyGameInstanceSubsystem.h"
#include "Engine/Engine.h"

void UMyGameInstanceSubsystem::Initialize(FSubsystemCollectionBase& Collection)
{
    Super::Initialize(Collection);
    UE_LOG(LogTemp, Warning, TEXT("Initialized"));
}

void UMyGameInstanceSubsystem::Deinitialize()
{
    UE_LOG(LogTemp, Warning, TEXT("Deinitialized"));
    Super::Deinitialize();
}

void UMyGameInstanceSubsystem::DoSomething()
{
    UE_LOG(LogTemp, Warning, TEXT("doing something"));
}

2.2 使用

可以在任何需要的地方访问和使用 UGameInstanceSubsystem,它的效果类似于全局变量:

  • 获取自定义子系统对象的地址
  • 调用其接口

获取子系统实例化对象的方法

  1. 通过World
    UWorld* World = GetWorld();
    UMyGameInstanceSubsystem* MySubsystem = World->GetGameInstance()->GetSubsystem<UMyGameInstanceSubsystem>();
    MySubSystem->DoSomething();
    
  2. 通过GEngine
    GetWorld()返回nullptr或者没有这个函数时,还可以通过访问全局变量GEngine获取当前运行的World
    World = GEngine->GetCurrentPlayWorld();
    UMyGameInstanceSubsystem* MySubsystem = World->GetGameInstance()->GetSubsystem<UMyGameInstanceSubsystem>();
    MySubSystem->DoSomething();
    
  3. 通过PlayerController
    如果有玩家控制器的引用也可以通过控制器获取
    // 别的方法获取控制器也是可以的
    APlayerController* PlayerController = GetWorld()->GetFirstPlayerController();
    UMyGameInstanceSubsystem* MySubsystem = PlayerController->GetGameInstance()->GetSubsystem<UMyGameInstanceSubsystem>();
    
  4. UObject的方法
    在任何 UObject 的派生类中,可以直接使用 GetGameInstance() 方法直接访问 GameInstance 并获取子系统。
    UMyGameInstanceSubsystem* MySubsystem = GetGameInstance()->GetSubsystem<UMyGameInstanceSubsystem>();
    

3、子系统是怎么工作的?

在UE中,UGameInstanceSubsystem 是一个特殊的类,它的存在是为了给游戏实例提供模块化的服务。

当创建一个 UGameInstanceSubsystem 的子类时,UE会在游戏运行时自动处理这个子类的实例化和注册过程

  1. 自动注册机制UGameInstanceSubsystem 的子类通常会通过引擎的反射系统自动注册。这是因为 GameInstance 在启动时会自动查找所有继承自 UGameInstanceSubsystem 的类,并创建它们的实例。
  2. 引擎初始化:当游戏启动时,引擎会初始化 GameInstance,并且在这个过程中,它会创建并初始化所有注册的子系统。由于自定义的类继承自 UGameInstanceSubsystem,它会被视为一个需要被初始化的子系统。
  3. 反射和工厂:UE使用反射来在运行时识别和实例化对象。当使用 获取子系统的接口时,引擎会利用它的反射系统来查找和创建 UMyGameInstanceSubsystem 类的实例
  4. 默认的单例模式UGameInstanceSubsystem 及其子类通常是作为单例实现的。这意味着无论在哪里调用 GetEngineSubsystem,它都会返回同一个实例。
  • 9
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
UE5嵌入Echarts可以通过以下步骤实现: 1. 在UE5创建一个Web端的UI组件,用于显示Echarts图表。 2. 在Web端的UI组件引入Echarts的JavaScript库和相关的样式文件。 3. 在Web端的UI组件编写JavaScript代码,使用Echarts的API来生成图表并将数据传递给Echarts。 4. 在UE5调用Web端的UI组件,并将需要展示的数据传递给Web端。 5. 在UE5监听数据的变化,并在数据发生变化时更新Web端的UI组件。 下面是一个示例代码,演示了如何在UE5嵌入Echarts: ```cpp // 在UE5创建一个Web端的UI组件,用于显示Echarts图表 UCLASS() class UWebUIComponent : public UUserWidget { GENERATED_BODY() public: // 在构造函数加载Web端的UI组件 UWebUIComponent() { // 加载Web端的UI组件 LoadWebUI(TEXT("http://localhost:8080/echarts.html")); } // 在UE5调用Web端的UI组件,并将需要展示的数据传递给Web端 void UpdateChartData(const FString& Data) { // 调用Web端的JavaScript函数,传递数据 CallJavascriptFunction(TEXT("updateChartData"), Data); } }; // 在UE5监听数据的变化,并在数据发生变化时更新Web端的UI组件 void UpdateDataInUE5() { // 获取需要展示的数据 FString Data = GetChartData(); // 创建Web端的UI组件 UWebUIComponent* WebUIComponent = NewObject<UWebUIComponent>(); // 更新数据 WebUIComponent->UpdateChartData(Data); } ``` 请注意,以上代码仅为示例,具体的实现方式可能会因项目需求而有所不同。你可以根据自己的需求进行相应的修改和调整。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

宗浩多捞

您的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值