Fork me on GitHub

UE4 从无到有纯 C++ & Slate 开发沙盒游戏(十) 模板单例与文件读取

这个部分将会写一些数据方面的部分,前边代码中有过语言、音量等数据。这些数据是记录到 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 }

 

 

 

 

 

 

 

 

 

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

 

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