Tambahkan ronde

*Konten ini diterjemahkan menggunakan AI (Beta) dan mungkin mengandung kesalahan. Untuk melihat halaman ini dalam bahasa Inggris, klik di sini.

Menambahkan ronde memungkinkan Anda mengatur gameplay menjadi fase dengan titik mulai dan selesai yang jelas sehingga pemain dapat mengukur kemajuan mereka dan memiliki kesempatan periodik untuk bermain dalam kondisi yang setara. Ini sangat penting untuk gameplay berbasis tim karena memberikan pemain kesempatan untuk mengubah gaya bermain mereka tergantung pada siapa yang ada di tim mereka selama ronde tersebut.

Menggunakan pengalaman laser tag contoh sebagai referensi, bagian dari tutorial ini mengajarkan Anda cara menggunakan dan menyesuaikan fitur bawaan Roblox untuk mengatur setiap ronde, termasuk bimbingan scripting tentang:

  • Memulai ronde dengan mengatur ulang poin individu dan tim, kemudian memunculkan pemain ke zona spawn tim mereka.
  • Menyesuaikan variabel yang mengatur tujuan untuk ronde di bagian atas layar setiap pemain.
  • Melacak kontribusi poin pemain untuk skor tim mereka.
  • Memicu tampilan UI unik tergantung pada apakah tim pemain memenangkan atau kalah ronde.
  • Mengakhiri ronde dengan memutuskan koneksi pemain dan memunculkan mereka di lobi netral.

Setelah Anda menyelesaikan bagian ini, Anda akan belajar bagaimana mengimplementasikan perilaku blaster yang akurat dan memuaskan bagi pemain.

Mulai loop

ServerScriptServiceGameplayRounds menangani sebagian besar logika untuk mengimplementasikan ronde, dan dimulai dengan memanggil fungsi startRoundLoopAsync() untuk menandai awal dari loop ronde. Sementara pemain bergabung ke lobi dan menunggu untuk disortir ke tim, startRoundLoopAsync() memanggil fungsi resetScores() di ServerScriptServiceGameplayScoring untuk mengatur ulang baik papan peringkat maupun poin tim.

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

Sekarang semua orang memulai dengan nol poin, startRoundLoopAsync() kemudian mengatur properti lokasi spawn Neutral Neutral menjadi false sehingga hanya pemain dengan properti Team.Color yang sama dengan properti TeamColor dari lokasi spawn yang dapat muncul di sana. Karena properti TeamColor dari lokasi spawn diatur ke white alih-alih tim mint atau carnation pink dari contoh, konfigurasi ini mencegah semua pemain muncul atau respawn di sana sementara ronde aktif.

Untuk pemain yang saat ini berada di lobi, startRoundLoopAsync() meneruskan semua pemain yang saat ini berada dalam pengalaman ke fungsi spawnPlayersInMap di ServerScriptServiceGameplayRoundsspawnPlayersInMap untuk menyortir dan menyeimbangkan semua orang ke dalam tim dengan jumlah pemain yang kira-kira sama.

Untuk pemain baru yang bergabung dengan pengalaman setelah kelompok lobi disortir ke dalam tim, startRoundLoopAsync() mendengarkan acara Players.PlayerAdded:Connect, kemudian memanggil lagi fungsi spawnPlayersInMap untuk menambahkan mereka ke tim dengan jumlah pemain paling sedikit. Untuk informasi lebih lanjut tentang proses ini, lihat Konfigurasi Lokasi Spawn dari bagian Memunculkan dan Respawn sebelumnya dari tutorial.

Rounds

-- Spawn all players in the map
neutralSpawn.Neutral = false
spawnPlayersInMap(Players:GetPlayers())
-- Spawn new players in the map when they join
local playerAddedConnection = Players.PlayerAdded:Connect(function(player: Player)
spawnPlayersInMap({ player })
end)

Tetapkan tujuan

Sekarang bahwa setiap pemain berada di arena dengan rekan satu tim mereka, pengalaman perlu memberikan instruksi tentang apa yang harus dilakukan untuk berhasil dalam ronde. Pengalaman laser tag contoh memenuhi persyaratan ini dengan memberikan prompt tujuan 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 mengonfigurasi dan menampilkan komponen UI Tujuan dalam Kurikulum UI, bagian ini fokus pada cara mengimplementasikan tujuan saat ronde dimulai, dimulai dengan bagaimana menetapkan jumlah poin yang perlu diselesaikan oleh setiap tim untuk menyelesaikan ronde.

Meskipun prompt tujuan saat runtime memberi tahu pemain bahwa mereka perlu mencetak tiga poin untuk menang, jika Anda memeriksa prompt di StarterGuiHUDGui, Anda dapat melihat bahwa ia malah berisi "%d" yang dapat dikonfigurasi untuk nilai poin.

"%d" adalah string placeholder yang dapat Anda tingkatkan atau kurangi kapan saja untuk memenuhi kebutuhan gameplay Anda sendiri dengan memperbarui variabel TEAM_SCORE_LIMIT di ReplicatedStorageTEAM_SCORE_LIMIT. Sebagai contoh, jika Anda mengatur angka ini ke 200 yang terlalu tinggi, prompt dan penghitung poin tim akan diperbarui sesuai.

TEAM_SCORE_LIMIT

local TEAM_SCORE_LIMIT = 200 -- updated line, be sure to change back
return TEAM_SCORE_LIMIT

Pembaruan variabel sederhana ini bekerja saat runtime karena saat ronde dimulai, ReplicatedStorageHUDGuiSetupSetObjective memerlukan modul skrip TEAM_SCORE_LIMIT sehingga dapat menukar string placeholder di objek TextLabel UI Tujuan.

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

Melacak poin

Sekarang bahwa pemain memiliki tujuan untuk ronde, pengalaman perlu melacak poin masing-masing tim hingga mereka memenuhi tujuan mereka. Sementara perilaku default dari layanan Teams secara otomatis mengelompokkan setiap pemain di bawah tim mereka dan menjumlahkan kontribusi setiap pemain ke skor tim mereka, penting untuk menyimpan dan memantau poin di lokasi terpisah untuk gameplay berbasis ronde karena jika seorang pemain mencetak poin lalu keluar sebelum ronde berakhir, kontribusinya akan dipotong dari papan peringkat segera setelah mereka terputus dari pengalaman.

Untuk memastikan ini tidak terjadi dan setiap kontribusi menuju tujuan tim tetap terjaga, ReplicatedStorageHUDGuiSetupStartSyncingTeamPoints menyimpan semua poin secara terpisah di bawah atribut teamPoints dalam layanan Teams. Saat teamPoints meningkat, modul skrip ini memanggil fungsi startSyncingTeamPoints untuk menemukan penghitung tim Class.GuiObjects di dalam komponen UI Tujuan.

Ketika menemukan TeamACounter dan TeamBCounter, ia mendapatkan atribut teamColor mereka, yang berkorelasi dengan zona spawn tim: TeamACounter menampilkan poin tim hijau, dan TeamBCounter melacak poin tim pink.

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)

Modul skrip kemudian memanggil fungsi getTeamFromTeamColor untuk memvalidasi bahwa atribut teamColor mint dari TeamACounter dan atribut teamColor carnation pink dari TeamBCounter keduanya cocok dengan properti Team.Color yang sesuai di bawah layanan Teams. Jika demikian, ia mengembalikan kedua tim tersebut.

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

Ketika ini terjadi, startSyncingTeamPoints mengatur objek TextLabel dari kedua penghitung tim ke nilai teamPoints mereka yang sesuai, dan terus memperbarui mereka setiap kali seorang pemain mencetak poin dengan menandai pemain lain di tim lawan.

StartSyncingTeamPoints

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

Semuanya di bagian ini sejauh ini telah berfokus pada cara melacak poin di layar pemain, tetapi penting untuk meninjau logika yang menangani pelacakan poin di server sehingga tahu kapan tim memenuhi tujuan dan memenangkan ronde. Jika Anda mengunjungi ServerScriptServiceGameplayScoring, Anda dapat melihat bahwa modul skrip dimulai dengan membuat acara bindable, yang akan dipicu setiap kali seorang pemain mencetak poin.

Scoring

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

Ia kemudian memanggil fungsi incrementScore, yang melakukan tindakan berikut:

  • Mengambil tim pemain dan nilai teamPoints mereka saat ini di objek Team dalam layanan Teams, kemudian menambah satu.
  • Mengambil skor individu pemain di papan peringkat, dan menambah satu.
  • Memicu acara bindable sebelumnya yang disebutkan dengan tim pemain dan skor mereka.

Proses ini secara efektif menjaga keselarasan antara klien dan server mengenai skor individu dan skor tim pemain.

Scoring

function Scoring.incrementScore(player: Player, amount: number)
local team = player.Team
assert(team, `Pemain {player.Name} harus berada di tim untuk mencetak poin, tetapi tidak memiliki tim`)
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

Saat pemain saling menandai dan mencetak poin untuk tim mereka, ServerScriptServiceGameplayRounds memeriksa apakah tim yang mencetak poin memenuhi tujuan ronde. Jika skor tim mereka lebih rendah dari variabel TEAM_SCORE_LIMIT di ReplicatedStorageTEAM_SCORE_LIMIT, server terus menunggu sampai salah satu tim mencetak lagi.

Namun, setelah skor tim mencapai variabel TEAM_SCORE_LIMIT, skrip memicu sebuah instance acara roundWinnerRemote dengan nama pemain dan tim mereka.

Rounds

-- Check if the round has finished after each score
local team: Team
local score: number = 0
while score < TEAM_SCORE_LIMIT do
team, score = Scoring.teamScoreChanged:Wait()
end
-- Display winning team
for _, player in Players:GetPlayers() do
-- Sending what team the player is on at the end of the round
-- because the player's team is about to be removed, so the client
-- won't be able to check its own team
roundWinnerRemote:FireClient(player, team, player.Team)
end

Skrip ReplicatedStorageRoundResultsGuiSetup pada setiap klien mendengarkan untuk acara instance roundWinnerRemote ini sehingga dapat:

  • Menampilkan layar UI StarterGuiRoundResultsGui unik yang mengumumkan hasil ronde dan apakah pemain berada di tim pemenang.
  • Memainkan klip audio kemenangan atau kekalahan.

Sebagai contoh, jika pemain berada di tim yang mencetak poin kemenangan, mereka menerima beberapa bentuk umpan balik tentang hasil ronde dalam bentuk layar UI yang menampilkan teks kemenangan, dan klip audio yang memainkan suara gembira. Sebaliknya, jika pemain tidak berada di tim yang mencetak poin kemenangan, mereka menerima layar UI yang menampilkan teks kekalahan, dan klip audio yang memainkan suara menakutkan.

Umpan balik Kemenangan
Umpan balik Kekalahan
RoundResultsGuiSetup

local function onRoundWinner(winner: Team, localTeam: Team?)
local victoryDefeatText = "Ronde berakhir!"
if localTeam then
-- Jika tim kami menang, kami akan menampilkan Kemenangan! Jika tidak, tampilkan Kekalahan...
local isVictory = winner == localTeam
if isVictory then
victorySound:Play()
victoryDefeatText = VICTORY_TEXT
else
defeatSound:Play()
victoryDefeatText = DEFEAT_TEXT
end
end

Reset tim

Pada saat yang sama bahwa ServerScriptServiceGameplayRounds memverifikasi bahwa sebuah tim memenuhi tujuan ronde dan memicu tampilan UI yang sesuai untuk setiap pemain, ia juga mentransportasikan semua pemain dari arena ke lobi dengan memutuskan koneksi mereka dari ronde. Ini memulai proses secara resmi mengakhiri ronde dan mereset kedua tim.

Menggunakan logika yang sama dalam Konfigurasi Lokasi Spawn, Rounds kemudian mengatur properti Neutral dari lokasi spawn Neutral menjadi true sehingga pemain dapat muncul di sana terlepas dari status tim mereka. Ini berarti lobi menjadi satu-satunya lokasi tempat pemain dapat muncul setelah mereka terputus dari ronde.

Rounds

-- Send everyone to the lobby
playerAddedConnection:Disconnect()
neutralSpawn.Neutral = true
spawnPlayersInLobby(Players:GetPlayers())

Setelah menunggu sepuluh detik untuk jeda, skrip server Rounds kemudian memulai loop lagi dengan mengatur ulang skor semua orang dan menyortir mereka ke dalam tim baru. Sampel ini mengulangi proses ronde siklis ini lagi hingga tidak ada pemain di dalam server.

Sekarang bahwa pemain dapat muncul ke peta dengan tim mereka sendiri dan bermain satu ronde penuh, bagian selanjutnya mengajarkan Anda tentang skrip di balik perilaku setiap blaster.

©2026 Roblox Corporation. Roblox, logo Roblox, dan Powering Imagination termasuk dalam merek dagang kami yang terdaftar dan tidak terdaftar di AS dan negara lainnya.