如何在Roblox游戏中创建可累加的总游戏时长追踪变量?
完整实现方案:Roblox游戏停留时长追踪+累加+徽章自动发放
1. 数据存储配置(跨会话保存时长)
所有时长数据必须存在服务器端的DataStore里,客户端无法篡改。在ServerScriptService新建脚本,核心逻辑如下:
- 用
DataStoreService获取专属数据存储,命名建议带游戏ID避免冲突 - 玩家加入时加载历史时长,玩家离开/服务器关闭时保存最新时长
local DataStoreService = game:GetService("DataStoreService") local BadgeService = game:GetService("BadgeService") local Players = game:GetService("Players") -- 初始化数据存储,替换为你的游戏专属标识 local playTimeStore = DataStoreService:GetDataStore("PlayerPlayTime_YourGameID") -- 玩家数据结构:{TotalPlayTime = 0} local function loadPlayerData(player) local success, data = pcall(function() return playTimeStore:GetAsync("Player_" .. player.UserId) end) if success then return data or {TotalPlayTime = 0} else warn("加载玩家" .. player.Name .. "数据失败:" .. data) return {TotalPlayTime = 0} end end local function savePlayerData(player, data) local success, err = pcall(function() playTimeStore:SetAsync("Player_" .. player.UserId, data) end) if not success then warn("保存玩家" .. player.Name .. "数据失败:" .. err) end end
2. 实时时长追踪与累加逻辑
玩家进入游戏后,记录当前会话的开始时间,每1秒更新总时长,避免用repeat wait()的低效写法,改用RunService实现定时更新:
local RunService = game:GetService("RunService") Players.PlayerAdded:Connect(function(player) local playerData = loadPlayerData(player) local sessionStartTime = tick() local isTracking = true -- 每1秒更新一次时长 local updateConnection = RunService.Heartbeat:Connect(function() if not isTracking then return end local sessionElapsed = tick() - sessionStartTime -- 累加至总时长(保留整数秒即可) playerData.TotalPlayTime = math.floor(playerData.TotalPlayTime + sessionElapsed) sessionStartTime = tick() -- 重置会话开始时间 -- 可选:把时长同步到客户端显示 local leaderstats = player:FindFirstChild("leaderstats") or Instance.new("Folder") leaderstats.Name = "leaderstats" leaderstats.Parent = player local playTimeValue = leaderstats:FindFirstChild("PlayTime") or Instance.new("IntValue") playTimeValue.Name = "PlayTime" playTimeValue.Value = playerData.TotalPlayTime playTimeValue.Parent = leaderstats -- 检查徽章发放条件 checkAndAwardBadges(player, playerData.TotalPlayTime) end) -- 玩家离开时停止追踪并保存数据 player.AncestryChanged:Connect(function(_, parent) if parent == nil then isTracking = false updateConnection:Disconnect() savePlayerData(player, playerData) end end) end)
3. 徽章自动发放实现
先在Roblox开发者后台创建好徽章并获取徽章ID,然后编写发放逻辑——必须在服务器端执行,且先检查玩家是否已拥有徽章:
-- 定义徽章ID和对应时长阈值,替换为你的实际徽章ID local badgeConfigs = { {BadgeId = 123456789, RequiredTime = 3600}, -- 1小时徽章 {BadgeId = 987654321, RequiredTime = 10800} -- 3小时徽章 } local function checkAndAwardBadges(player, totalTime) for _, config in ipairs(badgeConfigs) do -- 先检查玩家是否已拥有该徽章 local hasBadgeResult, err = pcall(function() return BadgeService:UserHasBadgeAsync(player.UserId, config.BadgeId) end) if hasBadgeResult then -- 时长达标且未拥有徽章,发放 if totalTime >= config.RequiredTime and not hasBadgeResult then local success, awardErr = pcall(function() BadgeService:AwardBadge(player.UserId, config.BadgeId) end) if not success then warn("给玩家" .. player.Name .. "发放徽章" .. config.BadgeId .. "失败:" .. awardErr) end end else warn("检查玩家" .. player.Name .. "徽章拥有状态失败:" .. err) end end end
关键注意事项
- 防作弊:所有时长计算和徽章发放必须在服务器端执行,绝不信任客户端传来的时长数据
- DataStore容错:必须用
pcall包裹DataStore操作,避免请求失败导致脚本崩溃 - 测试建议:在Studio中开启
DataStore模拟器(设置>游戏设置>安全>允许DataStore),避免测试时消耗真实DataStore配额 - 性能优化:也可以改为玩家离开时一次性计算会话总时长(用
tick()记录进入和离开的时间差),减少DataStore请求次数
内容的提问来源于stack exchange,提问作者wywl
相关产品推荐
相关产品推荐

