天天看點

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 }      

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