ในระหว่างรอบหนึ่งจะต้องติดตามเวลาและส่งสัญญาณระหว่างสคริปต์ที่แตกต่างกันเวลาจะได้รับการจัดการโดยใช้สคริปต์เวลาในขณะที่กิจกรรมซึ่งเป็นแนวคิดในการเขียนโค้ดของ Roblox ตรงกัน
ส่งสัญญาณด้วยเหตุการณ์
เมื่อผู้เล่นอยู่ในสนามแข่งแล้ว กิจกรรมสามารถใช้เพื่อส่งสัญญาณการเริ่มต้นของการแข่งขันและรหัสสำหรับตัวจับเวลาสามารถเริ่มต้นได้ในภายหลังอีเวนต์ยังสามารถใช้เพื่อส่งสัญญาณสิ้นสุดการแข่งขันและเป็นเวลาที่จะเปลี่ยนผู้เล่นกลับไปที่ล็อบบี้
อีเวนต์เหล่านี้ไม่ได้ถูกสร้างไว้ล่วงหน้าดังนั้นจึงจำเป็นต้องสร้างวัตถุอีเวนต์ที่กําหนดเองที่เรียกว่า อีเวนต์ที่ผูกได้ อีเวนต์ที่สามารถผูกได้มักใช้สำหรับการดำเนินการที่เกิดจากผู้เล่นและมีลักษณะคล้ายกับอีเวนต์เช่น Touched หรือ Changed
สคริปต์หลายตัวสามารถฟังเหตุการณ์ที่ผูกไว้เดียวกันได้สิ่งนี้ทำให้โค้ดของคุณเป็นระเบียบและทำให้เพิ่มโค้ดเพิ่มเติมสำหรับการเริ่มหรือสิ้นสุดการแข่งขันในภายหลังได้ง่ายขึ้นหากจำเป็น
สร้างอีเวนต์ที่ผูกได้
เริ่มต้นด้วยการสร้างวัตถุกิจกรรมที่ผูกได้สำหรับจุดเริ่มต้นและจุดสิ้นสุดของการแข่งขันเนื่องจากอีเวนต์ที่สามารถผูกได้ไม่โต้ตอบกับไคลเอนต์ จึงสามารถเก็บไว้ในพื้นที่จัดเก็บเซิร์ฟเวอร์ได้
ใน ServerStorage สร้างโฟลเดอร์ใหม่ชื่อ Events ในโฟลเดอร์นั้น สร้างสอง BindableEvents ชื่อ MatchStart และ MatchEnd
ใช้อีเวนต์
ตอนนี้เมื่อผู้เล่นเข้าสู่สนามแข่ง ช่วงระยะหยุดชะงักจะเริ่มต้นใหม่แทนที่จะเริ่มต้นตัวจับเวลาลูปเกมหลักต้องได้รับการบอกให้หยุดและรอจนกว่าอีเวนต์ MatchEnd จะเกิดขึ้นก่อนที่จะย้ายไปยังส่วนต่อไปของโค้ด
กิจกรรมมีสองฟังก์ชันที่ติดตั้งไว้แล้ว: Connect() และ Wait() .แทนที่จะใช้ Connect() เช่นเดิมก่อนหน้านี้ให้โทร Wait() ที่ MatchEnd เพื่อหยุดสคริปต์ผู้จัดการเกมจนกว่า 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() อีกครั้ง
- ตรวจสอบให้แน่ใจว่า MatchEnd เป็น BindableEvent พิมพ์เช่น RemoteEvent
ใช้ตัวจับเวลา
หนึ่งในเงื่อนไขที่จะทำให้การแข่งขันสิ้นสุดคือตัวจับเวลาหมดลงซึ่งจะได้รับการจัดการผ่านสคริปต์
ตั้งเวลาได้
เพื่อเพิ่มตัวจับเวลาในเกม ให้ใช้สคริปต์โมดูลล่วงหน้าในขั้นตอนด้านล่างรวมฟังก์ชันเพื่อเริ่มและสิ้นสุดตัวจับเวลาเช่นเดียวกับการคืนจำนวนเวลาที่เหลือ
ใน ServerStorage > ModuleScripts สร้างสคริปต์โมดูลใหม่ชื่อว่า Timer
แทนที่รหัสด้วยรหัสด้านล่าง
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ใน 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"))ด้านล่างตัวแปรสร้างวัตถุนับเวลาใหม่โดยการตั้งค่าตัวแปรชื่อ 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) - เมื่อนับเวลาจบลงแล้ว จะรันฟังก์ชันที่ส่งเป็นพารามิเตอร์
ใน MatchManager สร้างฟังก์ชันใหม่ชื่อ 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
เริ่มตัวจับเวลา
ตัวจับเวลาสามารถกระตุ้นได้ที่จุดเริ่มต้นของการแข่งขันโดยใช้อีเวนต์การเริ่มการแข่งขัน
ใน 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()เหนือ 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ทดสอบเกม ในหน้าต่างผลลัพธ์ ยืนยันว่าคุณสามารถเห็นคําสั่งพิมพ์สําหรับฟังก์ชันเริ่มต้นและหยุดของตัวจับเวลาได้
สคริปต์สําเร็จ
ด้านล่างเป็นสคริปต์ที่เสร็จสมบูรณ์เพื่อตรวจสอบงานของคุณอีกครั้ง
สคริปต์ 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
สคริปต์ GameManager
-- บริการ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