启用SQLite插件 Enable the SQLite plugins
-
编辑器界面下 Edit > Plugins 并搜索“sqlite”.
-
Check “SQLite” and “SQLite Support”. This will add the following content to your .uproject file:
{
"Name": "SQLiteCore",
"Enabled": true
},
{
"Name": "SQLiteSupport",
"Enabled": true
}
如果是插件开发,则将上述内容添加到.uplugin文件中。
- Add the necessary private dependencies to your
<Game>
.Build.cs file:
PrivateDependencyModuleNames.AddRange(new string[] { "SQLiteCore", "SQLiteSupport" });
这样我们就能添加#include "SQLiteDatabase.h"
和#include "SQLitePreparedSatatement"
了。
将数据库添加到project中(打包用)
- 打开项目的Content文件夹并为数据库添加一个新文件夹,可以叫Databases。我们将无法通过虚幻编辑器导入数据库,因此只需打开文件管理器并将其放入该文件夹即可。
- 为了确保该文件夹与您的游戏打包在一起,请转到 Edit > Project Settings > Packaging > Advanced > Additional Non-Asset Directories to Copy 。
- 添加一个数组元素,然后键入文件夹的名称,例如“Databases”。这可能会向您的DefaultGame.ini文件添加一堆条目,比如这一行:
+DirectoriesToAlwaysStageAsNonUFS=(Path="Databases")
构建数据库操作类
.h构建一个基类,后面操作不同的数据库获取不同的数据类型继承这个类。
#pragma once
#include "CoreMinimal.h"
class FSQLiteDatabase;
class FSQLitePreparedStatement;
/**
*
*/
class EARTH_API TerrainDatabase
{
public:
TerrainDatabase();
virtual TerrainDatabase();
virtual bool OpenDatabase(const FString& databasePath, bool readOnly);//创建或打开数据库
virtual bool CreateTable();//创建表
private:
FSQLiteDatabase* m_terrainDb;
FSQLitePreparedStatement* m_prepareStat;
};
.cpp
在cpp中包含标头:#include "SQLiteDatabase.h"
和#include "SQLitePreparedSatatement"
。
在构造函数中初始化类:
TerrainDatabase::TerrainDatabase()
{
m_terrainDb = new FSQLiteDatabase();
m_prepareStat = new FSQLitePreparedStatement();
}
OpenDatabase函数中调用FSQLiteDatabase类的打开函数进行数据库的打开操作,操作分为只读,读写和打开读写。设计的表分3列。
bOpened = m_terrainDb.Open(*databasePath, ESQLiteDatabaseOpenMode::ReadWriteCreate);
FString createTableSQL = TEXT(
"CREATE TABLE IF NOT EXISTS TT_TerrainTrans ("
"ID INTEGER PRIMIAY KEY AUTOINCREMENT, "
"Name TEXT, "
"TransMatrix BLOB"
");"
);
基类基本完成,这时构建子类FTerrainTransDatabase继承基类。 子类实现插入数据及查询数据,用以实现序列化后数据的入库及读取。 插入数据:
TArray<unit8> blobData;
const FString insertSQL = TEXT("INSERT INTO TT_TerrainTrans (Name, TransMatrix) VALUES (?,?);");
bool bPrepared = m_prepareStat->Create(*m_terrainDb, *insertSQL, ESQLitePreparedStatementFlags::Presisent);//构建状态
m_prepareStat->SetBindingValueByIndex(1, objectName);//绑定参数
m_prepareStat->SetBindingValueByIndex(2, blobData);
m_prepareStat->Execute();//执行语句
查询数据:
const FString selectSQL = TEXT("SELECT TransMatrix FROM TT_TerrainTrans WHERE Name = ?;");
if(m_prepareStat->Step() == ESQLitePreparedStatementStepResult::Row)
{
m_prepareStat->GetColumnValueByName(TEXT("TransMatrix"), binaryData);
}
序列化时的一些参数配置
利用FObjectAndNameAsStringProxyArchive
设置资产的一些属性,进而影响后续序列化的结果。
TArray<uint8> binaryData;
FObjectWriter objectWriter(binaryData);
UTileTransformAsset* transAsset = NewObject<UTileTransformAsset>(GetTransientPackage());//UTileTransformAsset继承与UObject
FObjectAndNameAsStringProxyArchive writeArchive(objectWriter, true);
writeArchive.SetIsPersisent(true);
transAsset->Serialize(writeArchive);
序列化数据的压缩与解压
要压缩 FObjectAndNameAsStringProxyArchive 序列化的数据,可以在将其数据存储到TArray<uint8>
后使用 Unreal Engine 提供的压缩工具。常用的方法是 FCompression 类,它支持多种压缩算法,如 Zlib、Gzip、LZ4 等。
- 序列化并压缩数据
首先,将对象序列化到一个字节数组TArray<uint8>
中,然后对数据进行压缩。
#include "Serialization/ObjectAndNameAsStringProxyArchive.h"
#include "Serialization/MemoryWriter.h"
#include "Serialization/MemoryReader.h"
#include "Misc/Compression.h"
bool SerializeAndCompressObject(UObject* Object, TArray<uint8>& OutCompressedData)
{
// 创建一个字节数组用于序列化数据
TArray<uint8> UncompressedData;
FMemoryWriter MemoryWriter(UncompressedData, true);
// 使用 FObjectAndNameAsStringProxyArchive 进行序列化
FObjectAndNameAsStringProxyArchive Ar(MemoryWriter, true);
Object->Serialize(Ar);
// 压缩数据
return FCompression::CompressMemory(
NAME_Zlib, // 使用 Zlib 算法压缩
OutCompressedData, // 输出压缩后的数据
UncompressedData.GetData(), // 输入未压缩的数据
UncompressedData.Num(), // 输入数据的字节数
COMPRESS_BiasMemory // 压缩方式,可根据需要选择
);
}
在这个代码中:
- SerializeAndCompressObject 函数接受一个 UObject 指针,并将序列化后压缩的数据存储在 OutCompressedData 中。
- FCompression::CompressMemory 使用 Zlib 算法对序列化的数据进行压缩。
- 解压缩并反序列化数据
在需要读取压缩数据时,首先解压缩数据,然后使用 FObjectAndNameAsStringProxyArchive 将其反序列化到对象中。
bool DecompressAndDeserializeObject(UObject* Object, const TArray<uint8>& CompressedData)
{
// 创建一个数组用于存储解压后的数据
TArray<uint8> DecompressedData;
// 获取解压后的数据大小
int32 UncompressedSize = FCompression::GetUncompressedSize(NAME_Zlib, CompressedData.GetData(), CompressedData.Num());
if (UncompressedSize <= 0)
{
return false; // 无法获取解压后的大小
}
// 设置解压后的数据大小
DecompressedData.SetNum(UncompressedSize);
// 解压数据
if (!FCompression::UncompressMemory(
NAME_Zlib,
DecompressedData.GetData(),
DecompressedData.Num(),
CompressedData.GetData(),
CompressedData.Num()))
{
return false; // 解压失败
}
// 使用 FMemoryReader 和 FObjectAndNameAsStringProxyArchive 进行反序列化
FMemoryReader MemoryReader(DecompressedData, true);
FObjectAndNameAsStringProxyArchive Ar(MemoryReader, true);
Object->Serialize(Ar);
return true;
}
Reference
「如果这篇文章对你有用,请随意打赏」
如果这篇文章对你有用,请随意打赏
使用微信扫描二维码完成支付

comments powered by Disqus