Fork me on GitHub

UE4 从无到有纯 C++ & Slate 开发沙盒游戏(十一) 读取存档Json文件

上一篇只是将一个Json文件加载进内存,并没有对文件进行解析,接下来写一个解析Json文件的方法,把文件的中的字符串解析成我们所需要的数据资源

 

 

首先将SlAiSingleton.cpp中的内容都放置到 SlAiSingleton.h 中

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 
14     static void Initialize();
15 
16     static TSharedRef<T> Create();
17 
18 private:
19     static TSharedPtr<T> TInstance;
20 
21 };
22 
23 
24 template<class T>
25 TSharedPtr<T> SlAiSingleton<T>::TInstance = NULL;
26 
27 //创建一个共享的引用
28 template<class T>
29 TSharedRef<T> SlAiSingleton<T>::Create()
30 {
31     TSharedRef<T> TRef = MakeShareable(new T());
32     return TRef;
33 }
34 
35 template<class T>
36 void SlAiSingleton<T>::Initialize()
37 {
38     //判断指针是否存在,如果不存在则Cteate一个
39     if (!TInstance.IsValid())
40     {
41         TInstance = Create();
42     }
43 }
44 
45 template<class T>
46 TSharedPtr<T> SlAiSingleton<T>::Get()
47 {
48     Initialize();
49     return TInstance;
50 }

d:\ue4 project\ue26.2\courseproject\slaicourse\Source\SlAiCourse\Private\Data\SlAiSingleton.cpp

SlAiSingleton.cpp 文件中则没有内容

1 #include "Data/SlAiSingleton.h"

 

 

解析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     /**
15      * 解析存档的方法
16      *Culture 为 ECultureTeam 下的 EN、ZH等值,
17      * 四个参数分别对应Json中的 Culture、MusicVolume、SoundVolume、RecordData
18      */
19     void RecordDataJsonRead(FString& Culture, float& MusicVolume, float& SoundVolume, TArray<FString>& RecordDataList);
20 
21 private:
22     //读取Json文件到字符串
23     bool LoadStringFromFile(const FString& FileName, const FString& RelaPath, FString& ResultString);
24 
25 private:
26     //存档文件名
27     FString RecordDataFileName;
28     //相对路径
29     FString RelativePath;
30 
31 };

 

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 void SlAiJsonHandle::RecordDataJsonRead(FString& Culture, float& MusicVolume, float& SoundVolume, TArray<FString>& RecordDataList)
11 {
12     //保存读取到的所有 Json 数据
13     FString JsonValue;
14 
15     //读取文件保存到 JsonValue
16     LoadStringFromFile(RecordDataFileName, RelativePath, JsonValue);
17 
18     //这是一个二维数组,用来保存解析出来的数据
19     TArray<TSharedPtr<FJsonValue>> JsonParsed;
20 
21     //将读取出来的数据通过一个Json读取的共享类TJsonReaderFactory 保存到JsonReader的引用
22     TSharedRef<TJsonReader<TCHAR>> JsonReader = TJsonReaderFactory<TCHAR>::Create(JsonValue);
23 
24     //解析
25     if (FJsonSerializer::Deserialize(JsonReader, JsonParsed))
26     {
27         //从对应数组下标,获取对应类型,对应字段的数据
28         Culture = JsonParsed[0]->AsObject()->GetStringField(FString("Culture"));
29         MusicVolume = JsonParsed[1]->AsObject()->GetNumberField(FString("MusicVolume"));
30         SoundVolume = JsonParsed[2]->AsObject()->GetNumberField(FString("SoundVolume"));
31 
32         //获取存档数据
33         TArray<TSharedPtr<FJsonValue>> RecordDataArray = JsonParsed[3]->AsObject()->GetArrayField(FString("RecordData"));
34         for (int i = 0; i < RecordDataArray.Num(); ++i)
35         {
36             FString RecordDataName = RecordDataArray[i]->AsObject()->GetStringField(FString::FromInt(i));
37             //保存到
38             RecordDataList.Add(RecordDataName);
39         }
40     }
41     else
42     {
43         SlAiHelper::Debug(FString("Deserialize Failed"));
44     }
45 }
46 
47 bool SlAiJsonHandle::LoadStringFromFile(const FString& FileName, const FString& RelaPath, FString& ResultString)
48 {
49     if (!FileName.IsEmpty())
50     {
51         //获取绝对路径 (ProjectContentDir() 是原来的 GameContentDir(), 4.26版本后改名了)
52         FString AbsoPath = FPaths::ProjectContentDir() + RelaPath + FileName;
53 
54         //判断文件是否存在
55         if (FPaths::FileExists(AbsoPath))
56         {
57             if (FFileHelper::LoadFileToString(ResultString, *AbsoPath))
58             {
59                 return true;
60             }
61             else
62             {
63                 //加载不成功
64                 SlAiHelper::Debug(FString("Load Error!!") + AbsoPath);
65                 return false;
66             }
67         }
68         else
69         {
70             //输出文件不存在
71             SlAiHelper::Debug(FString("File Not Exist!!") + AbsoPath);
72         }
73     }
74     return false;
75 }

 

 

然后菜单初始化是调用Json文件,将配置内容初始化

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     TArray<FString> RecordDataList;
31 
32 private:
33     //创建单例
34     static TSharedRef<SlAiDataHandle> Create();
35 
36     //根据enum类型获取字符串(该方法只能用于UENUM()反射后的枚举,普通枚举不能这样搞)
37     template<typename TEnum>
38     FString GetEnumValueAsString(const FString& Name, TEnum Value);
39 
40     //根据字符串获取enum值(该方法只能用于UENUM()反射后的枚举,普通枚举不能这样搞)
41     template<typename TEnum>
42     TEnum GetEnumValueFromString(const FString& Name, FString Value);
43 
44     //初始化存档数据
45     void InitRecordData();
46 
47 private:
48     static TSharedPtr<SlAiDataHandle> DataInstance;
49 };

 

D:\UE4 Project\UE26.2\CourseProject\SlAiCourse\Source\SlAiCourse\Private\Data\SlAiDataHandle.cpp

  1 #include "Data/SlAiDataHandle.h"
  2 #include "Internationalization/Internationalization.h"
  3 #include "Data/SlAiSingleton.h"
  4 #include "Data/SlAiJsonHandle.h"
  5 #include "Common/SlAiHelper.h"
  6 
  7 TSharedPtr<SlAiDataHandle> SlAiDataHandle::DataInstance = NULL;
  8 
  9 SlAiDataHandle::SlAiDataHandle()
 10 {
 11     ////初始化中文
 12     //CurrentCulture = ECultureTeam::ZH;
 13     ////初始化音乐
 14     //MusicVolume = 0.5f;
 15     ////初始化音效
 16     //SoundVolume = 0.5f;
 17 
 18     //初始化存档数据
 19     InitRecordData();
 20 }
 21 
 22 void SlAiDataHandle::Initialize()
 23 {
 24     if (!DataInstance.IsValid())
 25     {
 26         DataInstance = Create();
 27     }
 28 }
 29 
 30 TSharedPtr<SlAiDataHandle> SlAiDataHandle::Get()
 31 {
 32     Initialize();
 33     return DataInstance;
 34 }
 35 
 36 TSharedRef<SlAiDataHandle> SlAiDataHandle::Create()
 37 {
 38     /**
 39     *MakeShareable 可以用来创建共享指针和共享引用
 40     */
 41     TSharedRef<SlAiDataHandle> DataRef = MakeShareable(new SlAiDataHandle());
 42     return DataRef;
 43 }
 44 
 45 void SlAiDataHandle::ChangeLocalizationCulture(ECultureTeam Culture)
 46 {
 47     switch (Culture)
 48     {
 49     case ECultureTeam::EN:
 50         FInternationalization::Get().SetCurrentCulture(TEXT("en"));
 51         break;
 52     case ECultureTeam::ZH:
 53         FInternationalization::Get().SetCurrentCulture(TEXT("zh"));
 54         break;
 55     }
 56     //赋值
 57     CurrentCulture = Culture;
 58 }
 59 
 60 void SlAiDataHandle::ResetMenuVolume(float MusicVol, float SoundVol)
 61 {
 62     if (MusicVol > 0)
 63     {
 64         MusicVolume = MusicVol;
 65     }
 66     if (SoundVol > 0)
 67     {
 68         SoundVolume = SoundVol;
 69     }
 70 }
 71 
 72 //根据枚举值返回字符串
 73 template<typename TEnum>
 74 FString SlAiDataHandle::GetEnumValueAsString(const FString& Name, TEnum Value)
 75 {
 76     //通过UE4的FindObject寻找所有ANY_PACKAGE反射到的Name,寻找到后实例化后返回
 77     const UEnum* EnumPtr = FindObject<UEnum>(ANY_PACKAGE, *Name, ture);
 78 
 79     if (!EnumPtr)
 80     {
 81         return FString("InValid");
 82     }
 83     return EnumPtr->GetEnumName((int32)Value);
 84 }
 85 
 86 //根据字符串返回枚举值
 87 template<typename TEnum>
 88 TEnum SlAiDataHandle::GetEnumValueFromString(const FString& Name, FString Value)
 89 {
 90     const UEnum* EnumPtr = FindObject<UEnum>(ANY_PACKAGE, *Name, true);
 91 
 92     if (!EnumPtr)
 93     {
 94         return TEnum(0);
 95     }
 96     return (TEnum)EnumPtr->GetIndexByName(FName(*FString(Value)));
 97 }
 98 
 99 void SlAiDataHandle::InitRecordData()
100 {
101     //获取语言
102     FString Culture;
103     //使用单例读取存档数据
104     SlAiSingleton<SlAiJsonHandle>::Get()->RecordDataJsonRead(Culture, MusicVolume, SoundVolume, RecordDataList);
105 
106     //初始化语言
107     ChangeLocalizationCulture(GetEnumValueFromString<ECultureTeam>(FString("ECultureTeam"), Culture));
108 
109     //输出打印
110     SlAiHelper::Debug(Culture + FString("--") + FString::SanitizeFloat(MusicVolume) + FString("--") + FString::SanitizeFloat(SoundVolume), 20.f);
111     
112     //输出打印 RecordDataList 使用迭代器循环读取RecordDataList
113     for (TArray<FString>::TIterator It(RecordDataList); It; It++)
114     {
115         SlAiHelper::Debug(*It, 20.f);
116     }
117 }

 

 

 

 

 

 

 

 

 

====================================================================================================================================

 

posted @ 2021-08-30 17:40  索智源  阅读(447)  评论(0编辑  收藏  举报