1、问题来源

最近的项目里面有个需求,要在打包之后的
exe
或者
apk
运行起来后访问工程
Content
或者安卓目录下的非
Asset
文件,比如
text
文件,
json
文件等,从中读取一些可随时修改的配置项信息。但是这些没法直接被
UE
平台序列化存储,因此需要做一点点额外的操作来实现我们的目标,假设工程目录
Content
里面有个
Json
目录,
Json
里面有个
A.json文件
,程序在运行时需要读取
A.json。

下面针对
Windows

Android
平台依次展开讨论怎么做。

2、Windows平台

第一步
,在
Project Settings->Project->Packaging下面,取消勾选Use Pak File,因为打包成.pak文件的话,Content目录下的所有资源(Asset文件或Non-Asset文件),都会被打包进一个.pak文件,后期无法随时修改。

第二步,在
Project Setting
顶部搜索
asset
,在
Additional Non-Asset Directories to Package右边点击加号,在新增的一行右侧点击"..."标记,新增一条路径指向Conent目录下的Json文件夹。

打包一下,文件夹里面显示我们的
Json/A
.json
已经作为独立文件成功打包到
WindowsNoEditor
目录下。

写几行测试一下看看行不行,假设我要蓝图里面读
A.json

C++
封装函数如下,其实主要是要通过
FPaths::ConvertRelativePathToFull(FPaths::ProjectContentDir()) + JsonName拼接得到A.json的正确绝对路径

1 bool UJsonOperator::FindValueWithGivenProperty(FString JsonName, FString FieldName, FString&Val)2 {3     FString AbsoluteJsonPath = FPaths::ConvertRelativePathToFull(FPaths::ProjectContentDir()) +JsonName;4     if (FPlatformFileManager::Get().GetPlatformFile().FileExists(*AbsoluteJsonPath)) {5         UE_LOG(MiniFileReaderLog, Warning, TEXT("%s"), *AbsoluteJsonPath); //do not call UKismetSystemLibrary::PrintString in static function
6 
7 FString JsonData;8         FFileHelper::LoadFileToString(JsonData, *AbsoluteJsonPath);9 
10         /*convert fstring to json object.*/
11         TSharedRef<TJsonReader<>> JsonReader = TJsonReaderFactory<>::Create(JsonData);12         TSharedPtr<FJsonObject> RootJsonObj = MakeShareable(newFJsonObject);13 
14         if(FJsonSerializer::Deserialize(JsonReader, RootJsonObj)) {15             UE_LOG(MiniFileReaderLog, Warning, TEXT("Json Data: %s"), *JsonData);16 
17             TSharedPtr<FJsonValue> Member = RootJsonObj->TryGetField(FieldName);18             if(Member) {19                 Val = Member->AsString();20                 UE_LOG(MiniFileReaderLog, Log, TEXT("Property [%s], Value: %s"), *FieldName, *(Member->AsString()));21 }22             else{23                 UE_LOG(MiniFileReaderLog, Warning, TEXT("Property [%s] specified not exists."), *FieldName);24                 return false;25 }26 }27         else{28             UE_LOG(MiniFileReaderLog, Warning, TEXT("FJsonSerializer::Deserialize Failed!"));29             return false;30 }31 }32     else{33         UE_LOG(MiniFileReaderLog, Error, TEXT("File : %s not exists."), *JsonName);34         return false;35 }36     return true;37 }

3、Android平台

Android
平台略有不同,

UE
工程发布到安卓设备并启动之后,会在安卓设备的
/storage/emulated/0/UE4Game
目录下新建一个和
UE Project Name
的同名目录。该目录存放程序的运行数据,此处工程名假设为
FunctionProject

第一步,在运行数据目录新建
Json/A.json
,如下所示,里面存放程序需要读取的属性数据信息。

第二步,写一段示例代码读取到该目录下的A.json文件,如下所示:

bool UJsonOperator::LoadRawContentsToString(FString FileName, FString&FileContents)
{
#if PLATFORM_ANDROID externFString GFilePathBase;
FString tmp
= GFilePathBase + FString("/UE4Game/") + UKismetSystemLibrary::GetGameName() + FString("/") +FileName;
GEngine
->AddOnScreenDebugMessage(-1, 5.f, FColor::Blue, FString::Printf(TEXT("%s"), *tmp));return FFileHelper::LoadFileToString(FileContents, *tmp);#else const FString ThePath =FPaths::ConvertRelativePathToFull(FPaths::ProjectContentDir());
UE_LOG(MiniFileReaderLog, Log, TEXT(
"Json Path: %s"), *(ThePath +FileName));return FFileHelper::LoadFileToString(FileContents, *(ThePath +FileName));#endif}

此处,
UKismetSystemLibrary::GetGameName()
就是获取
UE4Game
目录下的
APP
发布名称,可以理解为
Android APP
运行数据的根目录,函数传入参数的第
1
个参数
FileName

Json/A.json
,那么最终拼接得到的
A.json
绝对路径为:

/storage/emulated/0/UE4Game/FunctionProject/Json/A.json

拿到这个绝对路径,就可以读取文件内容了,到此结束!

标签: none

添加新评论