เพิ่มรอบ

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

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

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

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

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

เริ่มลูป

ServerScriptServiceGameplayRounds จะจัดการตรรกะส่วนใหญ่สำหรับการนำรอบมาใช้ และเริ่มต้นโดยการเรียกใช้ฟังก์ชัน startRoundLoopAsync() เพื่อทำเครื่องหมายจุดเริ่มต้นของลูปรอบ ขณะที่ผู้เล่นเข้าร่วมล็อบบี้และรอการจัดกลุ่มเป็นทีม startRoundLoopAsync() จะเรียกใช้ฟังก์ชัน resetScores() ใน ServerScriptServiceGameplayScoring เพื่อรีเซ็ตทั้งกระดานคะแนนและคะแนนทีม

Scoring
function Scoring.resetScores()
for _, player in Players:GetPlayers() do
player.leaderstats.Points.Value = 0
end
for _, team in Teams:GetTeams() do
team:SetAttribute(GuiAttribute.teamPoints, 0)
end
end

ตอนนี้ทุกคนเริ่มต้นที่คะแนนศูนย์ startRoundLoopAsync() จะตั้งค่าคุณสมบัติ Neutral ของตำแหน่งเกิด Neutral เป็น false เพื่อให้ผู้เล่นที่มีคุณสมบัติ Team.Color เหมือนกับคุณสมบัติ TeamColor ของตำแหน่งเกิดสามารถเกิดที่นั่นได้เท่านั้น เนื่องจากคุณสมบัติ TeamColor ของตำแหน่งเกิดถูกตั้งค่าเป็น white แทนที่จะเป็นทีมสีมิ้นต์หรือสีชมพูดอกกุหลาบ การกำหนดค่านี้จะป้องกันไม่ให้ผู้เล่นทั้งหมดเกิดหรือเกิดใหม่ที่นั่นในขณะที่รอบกำลังดำเนินอยู่

สำหรับผู้เล่นที่อยู่ในล็อบบี้ในขณะนี้ startRoundLoopAsync() จะส่งผู้เล่นทั้งหมดที่อยู่ในเกมไปยังฟังก์ชัน spawnPlayersInMap ใน ServerScriptServiceGameplayRoundsspawnPlayersInMap เพื่อจัดกลุ่มและปรับสมดุลทุกคนให้เป็นทีมที่มีจำนวนผู้เล่นประมาณเท่ากัน

สำหรับผู้เล่นใหม่ที่เข้าร่วมเกมหลังจากที่กลุ่มล็อบบี้ถูกจัดกลุ่มเป็นทีม startRoundLoopAsync() จะฟังเหตุการณ์ Players.PlayerAdded:Connect จากนั้นเรียกใช้ฟังก์ชัน spawnPlayersInMap อีกครั้งเพื่อเพิ่มพวกเขาไปยังทีมที่มีจำนวนผู้เล่นน้อยที่สุด สำหรับข้อมูลเพิ่มเติมเกี่ยวกับกระบวนการนี้ โปรดดูที่ กำหนดค่าตำแหน่งเกิด จากส่วนก่อนหน้า การเกิดและการเกิดใหม่ ของบทเรียน

Rounds
-- เกิดผู้เล่นทั้งหมดในแผนที่
neutralSpawn.Neutral = false
spawnPlayersInMap(Players:GetPlayers())
-- เกิดผู้เล่นใหม่ในแผนที่เมื่อพวกเขาเข้าร่วม
local playerAddedConnection = Players.PlayerAdded:Connect(function(player: Player)
spawnPlayersInMap({ player })
end)

ตั้งเป้าหมาย

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

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

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

"%d" เป็นสตริงตัวแทนที่คุณสามารถเพิ่มหรือลดได้ทุกเมื่อเพื่อตอบสนองความต้องการในการเล่นเกมของคุณโดยการอัปเดตตัวแปร TEAM_SCORE_LIMIT ใน ReplicatedStorageTEAM_SCORE_LIMIT ตัวอย่างเช่น หากคุณตั้งค่าหมายเลขนี้เป็น 200 ที่สูงเกินไป คำแนะนำและตัวนับคะแนนทีมจะอัปเดตตามนั้น

TEAM_SCORE_LIMIT
local TEAM_SCORE_LIMIT = 200 -- บรรทัดที่อัปเดต อย่าลืมเปลี่ยนกลับ
return TEAM_SCORE_LIMIT

การอัปเดตตัวแปรที่ง่ายนี้ทำงานในระหว่างการทำงานเพราะเมื่อรอบเริ่มต้น ReplicatedStorageHUDGuiSetupSetObjective ต้องการสคริปต์โมดูล TEAM_SCORE_LIMIT เพื่อให้สามารถเปลี่ยนสตริงตัวแทนในวัตถุ TextLabel ของ UI เป้าหมายได้

TEAM_SCORE_LIMIT
local TEAM_SCORE_LIMIT = require(ReplicatedStorage.TEAM_SCORE_LIMIT)
local function setObjective(gui: ScreenGui)
local bodyTextLabel = gui.Objective.ObjectiveDisplay.Body.BodyTextLabel
bodyTextLabel.Text = bodyTextLabel.Text:format(TEAM_SCORE_LIMIT)
end

ติดตามคะแนน

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

เพื่อให้แน่ใจว่าสิ่งนี้ไม่เกิดขึ้นและการมีส่วนร่วมทุกอย่างต่อเป้าหมายของทีมได้รับการเก็บรักษาไว้ ReplicatedStorageHUDGuiSetupStartSyncingTeamPoints จะเก็บคะแนนทั้งหมดแยกต่างหากภายใต้คุณสมบัติ teamPoints ในบริการ Teams ขณะที่ teamPoints เพิ่มขึ้น สคริปต์โมดูลนี้จะเรียกใช้ฟังก์ชัน startSyncingTeamPoints เพื่อค้นหานับทีม Class.GuiObjects ภายในส่วนประกอบ UI เป้าหมาย

เมื่อมันค้นพบ TeamACounter และ TeamBCounter มันจะได้รับคุณสมบัติ teamColor ของพวกเขาซึ่งสัมพันธ์กับโซนเกิดของทีม: TeamACounter แสดงคะแนนของทีมสีเขียว และ TeamBCounter ติดตามคะแนนของทีมสีชมพู

StartSyncingTeamPoints
local function startSyncingTeamPoints(gui: ScreenGui)
for _, teamPointCounter in gui.Objective.TeamPointCounter:GetChildren() do
if not teamPointCounter:IsA("GuiObject") then
continue
end
local iconTeamColor = teamPointCounter:GetAttribute(GuiAttribute.teamColor)

สคริปต์โมดูลนี้จะเรียกใช้ฟังก์ชัน getTeamFromTeamColor เพื่อยืนยันว่าคุณสมบัติ teamColor ของ TeamACounter ที่เป็นสีมิ้นต์และคุณสมบัติ teamColor ของ TeamBCounter ที่เป็นสีชมพูดอกกุหลาบตรงกับคุณสมบัติ Team.Color ที่สอดคล้องกันภายใต้บริการ Teams หากเป็นเช่นนั้น มันจะส่งคืนทั้งสองทีม

StartSyncingTeamPoints
local function getTeamFromTeamColor(teamColor: Color3): Team?
for _, team in Teams:GetTeams() do
if team.TeamColor == teamColor then
return team
end
end
return nil
end

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

StartSyncingTeamPoints
teamPointCounter.TextLabel.Text = team:GetAttribute(GuiAttribute.teamPoints)
team:GetAttributeChangedSignal(GuiAttribute.teamPoints):Connect(function()
teamPointCounter.TextLabel.Text = team:GetAttribute(GuiAttribute.teamPoints)

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

Scoring
local teamScoreChangedBindable = Instance.new("BindableEvent")
local Scoring = {
teamScoreChanged = teamScoreChangedBindable.Event,
}

จากนั้นมันจะเรียกใช้ฟังก์ชัน incrementScore ซึ่งทำการกระทำดังต่อไปนี้:

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

กระบวนการนี้ช่วยให้ทั้งลูกค้าและเซิร์ฟเวอร์สอดคล้องกันเกี่ยวกับคะแนนของผู้เล่นแต่ละคนและคะแนนทีมของพวกเขา

Scoring
function Scoring.incrementScore(player: Player, amount: number)
local team = player.Team
assert(team, `Player {player.Name} must be on a team to score a point, but has no team`)
local teamPoints = team:GetAttribute(GuiAttribute.teamPoints)
teamPoints += amount
team:SetAttribute(GuiAttribute.teamPoints, teamPoints)
local leaderstat = player.leaderstats.Points
leaderstat.Value += amount
teamScoreChangedBindable:Fire(team, teamPoints)
end

แสดงผลลัพธ์

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

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

Rounds
-- ตรวจสอบว่ารอบสิ้นสุดลงหลังจากแต่ละคะแนน
local team: Team
local score: number = 0
while score < TEAM_SCORE_LIMIT do
team, score = Scoring.teamScoreChanged:Wait()
end
-- แสดงทีมที่ชนะ
for _, player in Players:GetPlayers() do
-- ส่งข้อมูลว่าผู้เล่นอยู่ในทีมใดเมื่อสิ้นสุดรอบ
-- เพราะทีมของผู้เล่นกำลังจะถูกลบออก ดังนั้นลูกค้า
-- จะไม่สามารถตรวจสอบทีมของตนเองได้
roundWinnerRemote:FireClient(player, team, player.Team)
end

สคริปต์ ReplicatedStorageRoundResultsGuiSetup บนแต่ละลูกค้าจะฟังเหตุการณ์ roundWinnerRemote เพื่อให้สามารถ:

  • แสดงหน้าจอ UI StarterGuiRoundResultsGui ที่ไม่ซ้ำกันซึ่งประกาศผลลัพธ์ของรอบและถ้าผู้เล่นอยู่ในทีมที่ชนะ
  • เล่นคลิปเสียงชัยชนะหรือความพ่ายแพ้

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

ฟีดแบ็กชัยชนะ
ฟีดแบ็กความพ่ายแพ้
RoundResultsGuiSetup
local function onRoundWinner(winner: Team, localTeam: Team?)
local victoryDefeatText = "รอบสิ้นสุดลง!"
if localTeam then
-- หากทีมของเราชนะ เราจะแสดงชัยชนะ! มิฉะนั้นจะแสดงความพ่ายแพ้...
local isVictory = winner == localTeam
if isVictory then
victorySound:Play()
victoryDefeatText = VICTORY_TEXT
else
defeatSound:Play()
victoryDefeatText = DEFEAT_TEXT
end
end

รีเซ็ตทีม

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

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

Rounds
-- ส่งทุกคนไปยังล็อบบี้
playerAddedConnection:Disconnect()
neutralSpawn.Neutral = true
spawnPlayersInLobby(Players:GetPlayers())

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

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

©2026 Roblox Corporation. Roblox, โลโก้ Roblox และ Powering Imagination เป็นส่วนหนึ่งของเครื่องหมายการค้าที่จดทะเบียน และไม่ได้จดทะเบียนของเราในสหรัฐฯ และประเทศอื่นๆ