Menambahkan ronde memungkinkan Anda untuk mengstrukturkan permainan menjadi fase dengan titik awal dan akhir yang jelas sehingga pemain dapat mengukur kemajuan mereka dan memiliki kesempatan berkala untuk bidang bermain yang sama.Ini sangat penting untuk gameplay berbasis tim karena menawarkan pemain kesempatan untuk beralih gaya bermain mereka tergantung pada siapa yang ada di tim mereka selama ronde itu.
Menggunakan pengalaman label laser sampel sebagai referensi, bagian tutorial ini mengajarkan Anda cara menggunakan dan menyesuaikan fitur bawaan Roblox untuk membangun setiap ronde, termasuk panduan pemrograman tentang:
- Memulai ronde dengan mengatur ulang poin individu dan tim, lalu menypawn pemain ke zona spawn tim mereka.
- Mengustomisasi variabel yang menetapkan tujuan untuk ronde di bagian atas layar setiap pemain.
- Pelacakan kontribusi titik pemain untuk skor tim mereka.
- Memicu layar UI unik bergantung pada apakah tim pemain menang atau kalah dalam ronde.
- Mengakhiri ronde dengan memutus koneksi pemain dan menempatkannya di lobi netral.
Setelah Anda menyelesaikan bagian ini, Anda akan belajar cara menerapkan perilaku blaster yang akurat dan memuaskan bagi pemain.

Mulai loop
ServerScriptService > Gameplay > Ronde menangani sebagian besar logika untuk menerapkan ronde, dan dimulai dengan memanggil fungsi startRoundLoopAsync() untuk menandai awal ronde loop.Sementara pemain bergabung dengan lobi dan menunggu untuk disortir menjadi tim, startRoundLoopAsync() memanggil fungsi resetScores() di ServerScriptService > Gameplay > Skor untuk mengatur ulang kedua papan peringkat dan poin tim.
Peringkat
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
Sekarang semua orang mulai dari titik nol, kemudian mengatur properti Neutral lokasi spawn ke false sehingga hanya pemain dengan properti yang sama dengan lokasi spawn seperti properti hanya bisa muncul di sana.Karena properti lokasi spawn TeamColor diatur ke putih bukan tim mint atau karnasi merah muda sampel, konfigurasi ini mencegah semua pemain untuk bertelur atau bertelur kembali di sana saat ronde aktif.
Untuk pemain yang saat ini berada di lobi, startRoundLoopAsync() melewati semua pemain saat ini dalam pengalaman ke fungsi spawnPlayersInMap di ServerScriptService > Gameplay > Rounds > spawnPlayersInMap untuk mengurutkan dan menyeimbangkan semua orang ke dalam tim dengan jumlah pemain yang hampir sama.
Untuk pemain baru yang bergabung dalam pengalaman setelah kelompok lobi disortir menjadi tim, startRoundLoopAsync() mendengarkan acara Players.PlayerAdded:Connect , kemudian memanggil fungsi spawnPlayersInMap lagi untuk menambahkannya ke tim dengan jumlah pemain paling sedikit.Untuk informasi lebih lanjut tentang proses ini, lihat Konfigurasi Lokasi Penyebaran dari bagian sebelumnya Spawn dan Respawning dari tutorial.
Bulat
-- Hasilkan semua pemain di peta
neutralSpawn.Neutral = false
spawnPlayersInMap(Players:GetPlayers())
-- Memunculkan pemain baru di peta saat mereka bergabung
local playerAddedConnection = Players.PlayerAdded:Connect(function(player: Player)
spawnPlayersInMap({ player })
end)
Tetapkan tujuan
Sekarang setiap pemain berada di arena bersama rekan satu tim, pengalaman perlu memberikan instruksi tentang apa yang harus dilakukan untuk berhasil dalam ronde.Pengalaman label laser sampel menangani persyaratan ini dengan memberikan prompt objektif di bagian atas layar setiap pemain dengan panduan yang jelas tentang apa yang perlu dilakukan tim untuk menang.

Sementara Anda dapat mempelajari lebih lanjut tentang cara mengkonfigurasi dan menampilkan komponen Objektif UI di UI Kurikulum, bagian ini berfokus pada cara menerapkan tujuan tujuan saat ronde dimulai, mulai dengan cara menetapkan jumlah poin yang dibutuhkan setiap tim untuk menyelesaikan ronde.
Meskipun tujuan prompt saat runtime menginformasikan pemain bahwa mereka perlu mencetak tiga poin untuk menang, jika Anda memeriksa prompt di StarterGui > HUDGui , Anda dapat melihat bahwa sebaliknya berisi " %d " yang dapat disesuaikan untuk nilai poin.

“ %d ” adalah string placeholder yang dapat Anda tingkatkan atau kurangi kapan saja untuk memenuhi persyaratan permainan Anda sendiri dengan memperbarui variabel TEAM_SCORE_LIMIT di ReplicatedStorage > TEAM_SCORE_LIMIT .Sebagai contoh, jika Anda menetapkan nomor ini ke angka yang berlebih tinggi 200 , maka tombol dan titik penghitung tim akan diperbarui sesuai.
SKOR TEAM_SCORE_LIMIT
local TEAM_SCORE_LIMIT = 200 -- baris diperbarui, pastikan untuk kembali berubahreturn TEAM_SCORE_LIMIT

Pembaruan variabel sederhana ini berfungsi saat menjalankan karena saat ronde dimulai, ReplicatedStorage > HUDGuiSetup > Tetapkan Tujuan memerlukan skrip modul sehingga dapat bertukar string placeholder di objek Tujuan UI.
SKOR 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
Titik jejak
Sekarang pemain memiliki tujuan untuk ronde, pengalaman perlu melacak poin setiap tim sampai mereka memenuhi tujuan mereka.Sementara perilaku default layanan Teams membagi setiap pemain di bawah tim mereka dan menambahkan kontribusi setiap pemain ke skor tim mereka, penting untuk menyimpan dan memantau poin di lokasi terpisah untuk permainan berbasis ronde karena jika seorang pemain mencetak skor maka pergi sebelum ronde berakhir, kontribusi mereka dikurangkan dari papan peringkat saat mereka terhubung dari pengalaman.
Untuk memastikan ini tidak terjadi dan setiap kontribusi terhadap tujuan tim dipertahankan, ReplicatedStorage > HUDGuiSetup > MulaiSinkronisasiPoinTim menyimpan semua poin secara terpisah di bawah atribut di layanan.Sebagai teamPoints peningkatan, skrip modul ini memanggil fungsi startSyncingTeamPoints untuk menemukan counter tim Class.GuiObjects di dalam komponen UI Tujuan.
Ketika menemukan TeamACounter dan TeamBCounter , ia mendapatkan atribut teamColor mereka, yang berhubungan dengan zona spawn tim: TeamACounter menampilkan poin tim hijau, dan TeamBCounter melacak poin tim merah muda.
MulaiSinkronisasiTimPoin
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)
Skrip modul kemudian memanggil fungsi dari TeamACounter's mint attribute dan TeamBCounter's carnation pink attribute keduanya cocok dengan properti yang sesuai di bawah layanan .Jika demikian, ia mengembalikan kedua tim.
MulaiSinkronisasiTimPoin
local function getTeamFromTeamColor(teamColor: Color3): Team?
for _, team in Teams:GetTeams() do
if team.TeamColor == teamColor then
return team
end
end
return nil
end
Ketika ini terjadi, mengatur kedua objek penghitung tim ke nilai masing-masing tim, dan terus memperbaruinya setiap kali pemain mencetak poin dengan menandai pemain lain di tim lawan.
MulaiSinkronisasiTimPoin
teamPointCounter.TextLabel.Text = team:GetAttribute(GuiAttribute.teamPoints)
team:GetAttributeChangedSignal(GuiAttribute.teamPoints):Connect(function()
teamPointCounter.TextLabel.Text = team:GetAttribute(GuiAttribute.teamPoints)
Semua yang ada di bagian ini sejauh ini telah fokus pada cara melacak titik di layar pemain, tetapi penting untuk meninjau logika yang menangani titik pelacakan di server sehingga tahu kapan tim memenuhi tujuan dan memenangkan ronde.Jika Anda mengunjungi kembali ServerScriptService > Gameplay > Skor , Anda dapat melihat bahwa skrip modul dimulai dengan membuat acara yang dapat diikat, yang akan menembak setiap kali pemain mencetak poin.
Peringkat
local teamScoreChangedBindable = Instance.new("BindableEvent")local Scoring = {teamScoreChanged = teamScoreChangedBindable.Event,}
Kemudian memanggil fungsi incrementScore, yang melakukan tindakan berikut:
- Ambil skor individu pemain di papan peringkat, dan tambahkan satu.
- Memicu acara yang disebutkan sebelumnya yang dapat diikat dengan tim pemain dan skor mereka.
Proses ini secara efektif menjaga klien dan server sejalan mengenai skor individu pemain dan skor tim mereka.
Peringkat
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
Tampilkan hasil
Sebagai pemain saling menandai dan mencetak poin untuk tim mereka, ServerScriptService > Gameplay > Ronde memeriksa apakah tim yang mencetak memenuhi tujuan ronde.Jika skor tim mereka lebih rendah dari variabel TEAM_SCORE_LIMIT di ReplicatedStorage > TEAM_SCORE_LIMIT , server terus menunggu sampai salah satu tim skor lagi.
Namun, setelah skor tim mencapai variabel TEAM_SCORE_LIMIT, skrip memicu instansi acara roundWinnerRemote dengan nama pemain dan timnya.
Bulat
-- Periksa apakah ronde telah selesai setelah setiap skorlocal team: Teamlocal score: number = 0while score < TEAM_SCORE_LIMIT doteam, score = Scoring.teamScoreChanged:Wait()end-- Tampilkan tim pemenangfor _, player in Players:GetPlayers() do-- Mengirim tim mana pemain berada di akhir ronde-- karena tim pemain akan dihapus, sehingga klien-- tidak akan dapat memeriksa tim sendiriroundWinnerRemote:FireClient(player, team, player.Team)end
Skrip ReplicatedStorage > RoundResultsGuiSetup pada setiap daftar klien mendengarkan instansi peristiwa ini sehingga dapat:
- Tampilkan layar UI unik StarterGui > RoundResultsGui yang mengumumkan hasil ronde dan jika pemain berada di tim pemenang.
- Mainkan klip audio kemenangan atau kekalahan.
Sebagai contoh, jika seorang pemain berada di tim yang mencetak poin kemenangan, mereka menerima banyak bentuk umpan balik tentang hasil ronde dalam bentuk layar UI yang menampilkan teks kemenangan, dan klip audio yang memainkan suara bergembira.Sebaliknya, jika seorang pemain tidak berada di tim yang mencetak poin kemenangan, mereka menerima layar UI yang menampilkan teks kekalahan, dan klip audio yang memainkan suara mengerikan.
Pengaturan RoundResultsGui
local function onRoundWinner(winner: Team, localTeam: Team?)
local victoryDefeatText = "Round ended!"
if localTeam then
-- Jika tim kami menang, kami akan menampilkan Kemenangan! Jika tidak, tampilkan Kehilangan...
local isVictory = winner == localTeam
if isVictory then
victorySound:Play()
victoryDefeatText = VICTORY_TEXT
else
defeatSound:Play()
victoryDefeatText = DEFEAT_TEXT
end
end
Setel ulang tim
Pada saat yang sama bahwa ServerScriptService > Gameplay > Putaran memverifikasi bahwa tim memenuhi tujuan ronde dan memicu tampilan UI yang sesuai untuk setiap pemain, itu juga mengangkut semua pemain dari arena ke lobi dengan memutuskan mereka dari ronde.Ini memulai proses mengakhiri secara formal ronde dan mengatur ulang kedua tim.
Menggunakan logika yang sama di Konfigurasi Lokasi Penyebaran , Ronde kemudian menetapkan properti Neutral lokasi spawnke benar sehingga pemain dapat muncul di sana terlepas dari status tim mereka.Ini berarti lobi menjadi satu-satunya lokasi yang dapat dimunculkan pemain setelah mereka terputus dari ronde.
Bulat
-- Kirim semua orang ke lobiplayerAddedConnection:Disconnect()neutralSpawn.Neutral = truespawnPlayersInLobby(Players:GetPlayers())
Setelah menunggu sepuluh detik untuk istirahat, skrip server Putaran kemudian memulai loop lagi dengan mereset skor semua orang dan mengurutkannya ke tim baru.Sampel mengulangi proses bulat siklik ini lagi sampai tidak ada pemain di dalam server.
Sekarang pemain dapat muncul di peta dengan tim mereka sendiri dan memainkan ronde penuh, bagian berikutnya mengajarkan Anda tentang skrip di balik perilaku setiap blaster.