这个部分将会写一些数据方面的部分,前边代码中有过语言、音量等数据。这些数据是记录到 json 文件中的。
如:D:\UE4 Project\UE26.2\CourseProject\SlAiCourse\Content\Res\ConfigDate\RecordData.json
[ { "Culture":"ZH" }, { "MusicVolume": 0.3 }, { "SoundVolume": 0.3 }, { "RecordData": [ { "0": "Default" } ] } ]
UE4项目读取 json 文件,需在项目的 Build 文件添加相关 Module ,如:
D:\UE4 Project\UE26.2\CourseProject\SlAiCourse\Source\SlAiCourse\SlAiCourse.Build.cs
1 // Copyright Epic Games, Inc. All Rights Reserved. 2 3 using UnrealBuildTool; 4 5 public class SlAiCourse : ModuleRules 6 { 7 public SlAiCourse(ReadOnlyTargetRules Target) : base(Target) 8 { 9 PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs; 10 11 PublicDependencyModuleNames.AddRange(new string[] 12 { 13 "Core", 14 "CoreUObject", 15 "Engine", 16 "InputCore", 17 "Slate", //由于要使用 Slate 的UI架构,这里加 Slate 的 Module 18 "SlateCore", 19 "Json", 20 "JsonUtilities", //Json 工具 21 }); 22 23 PrivateDependencyModuleNames.AddRange(new string[] { }); 24 25 // Uncomment if you are using Slate UI 26 // PrivateDependencyModuleNames.AddRange(new string[] { "Slate", "SlateCore" }); 27 28 // Uncomment if you are using online features 29 // PrivateDependencyModuleNames.Add("OnlineSubsystem"); 30 31 // To include OnlineSubsystemSteam, add it to the plugins section in your uproject file with the Enabled attribute set to true 32 } 33 }
添加完后一定要运行编译一次项目,让项目添加下Module,避免直接使用出现一些莫名其妙的报错
新建两个C++类
要在 SlAiSingleton类中实现C++基于模板类的单例模式,和一个JsonHandle的控制类
然后去 SlAiDataHandle 添加两个模板方法
1. 根据enum类型获取字符串
2. 根据字符串获取enum值
下方代码中加粗的内容
D:\UE4 Project\UE26.2\CourseProject\SlAiCourse\Source\SlAiCourse\Public\Data\SlAiDataHandle.h
1 #include "SlAiTypes.h" 2 #include "CoreMinimal.h" 3 4 5 class SLAICOURSE_API SlAiDataHandle 6 { 7 public: 8 SlAiDataHandle(); 9 10 static void Initialize(); 11 12 static TSharedPtr<SlAiDataHandle> Get(); 13 14 //修改中英文 15 void ChangeLocalizationCulture(ECultureTeam Culture); 16 //修改菜单音量大小 17 void ResetMenuVolume(float MusicVol, float SoundVol); 18 19 public: 20 /** 21 * 这里没有使用 GamePlay 框架的 GameInstance,变量直接写到C++类中除非你主动销毁,否则他会一直存在 22 */ 23 //语言状态 24 ECultureTeam CurrentCulture; 25 //音乐状态 26 float MusicVolume; 27 //音效状态 28 float SoundVolume; 29 30 private: 31 //创建单例 32 static TSharedRef<SlAiDataHandle> Create(); 33 34 //根据enum类型获取字符串(该方法只能用于UENUM()反射后的枚举,普通枚举不能这样搞) 35 template<typename TEnum> 36 FString GetEnumValueAsString(const FString& Name, TEnum Value); 37 38 //根据字符串获取enum值(该方法只能用于UENUM()反射后的枚举,普通枚举不能这样搞) 39 template<typename TEnum> 40 TEnum GetEnumValueFromString(const FString& Name, FString Value); 41 42 private: 43 static TSharedPtr<SlAiDataHandle> DataInstance; 44 45 };
相关实现
D:\UE4 Project\UE26.2\CourseProject\SlAiCourse\Source\SlAiCourse\Private\Data\SlAiDataHandle.cpp
// Fill out your copyright notice in the Description page of Project Settings. #include "Data/SlAiDataHandle.h" #include "Internationalization/Internationalization.h" TSharedPtr<SlAiDataHandle> SlAiDataHandle::DataInstance = NULL; SlAiDataHandle::SlAiDataHandle() { //初始化中文 CurrentCulture = ECultureTeam::ZH; //初始化音乐 MusicVolume = 0.5f; //初始化音效 SoundVolume = 0.5f; } void SlAiDataHandle::Initialize() { if (!DataInstance.IsValid()) { DataInstance = Create(); } } TSharedPtr<SlAiDataHandle> SlAiDataHandle::Get() { Initialize(); return DataInstance; } TSharedRef<SlAiDataHandle> SlAiDataHandle::Create() { /** *MakeShareable 可以用来创建共享指针和共享引用 */ TSharedRef<SlAiDataHandle> DataRef = MakeShareable(new SlAiDataHandle()); return DataRef; } void SlAiDataHandle::ChangeLocalizationCulture(ECultureTeam Culture) { switch (Culture) { case ECultureTeam::EN: FInternationalization::Get().SetCurrentCulture(TEXT("en")); break; case ECultureTeam::ZH: FInternationalization::Get().SetCurrentCulture(TEXT("zh")); break; } //赋值 CurrentCulture = Culture; } void SlAiDataHandle::ResetMenuVolume(float MusicVol, float SoundVol) { if (MusicVol > 0) { MusicVolume = MusicVol; } if (SoundVol > 0) { SoundVolume = SoundVol; } } template<typename TEnum> FString SlAiDataHandle::GetEnumValueAsString(const FString& Name, TEnum Value) { //通过UE4的FindObject寻找所有ANY_PACKAGE反射到的Name,寻找到后实例化后返回 const UEnum* EnumPtr = FindObject<UEnum>(ANY_PACKAGE, *Name, ture); if (!EnumPtr) { return FString("InValid"); } return EnumPtr->GetEnumName((int32)Value); } template<typename TEnum> TEnum SlAiDataHandle::GetEnumValueFromString(const FString& Name, FString Value) { const UEnum* EnumPtr = FindObject<UEnum>(ANY_PACKAGE, *Name, ture); if (!EnumPtr) { return TEnum(0); } return (TEnum)EnumPtr->GetIndexByName(FName(*FString(Value))); }
写一个基于模板的单例 SlAiSingleton ,算是一个扩展
D:\UE4 Project\UE26.2\CourseProject\SlAiCourse\Source\SlAiCourse\Public\Data\SlAiSingleton.h
1 #include "CoreMinimal.h" 2 3 /** 4 * 5 */ 6 template<class T> 7 class SLAICOURSE_API SlAiSingleton 8 { 9 public: 10 static TSharedPtr<T> Get(); 11 12 private: 13 static void Initialize(); 14 15 static TSharedPtr<T> Cteate(); 16 17 private: 18 static TSharedPtr<T> TInstance; 19 };
d:\ue4 project\ue26.2\courseproject\slaicourse\Source\SlAiCourse\Private\Data\SlAiSingleton.cpp
1 #include "Data/SlAiSingleton.h" 2 3 template<class T> 4 TSharedPtr<T> SlAiSingleton<T>::TInstance = NULL; 5 6 //创建一个共享的引用 7 template<class T> 8 TSharedPtr<T> SlAiSingleton<T>::Cteate() 9 { 10 TSharedPtr<T> TRef = MakeShareable(new T()); 11 return TRef; 12 } 13 14 template<class T> 15 void SlAiSingleton<T>::Initialize() 16 { 17 //判断指针是否存在,如果不存在则Cteate一个 18 if (!TInstance->IsValid()) 19 { 20 TInstance = Cteate(); 21 } 22 } 23 24 template<class T> 25 TSharedPtr<T> SlAiSingleton<T>::Get() 26 { 27 Initialize(); 28 return TInstance; 29 }
然后实现Json文件的读取相关内容
d:\ue4 project\ue26.2\courseproject\slaicourse\Source\SlAiCourse\Public\Data\SlAiJsonHandle.h
1 #include "CoreMinimal.h" 2 #include "SlAiTypes.h" 3 #include "Json.h" 4 5 6 /** 7 * 8 */ 9 class SLAICOURSE_API SlAiJsonHandle 10 { 11 public: 12 SlAiJsonHandle(); 13 14 private: 15 //读取Json文件到字符串 16 bool LoadStringFromFile(const FString& FileName, const FString& RelaPath, FString& ResultString); 17 18 private: 19 //存档文件名 20 FString RecordDataFileName; 21 //相对路径 22 FString RelativePath; 23 24 };
d:\ue4 project\ue26.2\courseproject\slaicourse\Source\SlAiCourse\Private\Data\SlAiJsonHandle.cpp
1 #include "Data/SlAiJsonHandle.h" 2 #include "Common/SlAiHelper.h" 3 4 SlAiJsonHandle::SlAiJsonHandle() 5 { 6 RecordDataFileName = FString("RecordData.json"); 7 RelativePath = FString("Res/ConfigData/"); 8 } 9 10 bool SlAiJsonHandle::LoadStringFromFile(const FString& FileName, const FString& RelaPath, FString& ResultString) 11 { 12 if (!FileName.IsEmpty()) 13 { 14 //获取绝对路径 15 FString AbsoPath = FPaths::GameContentDir() + RelaPath + FileName; 16 17 //判断文件是否存在 18 if (FPaths::FileExists(AbsoPath)) 19 { 20 if (FFileHelper::LoadFileToString(ResultString, *AbsoPath)) 21 { 22 return true; 23 } 24 else 25 { 26 //加载不成功 27 SlAiHelper::Debug(FString("Load Error!!") + AbsoPath); 28 } 29 } 30 else 31 { 32 //输出文件不存在 33 SlAiHelper::Debug(FString("File Not Exist!!") + AbsoPath); 34 } 35 } 36 37 return false; 38 }
==============================================================================================