数据存储

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

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

如果您想为数据存储添加细粒度的权限控制并在 Studio 或 Roblox 服务器之外访问它们,可以使用 数据存储的开放云 API

要通过 Creator Hub 查看和监控游戏中的所有数据存储,请使用 数据存储管理器

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

启用 Studio 访问

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

要在 已发布 的游戏中启用 Studio 访问:

  1. 打开 Studio 的 文件体验设置 窗口。
  2. 导航到 安全性
  3. 启用 启用 Studio 访问 API 服务 切换。
  4. 点击 保存

访问数据存储

要在游戏中访问数据存储:

  1. DataStoreService 添加到服务器端的 Script
  2. 使用 GetDataStore() 函数并指定您要使用的数据存储的名称。如果数据存储不存在,Studio 会在您第一次保存游戏数据时创建一个。
local DataStoreService = game:GetService("DataStoreService")
local gameStore = DataStoreService:GetDataStore("PlayerGame")

创建数据

数据存储本质上是一个字典,类似于 Luau 表。每个值在数据存储中都有一个唯一的 索引,例如用户的唯一 Player.UserId 或游戏促销的命名字符串。

用户数据键
3125060850
35167597920
50530609278000
促销数据键
ActiveSpecialEventSummerParty2
ActivePromoCodeBONUS123
CanAccessPartyPlacetrue

要创建一个新条目,请调用 SetAsync(),并提供键名和一个值。

local DataStoreService = game:GetService("DataStoreService")
local gameStore = DataStoreService:GetDataStore("PlayerGame")
local success, errorMessage = pcall(function()
gameStore: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("大写名称:", updatedName)
end

设置与更新

使用设置快速更新特定键。SetAsync() 函数:

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

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

  • 在进行任何更改之前,从最后更新它的服务器读取当前键值
  • 由于在写入之前读取,因此速度较慢
  • 计入读取和写入限制

读取数据

要读取数据存储条目的值,请调用 GetAsync(),并提供条目的键名。

local DataStoreService = game:GetService("DataStoreService")
local gameStore = DataStoreService:GetDataStore("PlayerGame")
local success, currentGame = pcall(function()
return gameStore:GetAsync("User_1234")
end)
if success then
print(currentGame)
end

增量数据

要在数据存储中递增一个整数,请调用 IncrementAsync(),并提供条目的键名和一个数字,表示要更改的值。IncrementAsync() 是一个便利函数,让您避免调用 UpdateAsync() 并手动递增整数。

local DataStoreService = game:GetService("DataStoreService")
local gameStore = DataStoreService:GetDataStore("PlayerGame")
local success, newGame = pcall(function()
return gameStore:IncrementAsync("Player_1234", 1)
end)
if success then
print(newGame)
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 gameStore = DataStoreService:GetDataStore("PlayerGame")
      local setOptions = Instance.new("DataStoreSetOptions")
      setOptions:SetMetadata({["GameElement"] = "Fire"})
      local success, errorMessage = pcall(function()
      gameStore:SetAsync("User_1234", 50, {1234}, setOptions)
      end)
      if not success then
      print(errorMessage)
      end
  • GetAsync()IncrementAsync()RemoveAsync() 返回 DataStoreKeyInfo 对象中的第二个值。这个第二个值包含服务定义的属性和获取用户定义元数据的函数。

    local DataStoreService = game:GetService("DataStoreService")
    local gameStore = DataStoreService:GetDataStore("PlayerGame")
    local success, currentGame, keyInfo = pcall(function()
    return gameStore:GetAsync("User_1234")
    end)
    if success then
    print(currentGame)
    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

读取多个条目

要在单个请求中读取多个 有序数据存储 条目,请调用 BatchGetAsync(),并提供一个键的数组。这是逐个读取条目的 GetAsync() 的批处理对应。

BatchGetAsync() 返回一个字典,将每个请求的键映射到一个具有 value 字段的表。不存在的键将从字典中省略,因此在读取其值之前,请确认键是否存在。

您请求的每个键都计为一个读取请求,因此对 N 个键的单个调用计为对有序数据存储 读取限制N 个请求。

以下示例在单个请求中读取三个玩家分数,然后循环遍历键并输出每个存在的分数。

local DataStoreService = game:GetService("DataStoreService")
local playerScores = DataStoreService:GetOrderedDataStore("PlayerScores")
local keys = {"Player_123", "Player_456", "Player_789"}
local success, results = pcall(function()
return playerScores:BatchGetAsync(keys)
end)
if success then
for _, key in keys do
local entry = results[key]
if entry then
print(key .. " : " .. tostring(entry.value))
else
print(key .. " 没有保存的条目")
end
end
end
©2026 Roblox Corporation、Roblox、Roblox 标志及 Powering Imagination 是我们在美国及其他国家或地区的注册与未注册商标。