计时器和事件

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

在回合的过程中,脚本需要跟踪时间并在不同的脚本之间发送信号。时间将通过使用时间脚本来管理,而事件,Roblox代码中的概念,将发送更改,例如结束一场匹配。

使用事件发送信号

现在玩家已经在竞技场中,可以使用事件来标志比赛开始,并且计时器的兑换码可以开始。稍后,一个事件也可以用来标志比匹配结束,并且将玩家转回大厅。

这些事件不是预构建的,因此定制的事件对象称为绑定式事件。 绑定式事件通常用于玩家发射的操作,并且与事件如TouchedChanged类似。

多个脚本可以听取相同的可绑定事件。这使您的代码有组织,并且可以更容易地在开始或结束比赛后添加额外的代码。

创建可绑定的事件

创建结束于匹配赛开始和结束的可绑定事件对象以启动。 由于可绑定事件不会与客户端交互,因此它们可以存储在服务器存储中。

  1. 在 ServerStorage 中,创建一个名为“Events”的新文件夹。在该文件夹中,创建两个名为“MatchStart”和“MatchEnd”的 BindableEvents

使用事件

当玩家进入竞技场时,中场休息会继续重新启动而不会开始计时器。主游戏循环需要告诉停止并等待在匹配结束事件发生之前移动到下一部分代验证码。

事件有两个内置函数:Connect()Wait()。 相反于以前使用 Connect() 作为游戏管理员脚本暂停游戏,请在匹配结束后调用 2>Wait2> 来暂停游戏管理员脚本直到匹配结束。 在这种情况下,等待函数会暂停代码直到游戏管理员收到信号 游戏结束。

  1. GameManager 中,创建变量为 Events 文件夹和 MatchEnd 事件。


    -- 模块脚本
    local moduleScripts = ServerStorage:WaitForChild("ModuleScripts")
    local matchManager = require(moduleScripts:WaitForChild("MatchManager"))
    local gameSettings = require(moduleScripts:WaitForChild("GameSettings"))
    -- 事件
    local events = ServerStorage:WaitForChild("Events")
    local matchEnd = events:WaitForChild("MatchEnd")
  2. 在进入下一个场景前,请等待脚本发射匹配结束事件。在 循环中,在 结束 中,类输入:matchEnd.Event:Wait()


    while true do
    repeat
    task.wait(gameSettings.intermissionDuration)
    print("Restarting intermission")
    until #Players:GetPlayers() >= gameSettings.minimumPlayers
    print("Intermission over")
    task.wait(gameSettings.transitionTime)
    matchManager.prepareGame()
    -- 等待游戏长度。
    matchEnd.Event:Wait()
    end
  3. 测试 游戏。确认一旦玩家进入竞技场,间歇循环 继续。脚本现在正在等待发射matchEnd信触发。

排查提示

在此时,代码不会如预期般工作,请尝试以下一种。

  • matchEnd.Event:Wait() 中检查使用双重空格或 colon 操作。
  • 确保MatchEnd是一个可绑定的事件,而不是另一个输入,例如RemoteEvent。

使用计时器

比赛结束的一个条件是计时器结束,这将通过脚本处理。

设置计时器

要将计时器添加到游戏中,请使用下面的步骤中的预制模块脚本。它包括启动和结束计时器的功能,还包括返回剩余时间。

  1. 在 ServerStorage > ModuleScripts 中,创建一个名为 Timer 的新模块脚本。

    将代码替换为下面的代码。


    local Timer = {}
    Timer.__index = Timer
    function Timer.new()
    local self = setmetatable({}, Timer)
    self._finishedEvent = Instance.new("BindableEvent")
    self.finished = self._finishedEvent.Event
    self._running = false
    self._startTime = nil
    self._duration = nil
    return self
    end
    function Timer:start(duration)
    if not self._running then
    task.spawn(function()
    self._running = true
    self._duration = duration
    self._startTime = tick()
    while self._running and tick() - self._startTime < duration do
    task.wait()
    end
    local completed = self._running
    self._running = false
    self._startTime = nil
    self._duration = nil
    self._finishedEvent:Fire(completed)
    end)
    else
    warn("Warning: timer could not start again as it is already running.")
    end
    end
    function Timer:getTimeLeft()
    if self._running then
    local now = tick()
    local timeLeft = self._startTime + self._duration - now
    if timeLeft < 0 then
    timeLeft = 0
    end
    return timeLeft
    else
    warn("Warning: could not get remaining time, timer is not running.")
    end
    end
    function Timer:isRunning()
    return self._running
    end
    function Timer:stop()
    self._running = false
    end
    return Timer
  2. 在 MatchManager 中,需要 GameSettings 和 Timer 模块。


    local MatchManager = {}
    -- 服务
    local ServerStorage = game:GetService("ServerStorage")
    -- 模块脚本
    local moduleScripts = ServerStorage:WaitForChild("ModuleScripts")
    local playerManager = require(moduleScripts:WaitForChild("PlayerManager"))
    local gameSettings = require(moduleScripts:WaitForChild("GameSettings"))
    local timer = require(moduleScripts:WaitForChild("Timer"))
  3. 在变量下,创建一个名为 myTimer 的新计时器对象,设置一个变量,其中 timer.new() 与 timer 相等。此对象将用于调用启动和停止计时器的函数。


    local gameSettings = require(moduleScripts:WaitForChild("GameSettings"))
    local timer = require(moduleScripts:WaitForChild("Timer"))
    -- 创建一个新的计时器对象来跟踪匹配时间。
    local myTimer = timer.new()

开始和停止

现在,当计时器创建后,使用包含在计时器中的函数 start()stop() 在比匹配中。以下是每个函数的描述和它所接受的参数。

  • start(time) - 启动计时器,并将时间以秒为参数。
  • finished:Connect(functionName) - 当计时器结束时,将传递函数作为参数运行。
  1. MatchManager 中,创建一个名为 timeUp() 的新函数,以便在计时器结束时运行。包括一个测试打印声明。


    local myTimer = timer.new()
    -- 本地函数
    local function timeUp()
    print("Time is up!")
    end
    -- 模块功能
    function MatchManager.prepareGame()
    playerManager.sendPlayersToMatch()
    end
    return MatchManager
  2. timeUp() 之下,添加一个名为 startTimer() 的函数,用打印语句显示计时器。你稍后会在游戏中显示计时器。


    -- 本地函数
    local function timeUp()
    print("Time is up!")
    end
    local function startTimer()
    print("Timer started")
    end
  3. 要启动和停止计时器,在 startTimer() :

    • 调用 myTimer.start() 。 在 gameSettings.matchDuration 中通过。
    • 调用 myTimer.finished:Connect()。在timeUp()后传送。

    -- 本地函数
    local function startTimer()
    print("Timer started")
    myTimer:start(gameSettings.matchDuration)
    myTimer.finished:Connect(timeUp)
    end

启动计时器

计时器可以使用匹配开始事件在比赛开始时触发。

  1. 在 MatchManager 中,在模块变量下,创建变量来存储事件文件夹、MatchStart 和 MatchEnd (将在未来的课程中使用)。


    -- 模块脚本
    local moduleScripts = ServerStorage:WaitForChild("ModuleScripts")
    local playerManager = require(moduleScripts:WaitForChild("PlayerManager"))
    local gameSettings = require(moduleScripts:WaitForChild("GameSettings"))
    local timer = require(moduleScripts:WaitForChild("Timer"))
    -- 事件
    local events = ServerStorage:WaitForChild("Events")
    local matchStart = events:WaitForChild("MatchStart")
    local matchEnd = events:WaitForChild("MatchEnd")
    --创建计时器
    local myTimer = timer.new()
  2. return MatchManager 之上,连接匹配开始事件到 startTimer()


    -- 模块功能
    function MatchManager.prepareGame()
    playerManager.sendPlayersToMatch()
    end
    matchStart.Event:Connect(startTimer)
    return MatchManager
  3. 要发射匹配开始事件,请在 prepareGame() 中,输入 matchStart:Fire()


    -- 模块功能
    function MatchManager.prepareGame()
    playerManager.sendPlayersToMatch()
    matchStart:Fire()
    end
  4. 测试游戏。在输出窗口中,确认您可以看到启动和关闭计时器的打印声明。

已完成的脚本

以下是完成脚本来重新检查您的工作。

MatchManager 脚本


local MatchManager = {}
-- 服务
local ServerStorage = game:GetService("ServerStorage")
-- 模块脚本
local moduleScripts = ServerStorage:WaitForChild("ModuleScripts")
local playerManager = require(moduleScripts:WaitForChild("PlayerManager"))
local gameSettings = require(moduleScripts:WaitForChild("GameSettings"))
local timer = require(moduleScripts:WaitForChild("Timer"))
-- 事件
local events = ServerStorage:WaitForChild("Events")
local matchStart = events:WaitForChild("MatchStart")
local matchEnd = events:WaitForChild("MatchEnd")
-- 创建一个新的计时器对象来跟踪匹配时间。
local myTimer = timer.new()
-- 本地函数
local function timeUp()
print("Time is up!")
end
local function startTimer()
print("Timer started")
myTimer:start(gameSettings.matchDuration)
myTimer.finished:Connect(timeUp)
end
-- 模块功能
function MatchManager.prepareGame()
playerManager.sendPlayersToMatch()
matchStart:Fire()
end
matchStart.Event:Connect(startTimer)
return MatchManager

游戏管理器脚本


-- 服务
local ServerStorage = game:GetService("ServerStorage")
local Players = game:GetService("Players")
-- 模块脚本
local moduleScripts = ServerStorage:WaitForChild("ModuleScripts")
local matchManager = require(moduleScripts:WaitForChild("MatchManager"))
local gameSettings = require(moduleScripts:WaitForChild("GameSettings"))
-- 事件
local events = ServerStorage:WaitForChild("Events")
local matchEnd = events:WaitForChild("MatchEnd")
while true do
repeat
task.wait(gameSettings.intermissionDuration)
print("Restarting intermission")
until #Players:GetPlayers() >= gameSettings.minimumPlayers
print("Intermission over")
task.wait(gameSettings.transitionTime)
matchManager.prepareGame()
-- 等待游戏长度。
matchEnd.Event:Wait()
end