如何解决DataStore报错‘Argument 1 missing or nil’问题?
问题分析与修复方案
核心错误原因
出现“Argument 1 missing or nil”的直接原因是game.Players:GetNameFromUserIdAsync()的参数为nil。你存储数据时用的键是player.UserId.."-Wins"(如123456-Wins),调用tonumber(data.key)时,带后缀的字符串无法转成有效数字,返回nil,导致GetNameFromUserIdAsync参数缺失报错。
具体修复步骤
1. 修正数据存储与读取的键格式
存储时直接用player.UserId作为键,不要加后缀,这样读取时data.key就是纯数字ID,无需转换:
-- 原存储代码 WinsDataStore:SetAsync(player.UserId.."-Wins",player.leaderstats.Wins.Value) -- 改为 WinsDataStore:SetAsync(player.UserId, player.leaderstats.Wins.Value)
2. 修复用户名获取逻辑
去掉多余的tonumber转换,直接用data.key作为参数(OrderedDataStore会自动保留键的类型,这里是数字ID):
-- 原代码 local Username = game.Players:GetNameFromUserIdAsync(tonumber(data.key)) -- 改为 local Username = game.Players:GetNameFromUserIdAsync(data.key)
3. 修正排行榜Frame的属性赋值
你直接给newlibframe.Wins和newlibframe.Rank赋值数值/字符串是错误的,这些应该是TextLabel控件,需要设置其Text属性:
-- 原代码 newlibframe.Wins = Wins newlibframe.Rank = "#"..rank -- 改为 newlibframe.Wins.Text = tostring(Wins) newlibframe.Rank.Text = "#"..rank
4. 添加循环延迟并包裹DataStore操作
原脚本的while true没有延迟,会导致服务器资源耗尽,同时所有DataStore操作都应该用pcall包裹,避免单次请求失败导致脚本崩溃:
while true do -- 存储玩家数据时用pcall包裹 for _, player in pairs(game.Players:GetPlayers()) do local success, err = pcall(function() -- 先检查leaderstats和Wins是否存在,避免nil错误 if player:FindFirstChild("leaderstats") and player.leaderstats:FindFirstChild("Wins") then WinsDataStore:SetAsync(player.UserId, player.leaderstats.Wins.Value) end end) if not success then print("存储玩家"..player.Name.."数据失败: "..err) end end for _, frame in pairs(game.Workspace["Total Wins"].Leaderboard.Holder:GetChildren()) do frame:Destroy() end Update() print("Updated") wait(30) -- 添加30秒延迟,可根据需求调整 end
5. 优化Update函数中的重复检查
在Update函数中,每次循环前已经清空了所有Frame,所以isonleaderboard的判断完全多余,可以直接删除这部分逻辑,同时用ipairs保证排行榜顺序正确:
local function Update() local success, errormessage = pcall(function() local Data = WinsDataStore:GetSortedAsync(false, 5) local WinsPage = Data:GetCurrentPage() for rank, data in ipairs(WinsPage) do local Username = game.Players:GetNameFromUserIdAsync(data.key) local Wins = data.value local newlibframe = game.ReplicatedStorage:WaitForChild("LeaderboardFrame"):Clone() newlibframe.Player.Text = Username newlibframe.Wins.Text = tostring(Wins) newlibframe.Rank.Text = "#"..rank newlibframe.Position = UDim2.new(0, 0, 0.08 * (rank - 1), 0) -- 直接根据排名计算位置,更准确 newlibframe.Parent = game.Workspace["Total Wins"].Leaderboard.Holder end end) if not success then print("更新排行榜失败: "..errormessage) end end
完整修复后的脚本
local DataStoreService = game:GetService("DataStoreService") local WinsDataStore = DataStoreService:GetOrderedDataStore("WinsRathersCamel") local function Update() local success, errormessage = pcall(function() local Data = WinsDataStore:GetSortedAsync(false, 5) local WinsPage = Data:GetCurrentPage() for rank, data in ipairs(WinsPage) do local Username = game.Players:GetNameFromUserIdAsync(data.key) local Wins = data.value local newlibframe = game.ReplicatedStorage:WaitForChild("LeaderboardFrame"):Clone() newlibframe.Player.Text = Username newlibframe.Wins.Text = tostring(Wins) newlibframe.Rank.Text = "#"..rank newlibframe.Position = UDim2.new(0, 0, 0.08 * (rank - 1), 0) newlibframe.Parent = game.Workspace["Total Wins"].Leaderboard.Holder end end) if not success then print("更新排行榜失败: "..errormessage) end end while true do for _, player in pairs(game.Players:GetPlayers()) do local success, err = pcall(function() if player:FindFirstChild("leaderstats") and player.leaderstats:FindFirstChild("Wins") then WinsDataStore:SetAsync(player.UserId, player.leaderstats.Wins.Value) end end) if not success then print("存储玩家"..player.Name.."数据失败: "..err) end end for _, frame in pairs(game.Workspace["Total Wins"].Leaderboard.Holder:GetChildren()) do frame:Destroy() end Update() print("Updated") wait(30) end
内容的提问来源于stack exchange,提问作者Sh3l0nC00p3r
相关产品推荐
相关产品推荐

