ตัวจับเวลาและอีเวนต์

*เนื้อหานี้แปลโดยใช้ AI (เวอร์ชัน Beta) และอาจมีข้อผิดพลาด หากต้องการดูหน้านี้เป็นภาษาอังกฤษ ให้คลิกที่นี่

ในระหว่างรอบหนึ่งจะต้องติดตามเวลาและส่งสัญญาณระหว่างสคริปต์ที่แตกต่างกันเวลาจะได้รับการจัดการโดยใช้สคริปต์เวลาในขณะที่กิจกรรมซึ่งเป็นแนวคิดในการเขียนโค้ดของ Roblox ตรงกัน

ส่งสัญญาณด้วยเหตุการณ์

เมื่อผู้เล่นอยู่ในสนามแข่งแล้ว กิจกรรมสามารถใช้เพื่อส่งสัญญาณการเริ่มต้นของการแข่งขันและรหัสสำหรับตัวจับเวลาสามารถเริ่มต้นได้ในภายหลังอีเวนต์ยังสามารถใช้เพื่อส่งสัญญาณสิ้นสุดการแข่งขันและเป็นเวลาที่จะเปลี่ยนผู้เล่นกลับไปที่ล็อบบี้

อีเวนต์เหล่านี้ไม่ได้ถูกสร้างไว้ล่วงหน้าดังนั้นจึงจำเป็นต้องสร้างวัตถุอีเวนต์ที่กําหนดเองที่เรียกว่า อีเวนต์ที่ผูกได้ อีเวนต์ที่สามารถผูกได้มักใช้สำหรับการดำเนินการที่เกิดจากผู้เล่นและมีลักษณะคล้ายกับอีเวนต์เช่น Touched หรือ Changed

สคริปต์หลายตัวสามารถฟังเหตุการณ์ที่ผูกไว้เดียวกันได้สิ่งนี้ทำให้โค้ดของคุณเป็นระเบียบและทำให้เพิ่มโค้ดเพิ่มเติมสำหรับการเริ่มหรือสิ้นสุดการแข่งขันในภายหลังได้ง่ายขึ้นหากจำเป็น

สร้างอีเวนต์ที่ผูกได้

เริ่มต้นด้วยการสร้างวัตถุกิจกรรมที่ผูกได้สำหรับจุดเริ่มต้นและจุดสิ้นสุดของการแข่งขันเนื่องจากอีเวนต์ที่สามารถผูกได้ไม่โต้ตอบกับไคลเอนต์ จึงสามารถเก็บไว้ในพื้นที่จัดเก็บเซิร์ฟเวอร์ได้

  1. ใน ServerStorage สร้างโฟลเดอร์ใหม่ชื่อ Events ในโฟลเดอร์นั้น สร้างสอง BindableEvents ชื่อ MatchStart และ MatchEnd

ใช้อีเวนต์

ตอนนี้เมื่อผู้เล่นเข้าสู่สนามแข่ง ช่วงระยะหยุดชะงักจะเริ่มต้นใหม่แทนที่จะเริ่มต้นตัวจับเวลาลูปเกมหลักต้องได้รับการบอกให้หยุดและรอจนกว่าอีเวนต์ MatchEnd จะเกิดขึ้นก่อนที่จะย้ายไปยังส่วนต่อไปของโค้ด

กิจกรรมมีสองฟังก์ชันที่ติดตั้งไว้แล้ว: Connect() และ Wait() .แทนที่จะใช้ Connect() เช่นเดิมก่อนหน้านี้ให้โทร Wait() ที่ MatchEnd เพื่อหยุดสคริปต์ผู้จัดการเกมจนกว่า 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 เป็น BindableEvent พิมพ์เช่น 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 ต้องการโมดูลการตั้งค่าเกมและนาฬิกา


    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. ใน 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

สคริปต์ 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 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