数据存储

*此内容使用人工智能(Beta)翻译,可能包含错误。若要查看英文页面,请点按 此处

DataStoreService 允许您存储需要在会话之间保持的数据,例如玩家的库存中的物品或技能积分。数据存储在每个体验中都是一致的,因此任何体验中的地点都可以访问和更改相同的数据,包括位于不同服务器上的地点。

如果您想将颗粒度权限控制添加到数据存储并在 Studio 或 Roblox 服务器之外访问它们,您可以使用 打开云端 API 对数据存储

要通过创作者中心查看和监控体验中的所有数据存储,请使用 数据存储管理器

对于需要频繁更新或访问的临时数据,请使用 内存存储

启用工作室访1) 使用权 2)通行证 3)访问权限

默认情况下,Studio 中测试的体验无法访问数据存储,因此您必须先启用它们。在工作室访问数据存储可能对实时体验有害,因为工作室访问的数据存储与客户端应用程序相同。为了避免覆盖生产数据,请不要为实时体验启用此设置。相反,启用它为体验的单独测试版本。

要在 发布的体验中启用工作室访问:

  1. 打开游戏设置
  2. 导航到 安全
  3. 启用 启用工作室访问API服务 切换。
  4. 点击 保存

访问数据存储

要访问体验中的数据存储:

  1. DataStoreService 添加到服务器端 Script
  2. 使用 GetDataStore() 函数并指定要使用的数据存储名称。如果数据存储不存在,当你第一次保存体验数据时,Studio会创建一个。

local DataStoreService = game:GetService("DataStoreService")
local experienceStore = DataStoreService:GetDataStore("PlayerExperience")

创建数据

数据存储基本上是一个词典,类似于 Luau 表。独特的 索引每个值在数据存商店中,像用户的独特 Player.UserId 或名为体验促销的命名字符串。

用户数据键
3125060850
35167597920
50530609278000
促销数据键
ActiveSpecialEvent夏季派对2
ActivePromoCode奖励123
CanAccessPartyPlace真实

要创建新的条目,请使用键名和值调用 SetAsync()


local DataStoreService = game:GetService("DataStoreService")
local experienceStore = DataStoreService:GetDataStore("PlayerExperience")
local success, errorMessage = pcall(function()
experienceStore:SetAsync("User_1234", 50)
end)
if not success then
print(errorMessage)
end

更新数据

要更改数据存商店中的任何存储值,请使用入口的键名和定义如何更新入口的回调函数来调用 UpdateAsync() ,以更改入口。这个回调接受当前值并根据你定义的逻辑返回新值。如果回调返回 nil,则写操作被取消,值不会更新。


local DataStoreService = game:GetService("DataStoreService")
local nicknameStore = DataStoreService:GetDataStore("Nicknames")
local function makeNameUpper(currentName)
local nameUpper = string.upper(currentName)
return nameUpper
end
local success, updatedName = pcall(function()
return nicknameStore:UpdateAsync("User_1234", makeNameUpper)
end)
if success then
print("Uppercase Name:", updatedName)
end

设置与更新

使用集来快速更新特定的键。 SetAsync() 函数:

  • 如果两个服务器同时尝试设置相同的键,可能会导致数据不一致
  • 仅计算对写入限制

使用更新来处理多服务器尝试。UpdateAsync() 函数:

  • 从服务器上阅读最后更新它之前的当前键值,以便进行任何更改
  • 因为它在写之前阅读,所以速度较慢
  • 对阅读和写入限制进行计数

阅读数据

要阅读数据存储入口的值,请使用入口的键名 GetAsync() 调用。


local DataStoreService = game:GetService("DataStoreService")
local experienceStore = DataStoreService:GetDataStore("PlayerExperience")
local success, currentExperience = pcall(function()
return experienceStore:GetAsync("User_1234")
end)
if success then
print(currentExperience)
end

增量数据

要在数据存商店中增加整数,请调用 IncrementAsync() 并将入口的键名和要更改值的数量作为参数,以增加值。IncrementAsync() 是一个方便的函数,可以让你避免调用 UpdateAsync() 并手动增加整数。


local DataStoreService = game:GetService("DataStoreService")
local experienceStore = DataStoreService:GetDataStore("PlayerExperience")
local success, newExperience = pcall(function()
return experienceStore:IncrementAsync("Player_1234", 1)
end)
if success then
print(newExperience)
end

删除数据

要删除一个入口并返回与键相关的值,请调用 RemoveAsync()


local DataStoreService = game:GetService("DataStoreService")
local nicknameStore = DataStoreService:GetDataStore("Nicknames")
local success, removedValue = pcall(function()
return nicknameStore:RemoveAsync("User_1234")
end)
if success then
print(removedValue)
end

元数据

与钥匙相关的两种类型的元数据:

  • 服务定义 : 默认阅读只读元数据,例如最新更新时间和创建时间。每个对象都有服务定义的元数据。
  • 用户定义 : 标签和分类的自定义元数据。使用 DataStoreSetOptions 对象和 SetMetadata() 函数定义。

要管理元数据,扩展 SetAsync()UpdateAsync()GetAsync()IncrementAsync()RemoveAsync() 函数。

  • SetAsync() 接受可选的第三和第四个参数:

    • 一个表的 UserIds . 这可以帮助内容版权和知识产权跟踪和移除。

    • 一个 DataStoreSetOptions 对象,您可以使用 SetMetadata() 函数定义自定义元数据。


      local DataStoreService = game:GetService("DataStoreService")
      local experienceStore = DataStoreService:GetDataStore("PlayerExperience")
      local setOptions = Instance.new("DataStoreSetOptions")
      setOptions:SetMetadata({["ExperienceElement"] = "Fire"})
      local success, errorMessage = pcall(function()
      experienceStore:SetAsync("User_1234", 50, {1234}, setOptions)
      end)
      if not success then
      print(errorMessage)
      end
  • GetAsync() , IncrementAsync() , 和 RemoveAsync() 返回第二值在 DataStoreKeyInfo 对象。这第二个值包含服务定义的属性和函数以及用户定义的元数据来获取。


    local DataStoreService = game:GetService("DataStoreService")
    local experienceStore = DataStoreService:GetDataStore("PlayerExperience")
    local success, currentExperience, keyInfo = pcall(function()
    return experienceStore:GetAsync("User_1234")
    end)
    if success then
    print(currentExperience)
    print(keyInfo.Version)
    print(keyInfo.CreatedTime)
    print(keyInfo.UpdatedTime)
    print(keyInfo:GetUserIds())
    print(keyInfo:GetMetadata())
    end
  • UpdateAsync() 的回调函数在 DataStoreKeyInfo 对象中添加了描述当前键状态的额外参数。它返回修改后的值、与 UserIds 关联的键以及键的元数据。


    local DataStoreService = game:GetService("DataStoreService")
    local nicknameStore = DataStoreService:GetDataStore("Nicknames")
    local function makeNameUpper(currentName, keyInfo)
    local nameUpper = string.upper(currentName)
    local userIDs = keyInfo:GetUserIds()
    local metadata = keyInfo:GetMetadata()
    return nameUpper, userIDs, metadata
    end
    local success, updatedName, keyInfo = pcall(function()
    return nicknameStore:UpdateAsync("User_1234", makeNameUpper)
    end)
    if success then
    print(updatedName)
    print(keyInfo.Version)
    print(keyInfo.CreatedTime)
    print(keyInfo.UpdatedTime)
    print(keyInfo:GetUserIds())
    print(keyInfo:GetMetadata())
    end

有关定义元数据时的限制,请参阅元数据限制

排序数据存储

默认情况下,数据存储不会排序其内容。如果需要按照订阅的方式获取数据,例如在持久排行榜统计中,请调用 GetOrderedDataStore() 而不是 GetDataStore()


local DataStoreService = game:GetService("DataStoreService")
local characterAgeStore = DataStoreService:GetOrderedDataStore("CharacterAges")

排序数据存储支持与默认数据存储相同的基本功能,加上独特的 GetSortedAsync() 函数。这会检索 多个排序键 基于特定排序顺序、页面大小和最小/最大值,按排序顺序返回多个排序键。

以下示例将角色数据排序为包含三个条目的页面,每个条目排序为下降顺序,然后循环通过页面并输出每个角色的名称和年龄。


local DataStoreService = game:GetService("DataStoreService")
local characterAgeStore = DataStoreService:GetOrderedDataStore("CharacterAges")
-- 填充订阅数据存储商店
local characters = {
Mars = 19,
Janus = 20,
Diana = 18,
Venus = 25,
Neptune = 62
}
for char, age in characters do
local success, errorMessage = pcall(function()
characterAgeStore:SetAsync(char, age)
end)
if not success then
print(errorMessage)
end
end
-- 按下降顺序将数据排序为每页三个条目的页
local success, pages = pcall(function()
return characterAgeStore:GetSortedAsync(false, 3)
end)
if success then
while true do
-- 获取当前(第一)页
local entries = pages:GetCurrentPage()
-- 在页面上循环所有键值对的所有对象
for _, entry in entries do
print(entry.key .. " : " .. tostring(entry.value))
end
-- 检查最后一页已达到
if pages.IsFinished then
break
else
print("----------")
-- 前进到下一页
pages:AdvanceToNextPageAsync()
end
end
end