Unity3D 中使用 FlexBuffers(存储大型配置的可行替代方案)

1 篇文章 0 订阅

英文原文:https://mzaks.medium.com/flexbuffers-for-unity3d-4d1ab5c53fbe

  如果您在游戏中使用 JSON、CSV、XML 甚至 SQLite 来存储数据,那么您绝对应该花几分钟时间阅读这篇博文。如果你不这样做,你可能仍然会学到一些有用的东西。


Fl​​exBuffers 是什么?

  FlexBuffers 是一种 JSON 可比较的二进制格式,设计为 FlatBuffers 项目中的无模式替代方案,该项目最初由 Google 构建。

如果您对源头感兴趣,请点击链接


JSON 可比性是什么意思?

  我的意思是,您可以用 JSON 表示的所有内容也可以用 FlexBuffers 表示,反之亦然。这就是为什么 FlexBuffers Unity 提供了一种将 JSON 文件转换为 FlexBuffer 文件的简单方法的原因。并将 FlexBuffer 文件导出为 JSON 文件。但稍后再讨论这个话题。


为什么我应该使用 FlexBuffers 而不是 JSON?

  JSON 文件是一个文本文件。为了访问 JSON 文件中的数据,我们需要将文本转换为 C# 对象树。这意味着我们必须将文件的内容读入内存,解析文本,并创建 C# 对象树。有不同的 JSON 解析器,可以使某些步骤或多或少地执行,但是 JSON 解析器无法避免其中一个步骤。

  当您从 FlexBuffers 文件中读取值时,只有两个步骤:

  1. 将文件内容加载到内存中
  2. 访问字节数组中的值

  使用 FlexBuffers,我们不会将您的数据结构反映为 C# 对象树。我们可以使用如下表达式直接从字节数组中读取数据:

var root = FlxValue.FromBytes(bytes);
Assert.AreEqual("Berlin", root["address"]["city"].AsString);

  用这个表达式,我们说根有一个属性address,这个属性有一个自己的属性,叫做city。我们知道 city 是字符串类型,我们要求将此值转换为 C# 字符串类型的对象。

  基于访问语义 [] 的字节遍历非常快,我们可以通过检查以下分析器屏幕截图看到:

在这里插入图片描述
  你在这里看到的是我按下一个 UI 按钮,它将一个 161KB 的 FlexBuffer 文件加载到内存中(参见 TextAsset.get_bytes() (0.38ms)),其中包含一个包含 1000 个条目的向量,然后我们从这个向量中访问 50 个条目:

var bytes = Resources.Load<TextAsset>("flx_data").bytes;
var root = FlxValue.FromBytes(bytes);
var names = new List<string>(50);
for (var i = 0; i < 50; i++)
{
    names.Add(root[i]["name"].AsString);
}
Debug.Log(names);

  中间的 50 个冰柱显示了从字节数组中以字符串形式访问名称所需的时间。这是我放大冰柱的屏幕截图:
在这里插入图片描述
  这证明了单独访问一个值是一个非常轻量级的操作。 (这可能可以进一步优化)。

  让我们使用 Unity 自己的 JSONUtility 来比较一个类似的过程:
在这里插入图片描述
  包含相同数据的 JSON 文件占用 246KB,加载时间为 1.28ms。这是因为相同数据的 JSON 表示要大 80KB (35%),而且在 FlexBuffers 的情况下,我们只需要一个原始字节数组,在 JSON 的情况下,我们需要一个 UTF-16编码的 C# 字符串对象。

  然后我们还看到,大部分时间都花在了 JsonUtility.FromJsonInternal() 中,因为我们需要解析字符串并将其转换为 C# 对象。

var jsonText = Resources.Load<TextAsset>("json_data2").text;
var cities = JsonUtility.FromJson<CityList>(jsonText);
var names = new List<string>(50);
for (var i = 0; i < 50; i++)
{
    names.Add(cities.list[i].name);
}
Debug.Log(names);

  实际访问这些值并将它们添加到字符串列表中完全可以忽略不计:

在这里插入图片描述
  所以 JSON 的主要性能瓶颈是解析步骤。如果您想知道其他 JSON 解析器是否比 Unity JsonUtility 更好。你自己看。

  这是一个使用 Utf8Json 库的测试,它宣称自己为:

绝对是 C#(NET、.NET Core、Unity、Xamarin)的最快和零分配 JSON 序列化程序

在这里插入图片描述
JsonSerializer.Deserialize() 需要 47.87 毫秒才能运行。

并且测试代码并没有那么不同:

var jsonText = Resources.Load<TextAsset>("json_data2").text;
var cities = Utf8Json.JsonSerializer.Deserialize<CityList>(jsonText);
var names = new List<string>(50);
for (var i = 0; i < 50; i++)
{
    names.Add(cities.list[i].name);
}
Debug.Log(names);

如果您认为这很糟糕,请查看 Json.Net 的此屏幕截图:

在这里插入图片描述
  使用 Json.Net,我们设法在 447.67 毫秒内解析 JSON 文件。所以比 Utf8Json 慢 10 倍,比 JsonUtility 慢 100 倍。

  使用 Json.Net,我们也不会将 JSON 文本转换为 C# 类实例。我们将结构转换为通用 JArray 和 JObject 实例。从这些实例中访问值会产生一些开销,这比我们在 FlexBuffers 中看到的要低一点:

在这里插入图片描述

预付与现收现付

  正如我们从这个简短的分析会话中看到的那样,使用 FlexBuffers,我们为将数据加载到内存中以及我们需要访问的每个值付费。使用 JSON,由于必要的解析步骤,我们需要支付高额的预付费用。税收还基于文件的大小,而不是您需要从文件中提取的值的数量。

  这就是为什么 FlexBuffers 在配置文件方面完全有意义的原因。配置文件通常包含游戏所有阶段的数据。但是根据玩家的进度,您只能访问一小部分数据。本地化文件、复杂级别文件和其他数据集合也是如此。我知道有些游戏发布 SQLite 是为了在运行时读取“随机”数据。我相信在很多情况下 FlexBuffers 文件会是一个更好的解决方案。


FlexBuffers 是人类可读的吗?

  FlexBuffers 不是文本格式,因此您将无法使用文本编辑器打开 FlexBuffers 文件,但是,FlexBuffer Unity 有一个 FlexBuffer 浏览器窗口:

在这里插入图片描述

  在这里,您可以看到我能够打开一个 127.1MB 的复杂 FlexBuffers 文件并在其中导航,没有任何明显的延迟。根据我的经验,没有文本编辑器能以相当的速度打开一个 127MB 的文件。

我可以在 FlexBuffer 文件中搜索值吗?

  目前,FlexBuffer Browser 只有一个路径过滤功能:

在这里插入图片描述

  如您所见,我们可以定义路径和向量范围以减少树子的数量。目前无法进行完整搜索,但可能会在未来的版本中引入。

如何创建 FlexBuffer 文件?

  您可以以编程方式构建 FlexBuffer,但这可能不是您想要为大型配置执行的操作。这就是我介绍以下菜单点的原因:
在这里插入图片描述
  通过选择 JSON 作为 FlexBuffer… CSV 作为 FlexBuffer… 或 XML 作为 FlexBuffer… 您将看到一个文件选择器来选择源文件和另一个文件选择器来选择您想要存储 .bytes 文件的位置包含 FlexBuffer。

如果我想更改现有 FlexBuffers 文件中的某些内容怎么办?

遗憾的是,直接在 FlexBuffers 文件中更改数据并不是那么简单。但是,我们可以将 FlexBuffer 文件导出为 JSON:
在这里插入图片描述
在文本编辑器中打开 JSON 文件并进行编辑:

在这里插入图片描述
在这里插入图片描述
单击从 JSON 按钮导入:

在这里插入图片描述

我怎样才能自己尝试呢?

  FlexBuffers Unity 基于 FlexBuffers-CSharp。并且还有一个自给自足的 Github 存储库:https://github.com/mzaks/FlexBuffersUnity

  其结构为 Unity 包。因此,如果您想在游戏中使用 FlexBuffers Unity,只需在 manifest.json 文件中添加以下行:

“com.mzaks.flexbuffers”: “https://github.com/mzaks/FlexBuffersUnity.git”,

感谢您阅读。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Unity3D使用点云可以通过以下步骤实现: 1. 导入点云数据:将点云数据导入Unity。点云数据可以是以文本格式(如CSV文件)存储的坐标数据,也可以是以二进制格式(如PCD或PLY文件)存储的点云文件。你可以使用Unity的AssetImporter或自定义脚本来导入这些数据。 2. 创建点云对象:在Unity创建一个空的游戏对象,并将其命名为“PointCloud”或其他你喜欢的名称。然后,你可以通过编写自定义脚本来读取导入的点云数据,并将其转化为点云对象。 3. 显示点云:为了在场景显示点云,你可以使用Unity的粒子系统或自定义渲染器来渲染点云。对于较大的点云数据集,使用GPU实例化技术可以提高性能。你可以编写自定义着色器来对点云进行着色、光照和其他效果。 4. 交互与操作:你可以通过编写自定义脚本来实现与点云的交互与操作。例如,你可以允许用户通过鼠标或手势进行点选、框选或平移缩放操作。你还可以实现点云的拾取、编辑和删除等功能。 5. 点云处理与分析:Unity的点云可以用于各种应用,如虚拟现实、增强现实、建筑模拟和机器人导航等。你可以使用自定义脚本或现有的点云处理库(如PCL或Open3D)来执行点云处理和分析任务,如滤波、配准、分割和特征提取等。 需要注意的是,点云数据通常具有大量的点,因此在处理和渲染时需要考虑性能优化。合理使用Unity的批处理、GPU实例化和级别LOD等技术可以提高点云的渲染性能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值