字符串在存储空间上一定比 Vector3 小吗?

我正在 Core 中开发一个系统来保存家具的变换,具体来说是位置和旋转,它们都是 Vector3。我在玩家存储中存储了这些信息,因此在保存所有玩家的家具时,我认为会达到玩家存储的最大限制。因此,我正在将所有的 Vector3 转换成字符串,使用我找到的 Roblox 脚本的修改版本:

local API = {}

API.VectorToString = function(vec)
    return math.floor(vec.x*100)/100 ..' '.. math.floor(vec.y*100)/100 ..' '.. math.floor(vec.z*100)/100
end

API.StringToVector = function(str)
    local tab = {}
    for a in string.gmatch(str,"(%-?%d*%.?%d+)") do
        table.insert(tab,a)
    end
    return Vector3.New(tab[1],tab[2],tab[3])
end

return API

因此,问题是,将所有这些 Vector 转换为字符串是否实际上节省了我的玩家数据存储空间?

点赞
用户9900937
用户9900937

最有效的存储方式很可能是使用 Vector3 格式而不是将其转换为字符串格式。在 Vector3 中,每个数字均为 16 位浮点数,因此每个数字需要 4 个字节来存储。如果将 Vector3 值转换为字符,则需要更多字节(每添加一个数字,需要一个字节,因为字符需要一个字节)。如果需要将 Vector3 存储为字符串,则建议使用下面的方法。

如果你想学习计算机如何使用仅四个字节存储如此广泛的数字范围,我非常推荐研究 IEEE 754 格式。

介绍 IEEE 754 格式的视频

可以使用 string.pack 和 string.unpack 函数将浮点数转换为字节数组,从而将其作为字符串发送。这种方法仅需要 12 个字节(12 个字符)的总和,精度可达 5 至 6 个小数点。虽然此方法只能节省少量字节,但允许您发送/保存更加精确的数字/位置。

local API = {}

API.VectorToString = function(vec)
    -- 将 x、y 和 z 位置转换为字节
    local byteXValue = string.pack('f', vec.x, 0)
    local byteYValue = string.pack('f', vec.y, 0)
    local byteZValue = string.pack('f', vec.z, 0)
    -- 将浮点字节合并为一个字符串
    local combinedBytes = byteXValue + byteYValue + byteZValue
    return combinedBytes
end

API.StringToVector = function(str)
    -- 将 x、y 和 z 位置从字节转换为浮点数值。
    -- 每隔 4 个字节表示一个新的浮点数值。
    local byteXValue = string.unpack('f', string.sub(1, 4))
    local byteYValue = string.unpack('f', string.sub(5, 8))
    local byteZValue = string.unpack('f', string.sub(9, 12))
    -- 将 x、y 和 z 值合并为一个 Vector3 对象
    return Vector3.New(byteXValue, byteYValue, byteZValue)
end

return API

String pack 函数文档

2021-03-02 23:30:43
用户4487767
用户4487767

这段代码可以更短,同时减少内存分配:

    local v3 = Vector3.New(111, 222, 333)
    local v3str = string.pack("fff", v3.x, v3.y, v3.z)
    local x, y, z = string.unpack("fff", v3str)
    local v31 = Vector3.New(x, y, z)
    assert(v3 == v31)

但是需要注意,大多数核心 API 函数不允许字符串中有零字节,如果你想将这些字符串存储在存储器中或将其用作事件参数 - 你需要对它们进行文本编码(Base64 是一个常见的选项)。

2021-06-15 08:12:14