Meng spawn adalah proses pembuatan objek atau karakter dalam pengalaman, dan respawn adalah proses menambahkan objek atau karakter kembali ke pengalaman setelah mereka memenuhi kondisi penghapusan, seperti kesehatan karakter mencapai nol atau jatuh dari peta. Kedua proses ini penting karena mereka memastikan pemain dapat bergabung dengan p
Menggunakan sample laser tag experience sebagai referensi, bagian ini dari tutorial menunjukkan cara menggunakan dan menyesuaikan fitur bawaan Roblox untuk menangani pembuatan dan respawning, termasuk panduan pemrograman tentang:
- Mengkonfigurasi lokasi bertelur agar pemain hanya dapat bertelur di zona bertelur tim mereka.
- Menambahkan pemain baru dan karakter mereka ke putaran saat mereka bergabung dengan pengalaman.
- Mengubah force field yang mencegah kerusakan saat pemain bertelur dan respawn.
- Mengelola status klien sehingga permainan berjalan dengan benar pada waktu yang tepat.
- Mengembalikan karakter setelah mereka ditandai keluar dari putaran.
- Melakukan tindakan kecil, miscellaneous yang penting untuk menetapkan parameter gameplay dan karakter.
Bagian ini mencakup banyak konten script, tetapi alih-alih menulis semuanya dari awal saat membuat pengalaman, itu mengundang Anda untuk menggunakan komponen yang ada, secara cepat bereiteriterasi, dan menemukan sistem mana yang memerlukan implementasi khusus untuk menyertakan visi Anda. Setelah Anda menyelesaikan bagian ini, Anda akan belajar cara meng implementasikan gameplay berbasis putaran yang melacak po
Konfigurasikan Lokasi Spawn
Jika Anda memainkan pengalaman sekarang, semua pemain akan secara acak muncul di salah satu objek SpawnLocation atau SpawnLocation di zona pemunculan tim hijau, atau objek Class.SpawnLocation di zona pemunculan tim pink. Ini menghadirkan masalah gameplay di mana pemain dapat menandai satu sama lain di setiap zona
Untuk mengatasi masalah ini, pengalaman tag laser sampel mengkonfigurasi kedua lokasi bertelur dengan Neutral property set ke false untuk menghindari pemain tim lawan dari bertelur
- TimASpawn – Lokasi bertelur di zona bertelur tim hijau dengan propperti TeamColor yang di set ke Mint .
- TeamBSpawn – Lokasi bertelur di zona bertelur tim pink dengan propperti TeamColor yang di set ke Carnation Pink .
Ketika seorang pemain bergabung dengan pengalaman, ServerScriptService > Gameplay > Rounds > 1> Rounds1> > 4> spawnPlayersInMap4> memeriksa untuk melihat berapa banyak pemain yang sudah ada di setiap tim, kemudian kembali tim dengan jumlah pemain terkecil.
bertelurkanPemainPeta
local function getSmallestTeam(): Team
local teams = Teams:GetTeams()
-- Urutkan tim dalam urutan menaik dari terkecil hingga terbesar
table.sort(teams, function(teamA: Team, teamB: Team)
return #teamA:GetPlayers() < #teamB:GetPlayers()
end)
-- Kembalikan tim terkecil
return teams[1]
end
Setelah mengetahui tim dengan jumlah pemain terendah, itu mengurutkan pemain ke dalam tim itu, menetapkan propietas mereka Player.Neutral ke false sehingga pemain hanya dapat menelurkan dan respawn di lokasi spawnbertelur tim mereka, kemudian menetapkan propietas mereka Player
bertelurkanPemainPeta
local function spawnPlayersInMap(players: { Player })
for _, player in players do
player.Team = getSmallestTeam()
player.Neutral = false
player:SetAttribute(PlayerAttribute.playerState, PlayerState.SelectingBlaster)
task.spawn(function()
player:LoadCharacter()
end)
end
end
Jika Anda mengeksaminya Ruang kerja > Dunia > Peta > 1>Spawne1> , Anda dapat meli
Misalnya, jika putaran aktif, set property Neutral menjadi false sehingga spawnPlayersInMap dapat m
Untuk menunjukkan, jika Anda mengeksaminya ServerScriptService > Gameplay > Rounds > 1> SpawnPlayersInLobby1>, yang berjalan di akhir sebuah putaran, Anda dapat melihat bahwa untuk setiap pemain yang dilewati ke tabel 4> players: Player4>, script:
- Tetapkan property mereka Player.Neutral ke benar untuk secara otomatis mengatur ulang Player.Team mereka ke nil, memungkinkan pemain untuk respawn di lobi ketika putaran tidak aktif, karena property lokasi bertindak Neutral juga di tetapkan ke 1>
- Mengubah PlayerState mereka menjadi InLobby untuk menghapus UI visual pemain dan UI pemain pertama.
Untuk informasi lebih lanjut tentang zona bertelur netral dan fungsionalitasnya untuk setiap putaran, lihat Menambahkan Putaran di bagian selanjutnya dari tutorial.
bangkitkanPemainDiLobby
local function spawnPlayersInLobby(players: { Player })
for _, player in players do
player.Neutral = true
player:SetAttribute(PlayerAttribute.playerState, PlayerState.InLobby)
task.spawn(function()
player:LoadCharacter()
end)
end
end
Hubungkan Pemain Baru
Kode Luau di Studio sering berdasarkan acara, yang berarti bahwa skrip mendengarkan acara dari layanan Roblox, lalu memanggil fungsi dalam respons. Misalnya, ketika menambahkan pemain baru ke pengalaman multiplayer, harus ada acara yang menangani semua yang diperlukan untuk pemain untuk Connectdengan sukses. Dalam contoh tag laser yang sama, acara yang sesuai adalah
Players.PlayerAdded:Connect adalah bagian dari beberapa script dalam pengalaman. Jika Anda menggunakan pintasan Ctrl/Command+Shift+F dan mencari Players.PlayerAdded:Connect, hasil memberikan titik awal yang baik untuk memahami pengaturan awal pengalaman.
Untuk menunjukkan, buka ServerScriptService > SetupHumanoid . Perbedaan antara Player dan 2> Class.Player.Character|Character2> adalah kunci untuk memahami skrip ini:
- Pemain harus memilih blaster dan ditambahkan ke papan peringkat. Karakter harus bertelur dan menerima blaster.
SetupHumanoid segera memeriksa apakah pemain memiliki karakter (baru saja bergabung) atau tidak (respawning). Setelah menemukan salah satu, itu menele
aturanHumanoidAsync
local function setupHumanoidAsync(player: Player, humanoid: Humanoid)
humanoid.DisplayDistanceType = Enum.HumanoidDisplayDistanceType.Subject
humanoid.NameDisplayDistance = 1000
humanoid.HealthDisplayDistance = 1000
humanoid.NameOcclusion = Enum.NameOcclusion.OccludeAll
humanoid.HealthDisplayType = Enum.HumanoidHealthDisplayType.AlwaysOn
humanoid.BreakJointsOnDeath = false
humanoid.Died:Wait()
onHumanoidDied(player, humanoid)
end
Nota penting dengan skrip ini adalah bahwa proporsi adalah benar-benar opsional, yang berarti bahwa jika Anda menghapus enam baris pertama dari fungsi, pengalaman masih bekerja dengan benar. Daripada menjadi persyaratan fungsional, setiap proporsi memungkinkan Anda untuk membuat keputusan desain yang memenuhi tujuan permainan Anda. Misalnya:
- Jika Anda ingin nama karakter untuk ditampilkan dalam jarak yang lebih dekat, kurangi nilai Humanoid.NameDisplayDistance.
- Jika Anda hanya ingin kesehatan karakter untuk ditampilkan jika di bawah 100%, atur Humanoid.HealthDisplayType untuk Menampilkan saat rusak .
- Jika Anda ingin karakter tersebut terpisah saat kesehatan mereka mencapai 0, atur Humanoid.BreakJointsOnDeath ke Benar .
Jika Anda mengubah nilai dari property ini, penting untuk mengetahui apakah Anda dapat melihat dampak dari pengaturan baru Anda. Anda dapat menggandakan apa yang pemain alami dalam lingkungan multiplayer dengan memilih setidaknya dua karakter dalam seksi Klien dan Server dari tab Pengujian .
Contoh lain dari acara Players.PlayerAdded:Connect adalah di ServerScriptService > PlayerStateHandler . Sama seperti dalam contoh sebelumnya, 1> PlayerStateHandler
PemainStatusHandle
local function onPlayerAdded(player: Player)
player.CharacterAdded:Connect(function()
if not player.Neutral then
player:SetAttribute(PlayerAttribute.playerState, PlayerState.SelectingBlaster)
onPlayerStateChanged(player, PlayerState.SelectingBlaster)
end
end)
Satu variabel khusus dalam PlayerStateHandler memerlukan diskusi: attributeChangedConnectionByPlayer . Tabel ini menyimpan semua pemain dan koneksi mereka ke Datatype.RBXScriptConnection
PemainStatusHandle
local attributeChangedConnectionByPlayer = {}
local function onPlayerAdded(player: Player)
-- Tangani semua pembaruan masa depan ke status pemain
attributeChangedConnectionByPlayer[player] = player
:GetAttributeChangedSignal(PlayerAttribute.playerState)
:Connect(function()
local newPlayerState = player:GetAttribute(PlayerAttribute.playerState)
onPlayerStateChanged(player, newPlayerState)
end)
end
-- Terputus dari koneksi属性 yang diubah saat pemain pergi
local function onPlayerRemoving(player: Player)
if attributeChangedConnectionByPlayer[player] then
attributeChangedConnectionByPlayer[player]:Disconnect()
attributeChangedConnectionByPlayer[player] = nil
end
end
Anda dapat melihat bahwa kedua fungsi yang terhubung dalam onPlayerAdded() panggilan onPlayerStateChanged() . Selama pengaturan awal setelah seorang
PemainStatusHandle
local function onPlayerStateChanged(player: Player, newPlayerState: string)
-- Negara pemain adalah 'Siap' hanya jika negara pemain adalah 'Bermain'
local newBlasterState = if newPlayerState == PlayerState.Playing then BlasterState.Ready else BlasterState.Disabled
-- Jadwalkan logika forcefield saat pemain mulai bermain
if newPlayerState == PlayerState.Playing then
scheduleDestroyForceField(player)
end
player:SetAttribute(PlayerAttribute.blasterStateServer, newBlasterState)
end
Jika Anda menambahkan breakpoints atau bahkan hanya menulis <
Sesuaikan Force Fields
Alih-alih menggunakan implementasi khusus, pengalaman laser tag sampel menggunakan kelas ForceField bawaan Studio untuk mencegah pemain mengambil kerusakan saat mereka memilih laser mereka. Ini menj
Mirip dengan setupHumanoidAsync , sebagian besar dari baris-baris dalam ForceFieldClientVisuals adalah opsional. Misalnya, jika Anda menyebutkan konten fungsi seperti yang dilakukan oleh script berikut, pengalaman menggunakan campo tekan default alih-alih skrip heksagonal di StarterGui > 1> ForceFieldGui</
Mengkomentari Out Properties di ForceFieldClientVisuals
local function onCharacterAddedAsync(character: Model)
-- ForceField = karakter: tunggu anak ("ForceField", 3)
-- jika tidak forceField maka
-- kembali
-- akhiri
-- forceField.Visible = benar
-- localPlayer.PlayerGui:WaitForChild("ForceFieldGui").Enabled = true
-- forceField.Destroying:Tunggu()
-- localPlayer.PlayerGui.ForceFieldGui.Enabled = false
end
Karena campo kekuatan khusus adalah GUI bukan Class.ParticleEmitter baru, script ForceFieldClientVisuals hanya meng影响玩家 pertama tentang visual kekuatan untuk setiap pemain, bukan visual pihak ketiga ketika pemain melihat pemain lain. Visual kekuatan pihak ketiga menyimpan penampilanRoblox default.
Force field berguna karena mereka memberikan pemain cukup waktu untuk bertukar antara spawning dan respawning tanpa perlu khawatir tentang pemain musuh, tetapi pada akhirnya mereka perlu menghilang untuk gameplay laser tag utama. Skrip yang menangani menghapus force field adalah di ReplicatedStorage > scheduleDestroyForceField , dan memeriksa tiga kondisi unik:
- Setelah pemain memilih blaster, force field harus bertahan cukup lama untuk memungkinkan pemain beradaptasi dengan lingkungan mereka.
- Selama waktu acclimation ini, force field tidak dapat menjadi keuntungan, jadi mereka perlu menghilang saat pemain menyalakan blaster mereka.
- Ladang kekuatan perlu menghilang saat pemain mengatur ulang karakter mereka sebelum meledak atau sebelum waktu force field habis.
Masing-masing dari periksa ini dalam scheduleDestroyForceField panggilan skrip endForceField() untuk kondisi ini.
jadwalHancurkanKekuatan
-- Akhiri lapangan kekuatan jika pemain meledak
local blasterStateAttribute = getBlasterStateAttribute()
attributeChangedConnection = player:GetAttributeChangedSignal(blasterStateAttribute):Connect(function()
local currentBlasterState = player:GetAttribute(blasterStateAttribute)
if currentBlasterState == BlasterState.Blasting then
endForceField()
end
end)
-- Akhiri force field jika pemain resets
characterRespawnedConnection = player.CharacterRemoving:Connect(endForceField)
-- Lepaskan lapangan kekuatan setelah 8 detik
task.delay(MAX_FORCE_FIELD_TIME, endForceField)
endForceField() termasuk pernyataan if yang tampaknya aneh di sekitar fungsi forceFieldEnded . Karena pemeriksaan berjalan secara berurutan, script dapat memanggil fungsi 0> endForceField0> dua atau bahkan tiga kali. Fungsi 3> end
jadwalHancurkanKekuatan
local function endForceField()
if forceFieldEnded then
return
end
forceFieldEnded = true
attributeChangedConnection:Disconnect()
characterRespawnedConnection:Disconnect()
destroyForceField(player)
end
Penanganan Status Klien
Sementara sebagian besar dari bagian ini berfokus pada ServerScriptService > PlayerStateHandler , ada script lain dari nama yang sama di ReplicatedStorage . Alasan untuk perpecahan ini adalah arsitektur klien-server:
Klien perlu memahami informasi status pemain sehingga itu dapat merespon dengan benar dalam waktu nyata, seperti menampilkan elemen antarmuka pengguna yang benar, atau mengaktifkan pemain untuk bergerak dan meledak.
Server memerlukan semua informasi yang sama ini sehingga itu dapat mencegah exploit. Misalnya, server juga memerlukan status pemain untuk melakukan tindakan seperti menelurkan dan mengepak kaki, menonaktifkan force field, dan menampilkan papan peringkat. Inilah mengapa script ini berada di ReplicatedStorage dan bukan lokasi client-side.
Untuk melihat logika inti ini, tinjau script berikut di ReplicatedStorage > PlayerStateHandler yang memverifikasi status pengguna saat ini, lalu memanggil fungsi yang sesuai yang menangani tindakan yang sesuai untuk status itu.
PemainStatusHandle
local function onPlayerStateChanged(newPlayerState: string)
if newPlayerState == PlayerState.SelectingBlaster then
onSelectingBlaster()
elseif newPlayerState == PlayerState.Playing then
onPlaying()
elseif newPlayerState == PlayerState.TaggedOut then
onTaggedOut()
elseif newPlayerState == PlayerState.InLobby then
onInLobby()
else
warn(`Invalid player state ({newPlayerState})`)
end
end
Semua tanggapan acara dianggap bersama-sama dalam script ini karena mereka memerlukan perilaku serupa untuk mengaktifkan atau menonaktifkan kendalipemain, gerakan kamera, dan UI layer yang terlihat. Misalnya, selama pemilihan blaster, pemain perlu menjadi invulnerable dan tidak dapat bergerak. Untuk men
PemainStatusHandle
local function onSelectingBlaster()
togglePlayerCamera(true)
togglePlayerMovement(false)
setGuiExclusivelyEnabled(playerGui.PickABlasterGui)
localPlayer:SetAttribute(PlayerAttribute.blasterStateClient, BlasterState.Disabled)
end
Fungsi onPlaying() sama mudah. Ini mengaktifkan gerakan, transisi ke tampilan utama (HUD), mengaktifkan blaster, dan memanggil fungsi field kekuatan serupa dengan server.
PemainStatusHandle
local function onPlaying()
togglePlayerMovement(true)
setGuiExclusivelyEnabled(playerGui.HUDGui)
localPlayer:SetAttribute(PlayerAttribute.blasterStateClient, BlasterState.Ready)
scheduleDestroyForceField()
end
Menggandakan Karakter
Pengalaman laser tag sampel menangani respawning character back into a round melalui onTaggedOut() state in ReplicatedStorage > PlayerStateHandler . Seperti 11 onSelectingBlaster()
PemainStatusHandle
local function onTaggedOut()
-- Nonaktifkan kontrol saat ditandai
togglePlayerMovement(false)
togglePlayerCamera(false)
setGuiExclusivelyEnabled(playerGui.OutStateGui)
-- Nonaktifkan blaster saat ditandai keluar
localPlayer:SetAttribute(PlayerAttribute.blasterStateClient, BlasterState.Disabled)
end
Jika Anda ingin menguji perilaku ini, Anda dapat menekan Esc, navigate to the Settings tab, then click the Reset Character button. Perhatikan bahwa ketika Anda mengaktifkan layar respawn, Anda tidak dapat bergerak, memutar kamera, atau meledakkan blaster Anda.
Penting untuk dicatat bahwa script ini tidak benar-benar menghasilkan karakter baru,
Ketika pemain respawn kembali ke ronde, mereka respawn di lokasi bertelur tim mereka menurut properti SpawnLocation.TeamColor. Untuk menyesuaikan waktu respawn, Anda dapat menambahkan baris berikut ke bagian atas SetupHumanoid . Untuk belajar lebih lanjut tentang teknik ini, lihat Players.RespawnTime.
Pengaturan Manusia
local Players = game:GetService("Players")Players.RespawnTime = 10 -- new line, in seconds
Pengaturan Umum
Sebagai bagian dari pengaturan awal, pengalaman tag laser sampel juga melakukan beberapa langkah kecil tapi penting:
Pengalaman ini termasuk naskah kosong bernama StarterPlayer > StarterCharacterScripts > Kesehatan yang menonaktifkan regenerasi kesehatan default Roblox. Untuk penjelasan perilaku propperti ini, lihat 1> Class.Humanoid.Health1> .
Pengalaman menggunakan kamera orang pertama dengan menetapkan StarterPlayer.CameraMode.LockFirstPerson property. Catat bahwa jika Anda ingin membiarkan pengguna beralih antara kamera orang pertama dan kamera orang ketiga, Anda harus mengubah program secara otomatis daripada hanya menetapkannya sekali di Studio, dan mengubah kontrol dan UI untuk menyesuaikan perubahan perspektif.
Pengalaman menggunakan papan peringkat Roblox bawaan dengan unit "poin", yang pemain peroleh setiap kali mereka tag pemain lain keluar. Anda dapat melihat konfigurasi di ServerScriptService > SetupLeaderboard , tet
Sekarang para pemain dapat spawn, pilih blaster, dan bidik dari sudut pandang orang pertama, bagian berikutnya mengajari Anda tentang script di belakang membuat gameplay berdasarkan putaran.