(UE44.20)UE4的全局单例模式Singleton(变量在切换关卡
时不被GC)
UE4开发中,很多对象在切换关卡中,伴随定义在Actor的各种对象伴随着Actor的消亡也被GC掉了。⽐如在我们AMyCharacter⾥定义各种UObject变量,等切换关卡时,我们的Character销毁了,于是⾥⾯的各种UObject也跟着消亡被GC了。那么我们如果需要⼀些数据在游戏中全局存在,得怎么办呢?
⼀般两种⽅式:
(1)在MyGameInstance定义的对象, 切换关卡的时候是不被GC的,是全局存在的。
(2)⽤SaveGame来保存相应的数据,但是SaveGame应该更多⽤于游戏关闭后保存数据在本地,在开始时在读取数据的情况。(也就是存储和读取游戏档案),当然你可以巧妙的在上⼀个关卡结束时保存数据到本地,下⼀个关卡时在读取本地的数据。
我们经常性的需要⼀些跨越整个游戏的单例类,并且这些单例类的属性变量,哪怕切换关卡,相应的变量都不会被GC掉。
这时候我们可以定义全局单例类Singleton
怎么实现全局单例模式Singleton呢?
定义最先存在的单例类GameSingleton, 与GEngine->GameSingleton关联
GameSingleton为游戏刚开始的单例类对象,起源于GEngine->GameSingleton,负责创建和查询各种继承于SingleAttribute的单例属性类,并且NewObject的对象为 “GameInstance”,GameInstance游戏全局都不会被GC,相应的被NewObject出来的SingleAttribute也不会被GC。
#pragma once
#include "CoreMinimal.h"
#include "UObject/NoExportTypes.h"
#include "ated.h"
class USingletonAttribute;
class UGameInstance;
/**
*
*/
UCLASS()
class SINGLELOBJECT_API UGameSingleton : public UObject
{
GENERATED_BODY()
public:
UGameSingleton();
static UGameSingleton* Get();
UPROPERTY()
TArray<USingletonAttribute*> arraySingletonAttribute;
template<typename T>
void AddSingletonAttribute(UGameInstance* gameInstance)
{
for (int index = 0; index < arraySingletonAttribute.Num(); ++index)
{
if (arraySingletonAttribute[index]->GetClass() == T::StaticClass())
return;
}
const FName singletonAttributeName = "singletonAttribute";
T* singletonAttribute = NewObject<T>(gameInstance, singletonAttributeName);
if (nullptr == singletonAttribute)
return;
arraySingletonAttribute.Add(singletonAttribute);generated
}
template<typename T>
T* GetSingletonAttribute()
{
T* singletonAttribute = nullptr;
for (int index = 0; index < arraySingletonAttribute.Num(); ++index)
{
if (arraySingletonAttribute[index]->GetClass() == T::StaticClass())
{
singletonAttribute = Cast<T>(arraySingletonAttribute[index]);
break;
}
}
return singletonAttribute;
}
};
#define GGameSingleton UGameSingleton::Get()
// Fill out your copyright notice in the Description page of Project Settings.
#include "GameSingleton.h"
#include "Engine/Engine.h"
UGameSingleton::UGameSingleton()
{
}
UGameSingleton* UGameSingleton::Get()
{
#if WITH_EDITOR
return Cast<UGameSingleton>(GEngine->GameSingleton);
#else
static UGameSingleton* singletonObject = Cast<UGameSingleton>(GEngine->GameSingleton);
return singletonObject;
#endif
}
UGameSingleton* UGameSingleton::singletonObject = nullptr;
定义我们的单例属性类SingleAttribute
SingleAttribute是各种单例属性的基础类,如GameWeatherAttribute(管理全局游戏天⽓属性)等等会继承于SingleAttribute
#include "CoreMinimal.h"
#include "UObject/NoExportTypes.h"
#include "ated.h"
/**
*
*/
UCLASS()
class SINGLELOBJECT_API USingletonAttribute : public UObject
{
GENERATED_BODY()
public:
USingletonAttribute();
};
#include "SingletonAttribute.h"
USingletonAttribute::USingletonAttribute()
{
}
游戏天⽓属性单例类:GameWeatherAttribute
作为⼀个管理游戏天⽓的单例类,全局不会被GC,这⾥定义⼀些变量
#pragma once
#include "CoreMinimal.h"
#include "SingletonAttribute.h"
#include "ated.h"
/**
*
*/
UCLASS()
class SINGLELOBJECT_API UGameWeatherAttribute : public USingletonAttribute {
GENERATED_BODY()
public:
float a;
float b;
float c;
public:
static UGameWeatherAttribute* Get();
};
#include "GameWeatherAttribute.h"
#include "GameSingleton.h"
UGameWeatherAttribute* UGameWeatherAttribute::Get()
{
return GGameSingleton->GetSingletonAttribute<UGameWeatherAttribute>();
}
游戏⼊⼝:MyGameInstance
#pragma once
#include "CoreMinimal.h"
#include "Engine/GameInstance.h"
#include "ated.h"
/**
*
*/
UCLASS()
class SINGLELOBJECT_API UMyGameInstance : public UGameInstance
{
GENERATED_BODY()
public:
UMyGameInstance();
protected:
virtual void StartGameInstance() override;
virtual FGameInstancePIEResult StartPlayInEditorGameInstance(ULocalPlayer* LocalPlayer,  const FGameInstancePIEParameters& Params) override;
};
#include "MyGameInstance.h"
#include "GameSingleton.h"
#include "GameWeatherAttribute.h"
UMyGameInstance::UMyGameInstance()
{
}
void UMyGameInstance::StartGameInstance()
{
FGameInstancePIEResult InitResult = FGameInstancePIEResult::Failure(FText());
UGameInstance* gameInstance = GetWorld()->GetGameInstance();
if (nullptr == gameInstance)
return;
GGameSingleton->AddSingletonAttribute<UGameWeatherAttribute>(gameInstance);
UGameWeatherAttribute* gameWeatherAttribute = UGameWeatherAttribute::Get();
if (nullptr == gameWeatherAttribute)
{
UE_LOG(LogTemp, Error, TEXT("can not get UGameWeatherAttribute ptr"));
return;
}
gameWeatherAttribute->a = 1;
gameWeatherAttribute->b = 2;
gameWeatherAttribute->c = 4;
Super::StartGameInstance();

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。