計時器和事件

*此內容是使用 AI(Beta 測試版)翻譯,可能含有錯誤。若要以英文檢視此頁面,請按一下這裡

在回合期間,腳本需要記錄時間並在不同腳本之間傳送信號。時間將使用時間指令碼管理,而事件,是 Roblox 編寫中的一個概念,會偵測到比相符結束等變更。

透過事件傳送信號

現在玩家已經在競技場中,事件可以用來警告比賽開始和計時器代碼開始。之後,事件也可以用來警告比相符結束,以及是時候將玩家轉回大廳了。

這些事件未預製,因此需要創建自訂事件對象,稱為 可綁定事件 ,以便執行。可綁定事件通常用於玩家發起的行動,與事件如 TouchedChanged 類似。

多個腳本可以聆聽相同的可綁定事件。這樣可以使您的代碼井然有序,並且使以後為比賽開始或結束添加額外代碼變得更容易。

創建可綁定的事件

從創建可綁定的比相符開始和結束事件對象開始。因為可綁定事件不會與客戶端互動,因此可以儲存在伺服器儲存中。

  1. 在伺服器儲存中,創建一個名為「事件」的新文件夾。在該文件夾中,創建兩個 可綁定事件 ,名為「匹配開始」和「匹配結束」。

使用事件

現在,當玩家進入競技場時,中場休息會繼續重新啟動,而不是開始計時器。主遊戲循環需要被告知停止,直到匹配結束事件發生,然後才能移至代碼的下一部分。

事件有兩個內置功能:Connect()Wait()。取代以前使用 Connect() 的方式,在 MatchEnd 上呼叫 Wait() 來暫停游戲管理員腳本直到 MatchEnd 被發射。在這種情況下,等待功能會暫停代碼,直到遊戲管理員收到信號表示比賽結束。

  1. 遊戲管理器 中,創建變量為 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() 中雙重檢查點或斑點運作器的使用。
  • 請確保 MatchEnd 是可綁定的事件,而不是其他輸入,例如遠端事件。

使用定時器

造成比賽結束的一個條件是定時器到期,這將通過腳指令碼處理。

設定計時器

要將定時器添加到遊戲中,請在下列步驟中使用預製模組腳本。它包括啟動和結束計時器的功能,以及返回剩餘時間的數量。

  1. 在伺服器儲存 > 模組腳本中,創建一個名為計時器的新模組腳本。

    將代碼替換為以下代碼。


    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() 來創建新的計時器對象。這個對象將用於呼叫開始和停止計時器的函數。


    local gameSettings = require(moduleScripts:WaitForChild("GameSettings"))
    local timer = require(moduleScripts:WaitForChild("Timer"))
    -- 創建一個新的計時器對象,用於跟蹤比賽時間。
    local myTimer = timer.new()

開始和停止

現在創建了定時器,在比相符期間使用包含的功能 start()stop() 。以下是每個功能的說明和它接受的參數。

  • start(time) - 啟動計時器,使用秒為參數的時間。
  • finished:Connect(functionName) - 當定時器結束時,運行傳遞為參數的函數。
  1. 配對管理器 中,創建一個新函數名為 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 中,在模組變量下,創建變量來儲存事件文件夾、比賽開始和比賽結束(將在未來的課程中使用)。


    -- 模組腳本
    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. 測試遊戲。在輸出窗口中,確認您可以看到計時器啟動和停止功能的印刷聲明。

已完成的腳本

以下是完成的腳本來檢查您的工作。

匹配管理員腳指令碼


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