Roblox Lua 中的秒表使用 while 循环

Stopwatch in Roblox Lua using a while loop

我正在制作一个 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

任意 wait() 和循环可能是导致计时问题的原因,尽管我看不到任何可能减慢速度的具体原因。您确定 WHichTower 上的 :FindFirstChild 总是返回结果吗?在那里添加一个打印语句,这样你的调试 window 就会有一个恒定的值流,你可以确认它是否找到了合适的塔。

另外,只有在有塔的情况下才更新文本;对于将值设置为 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

正如 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

我使用另一组代码解决了这个问题。 Roblox 将等待参数限制为至少 0.03 秒,这就是我之前的代码无法正常工作的原因。