目录
本篇日志将会介绍如何实现一个模拟经营游戏中的存档系统以及能够调整游戏画质分辨率等的游戏设置菜单,效果如下图:


一、存档类
1.创建一个SaveGame类
UE中存档的原理是我们建一个SaveGame类,然后我们在其中声明要存储的变量类型,再实例化一个该类的对象,将要存储的值传给该对象中声明的变量,再调用保存函数就能将数据以.sav文件的方式保存到本地,读档时也是从 该文件中实例化一个SaveGame对象,将该对象中的值赋给当前场景以实现数据的加载
创建SaveGame类的子类,这里我们已经创建好了两个类,一个存储全局设置包括存档栏,另一个储存关卡数据:

2.存储关卡内数据
每个关卡存档都包含关卡内必须要保存的数据,这里以玩家仓库为例,同时我们每个存档还有记录游玩总时长的功能,FTimeSpan是存储流逝的时间的结构,可以从秒数转化而来:
UCLASS()
class ASTROMUTATE_2_API USaveGameData : public USaveGame
{
GENERATED_BODY()
public:
UPROPERTY(EditAnywhere,BlueprintReadWrite,Category="SaveGame")
FInventoryInformation PlayerStorage;//玩家仓库
//游戏游玩的总秒数
UPROPERTY(EditAnywhere,BlueprintReadWrite,Category="Time")
int PlayedSeconds;
//游戏游玩的总时间
UPROPERTY(EditAnywhere,BlueprintReadWrite,Category="Time")
FTimespan PlayedTime;
};
接下来就可以实现保存游戏的函数了,首先传入存档的文件名,稍后在加载游戏是也是根据该存档的文件名来找到具体存档,SaveGameSlot中的第一个参数是要保存的SaveGame对象,第二个参数是本地存档文件的名字,第三个参数是玩家的索引,单机游戏使用0即可:
void ADebugActor::SaveGame(const FString& SaveFileName)
{
UE_LOG(LogTemp,Warning,TEXT("Saving"));
//实例化我们之前创建的SaveGame类
USaveGameData* DataToSave{ Cast<USaveGameData>(UGameplayStatics::CreateSaveGameObject(USaveGameData::StaticClass())) };
//该存档游玩的总秒数=之前读档是继承的总秒数+当前时间-进入游戏时获取的时间
DataToSave->PlayedSeconds=PlayedSeconds+(FDateTime::Now()-StartTime).GetTotalSeconds();
//将秒数转换为小时分钟
DataToSave->PlayedTime=FTimespan::FromSeconds(DataToSave->PlayedSeconds);
PlayedTime=DataToSave->PlayedTime;
//从场景中获取玩家库存信息
SetPlayerStorageEvent();
//将玩家库存数据赋值给存档类
DataToSave->PlayerStorage = PlayerStorage;
//将存档保存到本地
UGameplayStatics::SaveGameToSlot(DataToSave, SaveFileName, 0);
UE_LOG(LogTemp,Warning,TEXT("game succesfully saved"));
}
3.加载关卡数据
在加载存档前,无论是从主菜单加载还是从已经进入的关卡中加载,我们都需要重新打开这个关卡,在打开关卡之后,我们首先需要确保所有关键Actor初始化完成,如果是用c++定义的Actor,可以直接使用DispatchBeginPlay()来确保该actor执行完了BeginPlay中的所有步骤,没有用C++定义的actor比较麻烦,这里的实现方法时进入关卡后设置一个每0.5秒一检查的定时器,所有待加载的Actor都标记为已执行完BeginPlay后,再调用下面的LoadGame函数。
因为我们实现加载游戏函数的Actor是在关卡内的,所以要实现从主菜单加载,就在玩家点击存档栏中的存档时,将游戏实例中的存档文件名设置成要加载的存档的名字,然后在进入关卡时如果检查到这个文件名不为空,则执行加载。
void ADebugActor::BeginPlay()
{//省略了其他与存档系统无关的代码
Instance = Cast<UAstromutateGameInstance>(GetWorld()->GetGameInstance());
if (!Instance->IsValidLowLevel())
{
UE_LOG(LogTemp, Error, TEXT("BeginPlay in DebugActor failed,invalid pointer:Instance"));
return;
}
Super::Begi

5532

被折叠的 条评论
为什么被折叠?



