在回合进行期间,脚本需要跟踪时间并在不同的脚本之间发送信号。时间将使用时间脚本进行管理,而事件,是 Roblox 编程中的一个概念,将显示更改,例如比匹配结束。
用事件发送信号
现在玩家已经在竞技场中,事件可以用来显示比赛开始的信号,计时器代码也可以开始。之后,事件也可以用来显示比匹配结束,以及是时候将玩家转回大厅了。
这些事件不是预制的,因此需要创建自定义事件对象称为 可绑定事件 。可绑定事件经常用于玩家发起的行动,与事件如 Touched 或 Changed 类似。
多个脚本可以监听相同的绑定事件。这使您的代码井然有序,以便以后需要时更容易添加比赛的开始或结束部分的额外代码。
创建可绑定的事件
首先创建可绑定的事件对象来匹配的开始和结束。因为可绑定的事件不会与客户端互动,所以它们可以存储在服务器存储中。
在 ServerStorage 中,创建一个名为 Events 的新文件夹。在该文件夹中,创建两个 可绑定事件 名为 MatchStart 和 MatchEnd 的文件。
使用事件
现在,当玩家进入竞技场时,中场休息继续重启而不是开始计时器。主游戏循环需要被告知停止,等待匹配结束事件发生,然后才能移至代验证码的下一部分。
事件有两个内置函数:Connect()和Wait()。而不是使用之前的 Connect() ,在 MatchEnd 结束时调用 Wait() 以暂停游戏管理脚本,直到 MatchEnd 发射。在这种情况下,等待函数暂停代码,直到游戏管理器收到信号称比赛结束了。
在 游戏管理器 中,为 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")让脚本等待结束事件发射,然后继续移动。在 循环 中,在 结束 时,键输入: matchEnd.Event:Wait()
while true dorepeattask.wait(gameSettings.intermissionDuration)print("Restarting intermission")until #Players:GetPlayers() >= gameSettings.minimumPlayersprint("Intermission over")task.wait(gameSettings.transitionTime)matchManager.prepareGame()-- 等待器放置为游戏的长度。matchEnd.Event:Wait()end测试 游戏。确认一旦玩家进入竞技场,中场循环 不会继续 。脚本现在正在等待 matchEnd 信号发触发。
排除问题的提示
在这一点上,代码没有按期望的方式工作,请尝试以下方法之一。
- 在 matchEnd.Event:Wait() 中重复检查 dot 或 colon 运营商的使用。
- 确保匹配结束是可绑定的事件,而不是另一种输入,例如远程事件。
使用计时器
导致比赛结束的条件之一是计时器到期,这将通过脚本处理。
设置计时器
要将计时器添加到游戏中,请在下面的步骤中使用预制模块脚本。它包括启动和结束计时器的功能,还包括返回剩余时间的功能。
在服务器存储 > 模块脚本中,创建一个名为计时器的新模块脚本。
将代码替换为以下代码。
local Timer = {}Timer.__index = Timerfunction Timer.new()local self = setmetatable({}, Timer)self._finishedEvent = Instance.new("BindableEvent")self.finished = self._finishedEvent.Eventself._running = falseself._startTime = nilself._duration = nilreturn selfendfunction Timer:start(duration)if not self._running thentask.spawn(function()self._running = trueself._duration = durationself._startTime = tick()while self._running and tick() - self._startTime < duration dotask.wait()endlocal completed = self._runningself._running = falseself._startTime = nilself._duration = nilself._finishedEvent:Fire(completed)end)elsewarn("Warning: timer could not start again as it is already running.")endendfunction Timer:getTimeLeft()if self._running thenlocal now = tick()local timeLeft = self._startTime + self._duration - nowif timeLeft < 0 thentimeLeft = 0endreturn timeLeftelsewarn("Warning: could not get remaining time, timer is not running.")endendfunction Timer:isRunning()return self._runningendfunction Timer:stop()self._running = falseendreturn 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"))在变量下面,通过设置一个名为 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) - 当计时器结束时,运行传递作为参数的函数。
在 匹配管理器 中,创建一个名为 timeUp() 的新函数来运行计时器结束时。包括测试打印声明。
local myTimer = timer.new()-- 本地函数local function timeUp()print("Time is up!")end-- 模块功能function MatchManager.prepareGame()playerManager.sendPlayersToMatch()endreturn MatchManager在 timeUp() 下,添加一个名为 startTimer() 的函数,带有打印声明。你将在游戏中稍后显示计时器。
-- 本地函数local function timeUp()print("Time is up!")endlocal function startTimer()print("Timer started")end要启动和停止计时器,在 startTimer() :
- 调用 myTimer.start() . 传递 gameSettings.matchDuration .
- 调用 myTimer.finished:Connect() . 传递 timeUp() .
-- 本地函数local function startTimer()print("Timer started")myTimer:start(gameSettings.matchDuration)myTimer.finished:Connect(timeUp)end
启动计时器
计时器可以使用匹配开始事件在比赛开始时触发。
在匹配管理器中,在模块变量下,创建变量来存储事件文件夹、匹配开始和匹配结束(这在未来的课程中使用)。
-- 模块脚本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()在 return MatchManager 上,连接匹配开始事件到 startTimer() 。
-- 模块功能function MatchManager.prepareGame()playerManager.sendPlayersToMatch()endmatchStart.Event:Connect(startTimer)return MatchManager要发射匹配开始事件,在 prepareGame() 中,输入 matchStart:Fire() .
-- 模块功能function MatchManager.prepareGame()playerManager.sendPlayersToMatch()matchStart:Fire()end测试游戏。在输出窗口中,确认您可以看到计时器启动和停止功能的打印声明。
已完成的脚本
以下是完成的脚本来检查您的工作。
匹配管理器脚本
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 dorepeattask.wait(gameSettings.intermissionDuration)print("Restarting intermission")until #Players:GetPlayers() >= gameSettings.minimumPlayersprint("Intermission over")task.wait(gameSettings.transitionTime)matchManager.prepareGame()-- 等待器放置为游戏的长度。matchEnd.Event:Wait()end