【问题标题】:Stopwatch in Roblox Lua using a while loopRoblox Lua 中的秒表使用 while 循环
【发布时间】:2021-04-21 09:20:59
【问题描述】:
我正在制作一个 Roblox 游戏,我希望它有一个秒表。秒表可以工作,但由于某种原因,它的计数非常缓慢。
这是我在 StarterGui 中的 ScreenGui:
这是 LocalScript 中的代码:
local timer = script.Parent.Timer
local tms = 00
local ts = 00
local tm = 00
local tt
local tts
local y = 0
local whichtower = game.Players.LocalPlayer:FindFirstChild("WhichTower")
while true do
wait(0.01)
if whichtower.Value == "" then
tms = 00
ts = 00
tm = 00
tts = 0
else
tms = tms + 1
if tms == 100 then
ts = ts + 1
tms = 0
tts = tts + 1
if ts == 60 then
tm = tm + 1
ts = 0
end
end
tt = tostring(tm)..":"..tostring(ts)..":"..tostring(tms)
timer.Text = tt
game.Players.LocalPlayer:FindFirstChild("Time").Value = tt
end
end
【问题讨论】:
标签:
time
while-loop
lua
roblox
【解决方案1】:
任意的 wait() 和循环是计时问题的一个可能原因,尽管我看不到任何可能减慢它的具体内容。您确定 WHichTower 上的 :FindFirstChild 总是返回结果吗?在那里添加一个打印语句,这样你的调试窗口就会有一个恒定的值流,你可以确认它是否找到了合适的塔。
另外,如果有塔,您只会更新文本;对于将值设置为 0 的代码,没有 timer.Text 更新。
但如果你不认为这是问题所在:
我会尝试将您的代码放入 Heartbeat 函数中,定期调用并与刷新率相关联(我认为)。然后你不需要 while 循环,也不需要 wait() 命令。 Heartbeat 的运行速度仅与刷新率一样快,因此,没有必要尝试运行比刷新率更快的任何东西,因为屏幕不会更新。
local lPlayers = game:GetService("Players")
local lRunSvc = game:GetService("RunService")
local function onPlayerAdded(pPlayer) -- pPlayer (variable name is up to you) is the ref to the joined player.
print(pPlayer.Name .. " joined the game.")
lRunSvc.Heartbeat:Connect(function()
print("whichtower.value is:" .. whichtower.Value) -- View prints in the Output console
if whichtower.Value == "" then
tms = 00
ts = 00
tm = 00
tts = 0
else
tms = tms + 1
if tms == 100 then
ts = ts + 1
tms = 0
tts = tts + 1
if ts == 60 then
tm = tm + 1
ts = 0
end
end
tt = tostring(tm)..":"..tostring(ts)..":"..tostring(tms)
timer.Text = tt
game.Players.LocalPlayer:FindFirstChild("Time").Value = tt
end
end)
end
lPlayers.PlayerAdded:Connect(onPlayerAdded) -- This is called when a player joins
【解决方案2】:
正如 Vexen Crabtree 所指出的,wait() 实际暂停脚本的时间是基于系统时钟对已经过去了多少时间的最佳猜测。计算经过时间的更可靠方法是使用tick() 函数,而不是计算毫秒数。
tick() 将为您提供当前纪元时间,即自 1970 年 1 月 1 日以来经过的毫秒数。
因此,如果您知道一个开始时间,您可以从当前时间中减去它并获得经过的毫秒数。这种方法不依赖于循环时间,并且可以更准确地测量已经过去的实际时间。您使用wait() 选择的时间量只会反映更新值的速度。
local timer = script.Parent.Timer
local whichtower = game.Players.LocalPlayer:FindFirstChild("WhichTower")
local playerTime = game.Players.LocalPlayer:FindFirstChild("Time")
local startingTime = 0
local isTiming = false
-- attach a listener to know when to start the clock
whichTower.Changed:Connect(function(newValue)
-- reset the clock to zero when the value is empty
isTiming = newValue ~= ""
if not isTiming then
startingTime = 0
else
-- start the clock!
startingTime = tick()
end
end)
local refreshTime = 0.01
while true do
wait(refreshTime)
if isTiming then
-- calculate the time that has passed
local ms = tick() - startingTime
-- calculate how many minutes have passed
local tm = ms - (ms % (60 * 1000))
ms = ms - tm
tm = tm / 1000
-- calculate how many seconds have passed
local ts = ms - (ms % 1000)
ms = ms - ts
ts = ts / 1000
-- format the remainder
local tms = ms / 1000
if #tostring(tms) > 2 then
tms = string.sub(tostring(tms), 3)
else
tms = "0"
end
-- format the time into mm:ss.ss ex) 123:01.123
local tt = string.format("%.2d:%.2d.%s", tm, ts, tms)
timer.Text = tt
playerTime.Value = tt
end
end