Spawn và respawn

*Nội dung này được dịch bằng AI (Beta) và có thể có lỗi. Để xem trang này bằng tiếng Anh, hãy nhấp vào đây.

Spawn là quá trình tạo ra một đối tượng hoặc nhân vật trong một trò chơi, và respawn là quá trình đưa một đối tượng hoặc nhân vật trở lại vào trò chơi sau khi họ gặp điều kiện loại bỏ, chẳng hạn như sức khỏe của nhân vật đạt đến zero hoặc rơi ra khỏi bản đồ. Cả hai quá trình này đều quan trọng vì chúng đảm bảo rằng người chơi có thể tham gia trò chơi của bạn và có thể tiếp tục chơi để cải thiện kỹ năng của họ.

Sử dụng trò chơi laser tag mẫu làm tham chiếu, phần này của hướng dẫn sẽ dạy bạn cách sử dụng và tùy chỉnh các tính năng tích hợp sẵn của Roblox để xử lý việc spawn và respawn, bao gồm hướng dẫn lập trình về:

  • Cấu hình các vị trí spawn để người chơi chỉ có thể spawn vào khu vực spawn của đội mình.
  • Thêm người chơi mới và nhân vật của họ vào vòng chơi khi họ tham gia trò chơi.
  • Tùy chỉnh các trường lực để ngăn chặn sát thương khi người chơi spawn và respawn.
  • Xử lý trạng thái của client để gameplay hoạt động chính xác vào thời điểm thích hợp.
  • Respawn các nhân vật sau khi họ bị loại khỏi vòng chơi.
  • Thực hiện các hành động nhỏ, linh tinh mà rất quan trọng để thiết lập gameplay và các tham số của nhân vật.

Phần này bao gồm nhiều nội dung lập trình, nhưng thay vì viết mọi thứ từ đầu khi tạo một trò chơi, nó khuyến khích bạn tận dụng các thành phần hiện có, lặp lại nhanh chóng và tìm ra hệ thống nào cần một triển khai tùy chỉnh để phù hợp với tầm nhìn của bạn. Sau khi bạn hoàn thành phần này, bạn sẽ học cách triển khai gameplay theo vòng mà theo dõi điểm số, giám sát trạng thái người chơi và hiển thị kết quả vòng chơi.

Cấu hình các vị trí spawn

Nếu bạn thử nghiệm trò chơi ngay bây giờ, tất cả người chơi sẽ spawn ngẫu nhiên tại đối tượng SpawnLocation trong khu vực spawn của đội xanh, hoặc đối tượng SpawnLocation trong khu vực spawn của đội hồng. Điều này tạo ra một vấn đề trong gameplay khi người chơi có thể tag nhau trong mỗi khu vực spawn ngay khi trường lực của đối thủ biến mất.

Để chống lại vấn đề này, trò chơi laser tag mẫu cấu hình cả hai vị trí spawn với thuộc tính Neutral được đặt thành false để hạn chế người chơi của đội đối phương spawn vào khu vực spawn sai, và thuộc tính TeamColor được đặt thành giá trị tương ứng của Team.Color từ Gán màu đội trong phần trước của hướng dẫn:

  • TeamASpawn – Vị trí spawn trong khu vực spawn của đội xanh với thuộc tính TeamColor được đặt thành Mint.
  • TeamBSpawn – Vị trí spawn trong khu vực spawn của đội hồng với thuộc tính TeamColor được đặt thành Carnation Pink.
TeamASpawn
TeamBSpawn

Khi một người chơi tham gia trò chơi, ServerScriptServiceGameplayRoundsspawnPlayersInMap kiểm tra xem có bao nhiêu người chơi đã có trên mỗi đội, sau đó trả về đội có ít người chơi nhất.

spawnPlayersInMap
local function getSmallestTeam(): Team
local teams = Teams:GetTeams()
-- Sắp xếp các đội theo thứ tự tăng dần từ nhỏ nhất đến lớn nhất
table.sort(teams, function(teamA: Team, teamB: Team)
return #teamA:GetPlayers() < #teamB:GetPlayers()
end)
-- Trả về đội nhỏ nhất
return teams[1]
end

Khi nó biết đội có ít người chơi nhất, nó sắp xếp người chơi vào đội đó, đặt thuộc tính Player.Neutral của họ thành false để người chơi chỉ có thể spawn và respawn vào vị trí spawn của đội mình, sau đó đặt trạng thái PlayerState của họ thành SelectingBlaster, mà bạn sẽ tìm hiểu thêm sau trong hướng dẫn.

spawnPlayersInMap
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

Nếu bạn kiểm tra WorkspaceWorldMapSpawns, bạn có thể thấy rằng có một vị trí spawn khác trong bản đồ: NeutralSpawn. Vị trí spawn này khác với các vị trí khác vì nó không có thuộc tính TeamColor được đặt thành một trong hai đội trong trò chơi; thay vào đó, vị trí spawn này có thuộc tính Neutral thay đổi tùy thuộc vào việc một vòng chơi có đang hoạt động hay không.

Ví dụ, nếu vòng chơi đang hoạt động, thuộc tính Neutral được đặt thành false để spawnPlayersInMap có thể sắp xếp người chơi vào các đội và spawn họ vào đấu trường. Tuy nhiên, nếu vòng chơi không hoạt động, chẳng hạn như thời gian giữa một vòng và vòng tiếp theo, thuộc tính Neutral được đặt thành true để người chơi có thể spawn ở đó bất kể trạng thái đội của họ. Quá trình này là điều làm cho vị trí spawn Neutral trở thành một sảnh chức năng.

Neutral

Để minh họa, nếu bạn kiểm tra ServerScriptServiceGameplayRoundsSpawnPlayersInLobby, chạy vào cuối một vòng chơi, bạn có thể thấy rằng đối với mỗi người chơi được truyền vào bảng players: { Player }, script:

  • Đặt thuộc tính Player.Neutral của họ thành true để tự động đặt lại Player.Team của họ thành nil, cho phép người chơi respawn trong sảnh khi một vòng không hoạt động, vì thuộc tính Neutral của vị trí spawn cũng được đặt thành true.
  • Thay đổi trạng thái PlayerState của họ thành InLobby để loại bỏ blaster của người chơi và các hình ảnh giao diện người dùng trong chế độ xem thứ nhất.

Để biết thêm thông tin về khu vực spawn trung lập và chức năng của nó cho mỗi vòng, hãy xem Thêm Vòng trong phần tiếp theo của hướng dẫn.

spawnPlayersInLobby
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

Kết nối người chơi mới

Mã Luau trong Studio thường được điều khiển bởi sự kiện, có nghĩa là các script lắng nghe các sự kiện từ một dịch vụ Roblox, sau đó gọi một hàm để phản hồi. Ví dụ, khi thêm người chơi mới vào một trò chơi nhiều người, phải có một sự kiện xử lý mọi thứ cần thiết để người chơi kết nối thành công. Trong trò chơi laser tag mẫu, sự kiện tương ứng này là Players.PlayerAdded:Connect.

Players.PlayerAdded:Connect là một phần của nhiều script trong trò chơi. Nếu bạn sử dụng phím tắt Ctrl/Cmd+Shift+F và tìm kiếm Players.PlayerAdded:Connect, các kết quả cung cấp một điểm khởi đầu tốt để hiểu về thiết lập ban đầu của trò chơi.

Cửa sổ Tìm Tất cả của Studio với các kết quả Players.PlayerAdded được làm nổi bật.

Để minh họa, mở ServerScriptServiceSetupHumanoid. Sự phân biệt giữa PlayerCharacter là chìa khóa để hiểu script này:

  • Một người chơi là một client đã kết nối, và một nhân vật là một mô hình Humanoid.
  • Người chơi cần chọn một blaster và được thêm vào bảng điểm. Nhân vật cần được spawn và nhận một blaster.

SetupHumanoid ngay lập tức kiểm tra xem người chơi có một nhân vật (vừa tham gia) hay không (đang respawn). Sau khi tìm thấy một cái, nó gọi onCharacterAdded(), lấy mô hình Humanoid từ nhân vật và truyền nó đến ServerScriptServiceSetupHumanoidsetupHumanoidAsync để tùy chỉnh. Sau khi thiết lập các giá trị này, script sẽ chờ cho sức khỏe của nhân vật đạt đến zero. Bạn sẽ tìm hiểu thêm về respawn sau trong phần này của hướng dẫn.

setupHumanoidAsync
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

Lưu ý quan trọng với script này là các thuộc tính hoàn toàn là tùy chọn, có nghĩa là nếu bạn xóa sáu dòng đầu tiên của hàm, trò chơi vẫn hoạt động đúng. Thay vì là yêu cầu chức năng, mỗi thuộc tính cho phép bạn đưa ra các quyết định thiết kế phù hợp với mục tiêu gameplay của bạn. Ví dụ:

  • Nếu bạn muốn tên nhân vật hiển thị ở khoảng cách gần hơn, giảm giá trị của Humanoid.NameDisplayDistance.
  • Nếu bạn chỉ muốn hiển thị sức khỏe của nhân vật nếu nó dưới 100%, đặt Humanoid.HealthDisplayType thành DisplayWhenDamaged.
  • Nếu bạn muốn nhân vật bị vỡ ra khi sức khỏe của họ đạt 0, đặt Humanoid.BreakJointsOnDeath thành True.

Nếu bạn thay đổi các giá trị của những thuộc tính này, điều quan trọng là phải thử nghiệm để bạn có thể thấy tác động của các cài đặt mới của bạn. Bạn có thể tái tạo những gì người chơi trải nghiệm trong một mô phỏng nhiều client bằng cách chọn ít nhất hai nhân vật trong một bài thử nghiệm Server & Clients từ mezzanine.

Tùy chọn Server & Clients trong menu thả xuống các chế độ thử nghiệm của mezzanine trong Studio.

Một ví dụ khác về sự kiện Players.PlayerAdded:Connect là trong ServerScriptServicePlayerStateHandler. Giống như trong ví dụ trước, PlayerStateHandler ngay lập tức kiểm tra xem có một nhân vật hay không. Nếu người chơi không ở trong sảnh, script đặt một thuộc tính của người chơi thành trạng thái SelectingBlaster, trạng thái ban đầu cho một vòng mà trong đó người chơi có thể chọn từ một trong hai loại blaster khác nhau sau khi spawn vào đấu trường. Trạng thái này cũng bao gồm một trường lực ngăn chặn người chơi bị sát thương trong khi họ đang thực hiện lựa chọn của mình.

PlayerStateHandler
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)

Một biến cụ thể trong PlayerStateHandler đáng được thảo luận: attributeChangedConnectionByPlayer. Bảng này lưu trữ tất cả người chơi và Connections của họ đến GetAttributeChangedSignal. Lý do lưu trữ kết nối này trong một bảng là để PlayerStateHandler có thể ngắt kết nối nó khi người chơi rời khỏi trò chơi. Quá trình này phục vụ như một loại quản lý bộ nhớ để ngăn số lượng kết nối ngày càng tăng theo thời gian.

PlayerStateHandler
local attributeChangedConnectionByPlayer = {}
local function onPlayerAdded(player: Player)
-- Xử lý tất cả các cập nhật trong tương lai đến trạng thái người chơi
attributeChangedConnectionByPlayer[player] = player
:GetAttributeChangedSignal(PlayerAttribute.playerState)
:Connect(function()
local newPlayerState = player:GetAttribute(PlayerAttribute.playerState)
onPlayerStateChanged(player, newPlayerState)
end)
end
-- Ngắt kết nối khỏi kết nối thay đổi thuộc tính khi người chơi rời
local function onPlayerRemoving(player: Player)
if attributeChangedConnectionByPlayer[player] then
attributeChangedConnectionByPlayer[player]:Disconnect()
attributeChangedConnectionByPlayer[player] = nil
end
end

Bạn có thể thấy rằng cả hai hàm kết nối trong onPlayerAdded() đều gọi onPlayerStateChanged(). Trong thiết lập ban đầu sau khi một người chơi được sắp xếp vào một đội, onPlayerAdded() đặt PlayerState thành SelectingBlaster, vì vậy câu lệnh if đầu tiên đánh giá là false và vô hiệu hóa BlasterState. Trong phần Triển khai blaster sau của hướng dẫn, bạn sẽ tìm hiểu thêm chi tiết về quy trình này.

PlayerStateHandler
local function onPlayerStateChanged(player: Player, newPlayerState: string)
-- Trạng thái blaster là 'Ready' chỉ khi trạng thái người chơi là 'Playing'
local newBlasterState = if newPlayerState == PlayerState.Playing then BlasterState.Ready else BlasterState.Disabled
-- Lên lịch logic xóa trường lực khi người chơi bắt đầu chơi
if newPlayerState == PlayerState.Playing then
scheduleDestroyForceField(player)
end
player:SetAttribute(PlayerAttribute.blasterStateServer, newBlasterState)
end

Nếu bạn thêm các điểm dừng hoặc thậm chí chỉ một câu lệnh print(), bạn có thể thấy rằng onPlayerStateChanged() được gọi thường xuyên trong suốt trò chơi: chẳng hạn như trong thiết lập ban đầu của một vòng, để tự đặt mình vào đường dẫn mã chính, sau khi người chơi chọn một blaster, và khi người chơi trở lại sảnh, hoặc vị trí spawn Neutral. Hơn nữa, sau khi người chơi chọn một blaster, ServerScriptServiceBlasterSelectedHandler đặt PlayerState thành Playing, và PlayerStateHandler cuối cùng có thể xóa trường lực bằng cách gọi scheduleDestroyForceField().

Tùy chỉnh trường lực

Thay vì sử dụng một triển khai tùy chỉnh, trò chơi laser tag mẫu sử dụng lớp ForceField tích hợp sẵn của Studio để ngăn chặn người chơi bị sát thương trong khi họ đang chọn blaster của mình. Điều này đảm bảo rằng yêu cầu duy nhất để người chơi spawn với một trường lực là bao gồm các vị trí spawn với thuộc tính SpawnLocation.Duration lớn hơn 0. Mẫu sử dụng một giá trị tùy ý là 9,999 để kích hoạt các trường lực, sau đó xử lý thời gian thực tế một cách lập trình trong ReplicatedStorageForceFieldClientVisuals.

Tương tự như setupHumanoidAsync, hầu hết các dòng trong ForceFieldClientVisuals là tùy chọn. Ví dụ, nếu bạn bình luận nội dung của hàm như script sau đây, trò chơi sẽ sử dụng trường lực lấp lánh mặc định thay vì script hình lục giác trong StarterGuiForceFieldGui.

Commenting Out Properties in ForceFieldClientVisuals
local function onCharacterAddedAsync(character: Model)
-- local forceField = character:WaitForChild("ForceField", 3)
-- if not forceField then
-- return
-- end
-- forceField.Visible = false
-- localPlayer.PlayerGui:WaitForChild("ForceFieldGui").Enabled = true
-- forceField.Destroying:Wait()
-- localPlayer.PlayerGui.ForceFieldGui.Enabled = false
end

Bởi vì trường lực tùy chỉnh là một GUI thay vì một ParticleEmitter mới, script ForceFieldClientVisuals chỉ ảnh hưởng đến hình ảnh trong chế độ xem thứ nhất cho mỗi người chơi, không ảnh hưởng đến hình ảnh trong chế độ xem thứ ba khi người chơi nhìn vào người chơi khác. Hình ảnh trong chế độ xem thứ ba giữ nguyên diện mạo mặc định của Roblox. Để biết thêm thông tin về việc sửa đổi trường lực, hãy xem ForceField.Visible.

Hình ảnh trường lực trong chế độ xem thứ nhất bao gồm một lưới hình lục giác tương lai trên viền màn hình.
Hình ảnh trường lực trong chế độ xem thứ nhất
Hình ảnh trường lực trong chế độ xem thứ ba bao gồm một quả cầu lấp lánh màu xanh quanh người chơi đang spawn vào trò chơi.
Hình ảnh trường lực trong chế độ xem thứ ba

Trường lực rất hữu ích vì chúng cung cấp cho người chơi đủ thời gian giữa việc spawn và respawn mà không cần lo lắng về những người chơi đối thủ, nhưng cuối cùng chúng cần biến mất để gameplay laser tag chính diễn ra. Script xử lý việc xóa trường lực nằm trong ReplicatedStoragescheduleDestroyForceField, và nó kiểm tra ba điều kiện độc đáo:

  • Sau khi người chơi chọn một blaster, trường lực cần tồn tại đủ lâu để cho phép người chơi làm quen với môi trường xung quanh.
  • Trong thời gian làm quen này, trường lực không thể là một lợi thế, vì vậy chúng cần biến mất ngay khi một người chơi bắn blaster của họ.
  • Trường lực cần biến mất khi người chơi đặt lại nhân vật của họ, hoặc trước khi bắn hoặc trước khi trường lực hết thời gian.

Mỗi trong số các kiểm tra này trong script scheduleDestroyForceField gọi endForceField() cho các điều kiện này.

scheduleDestroyForceField
-- Kết thúc trường lực nếu người chơi bắn
local blasterStateAttribute = getBlasterStateAttribute()
attributeChangedConnection = player:GetAttributeChangedSignal(blasterStateAttribute):Connect(function()
local currentBlasterState = player:GetAttribute(blasterStateAttribute)
if currentBlasterState == BlasterState.Blasting then
endForceField()
end
end)
-- Kết thúc trường lực nếu người chơi đặt lại
characterRespawnedConnection = player.CharacterRemoving:Connect(endForceField)
-- Kết thúc trường lực sau 8 giây
task.delay(MAX_FORCE_FIELD_TIME, endForceField)

endForceField() bao gồm một câu lệnh if có vẻ kỳ lạ xung quanh boolean forceFieldEnded. Bởi vì các kiểm tra chạy tuần tự, script có thể gọi hàm endForceField() hai hoặc thậm chí ba lần. Boolean forceFieldEnded đảm bảo rằng hàm chỉ cố gắng xóa một trường lực một lần.

scheduleDestroyForceField
local function endForceField()
if forceFieldEnded then
return
end
forceFieldEnded = true
attributeChangedConnection:Disconnect()
characterRespawnedConnection:Disconnect()
destroyForceField(player)
end

Xử lý trạng thái client

Trong khi phần lớn của phần này tập trung vào ServerScriptServicePlayerStateHandler, có một script khác cùng tên trong ReplicatedStorage. Lý do cho sự phân chia này là kiến trúc client-server:

  • Client cần hiểu thông tin trạng thái người chơi để có thể phản hồi một cách thích hợp trong thời gian thực, chẳng hạn như hiển thị các yếu tố giao diện người dùng đúng, hoặc cho phép người chơi di chuyển và bắn.

  • Server cần tất cả thông tin này để có thể ngăn chặn các hành vi gian lận. Ví dụ, server cũng cần trạng thái người chơi để thực hiện các hành động như spawn và trang bị nhân vật, vô hiệu hóa trường lực, và hiển thị bảng điểm. Đây là lý do tại sao script này nằm trong ReplicatedStorage và không phải là một vị trí hoàn toàn phía client.

Để xem logic cốt lõi này, hãy xem script sau trong ReplicatedStoragePlayerStateHandler xác minh trạng thái hiện tại của người dùng, sau đó gọi hàm thích hợp xử lý các hành động tương ứng cho trạng thái đó.

PlayerStateHandler
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

Tất cả các phản hồi sự kiện được nhóm lại một cách hợp lý trong script này vì chúng yêu cầu hành vi tương tự về việc kích hoạt hoặc vô hiệu hóa điều khiển của người chơi, di chuyển camera, và lớp UI nào là hiển thị. Ví dụ, trong quá trình chọn blaster, người chơi cần vừa không thể bị tổn thương vừa không thể di chuyển. Server đã xử lý trường lực, nhưng client xử lý việc di chuyển. Để minh họa, nếu bạn kiểm tra logic cho hàm onSelectingBlaster(), bạn có thể thấy rằng client vô hiệu hóa việc di chuyển của người chơi trong khi họ đang chọn một blaster.

PlayerStateHandler
local function onSelectingBlaster()
togglePlayerCamera(true)
togglePlayerMovement(false)
setGuiExclusivelyEnabled(playerGui.PickABlasterGui)
localPlayer:SetAttribute(PlayerAttribute.blasterStateClient, BlasterState.Disabled)
end

Hàm onPlaying() cũng tương tự như vậy. Nó kích hoạt việc di chuyển, chuyển sang hiển thị chính (HUD), kích hoạt blaster, và gọi cùng một hàm trường lực như server.

PlayerStateHandler
local function onPlaying()
togglePlayerMovement(true)
setGuiExclusivelyEnabled(playerGui.HUDGui)
localPlayer:SetAttribute(PlayerAttribute.blasterStateClient, BlasterState.Ready)
scheduleDestroyForceField()
end

Respawn các nhân vật

Trò chơi laser tag mẫu xử lý việc respawn nhân vật trở lại vào một vòng thông qua trạng thái onTaggedOut() trong ReplicatedStoragePlayerStateHandler. Giống như trạng thái onSelectingBlaster()onPlaying(), onTaggedOut() kích hoạt hành vi độc đáo theo các thay đổi của thuộc tính playerState. Cụ thể, nó vô hiệu hóa việc di chuyển của người chơi, hiển thị UI respawn, và vô hiệu hóa blaster.

PlayerStateHandler
local function onTaggedOut()
-- Vô hiệu hóa điều khiển khi bị loại
togglePlayerMovement(false)
togglePlayerCamera(false)
setGuiExclusivelyEnabled(playerGui.OutStateGui)
-- Vô hiệu hóa blaster khi bị loại
localPlayer:SetAttribute(PlayerAttribute.blasterStateClient, BlasterState.Disabled)
end

Nếu bạn muốn kiểm tra hành vi này, bạn có thể nhấn Esc, điều hướng đến tab Cài đặt, sau đó nhấp vào nút Đặt lại Nhân vật. Lưu ý rằng khi bạn kích hoạt màn hình respawn, bạn không thể di chuyển, xoay camera, hoặc bắn blaster của mình.

Menu cài đặt của Roblox với nút Đặt lại Nhân vật được làm nổi bật.
Nút Đặt lại Nhân vật
Màn hình respawn hiển thị khi một người chơi respawn trở lại vòng chơi.
Màn hình Respawn

Điều quan trọng cần lưu ý là script này không thực sự respawn các nhân vật, nó chỉ ngăn họ hành động và cung cấp phản hồi hình ảnh cho người chơi rằng server đang respawn các nhân vật của họ. Để minh họa, nếu bạn kiểm tra ServerScriptServiceSetupHumanoidsetupHumanoidAsynconHumanoidDied, script đặt PlayerState thành TaggedOut (về cơ bản thông báo cho ReplicatedStoragePlayerStateHandler), và thêm một số chỉ báo hình ảnh. Logic thực tế của việc respawn là một hành vi tích hợp sẵn của Roblox.

Khi người chơi respawn trở lại vào vòng chơi, họ respawn tại vị trí spawn của đội mình theo thuộc tính SpawnLocation.TeamColor. Để tùy chỉnh thời gian respawn, bạn có thể thêm dòng sau vào đầu SetupHumanoid. Để tìm hiểu thêm về kỹ thuật này, hãy xem Players.RespawnTime.

SetupHumanoid
local Players = game:GetService("Players")
Players.RespawnTime = 10 -- dòng mới, tính bằng giây

Thiết lập linh tinh

Như một phần của thiết lập ban đầu, trò chơi laser tag mẫu cũng thực hiện một số bước nhỏ nhưng quan trọng:

  • Trò chơi bao gồm một script trống có tên StarterPlayerStarterCharacterScriptsHealth mà vô hiệu hóa việc hồi phục sức khỏe mặc định của Roblox. Để giải thích về hành vi của thuộc tính này, hãy xem Humanoid.Health.

  • Trò chơi sử dụng camera chế độ xem thứ nhất bằng cách đặt thuộc tính StarterPlayer.CameraMode.LockFirstPerson. Lưu ý rằng nếu bạn muốn cho phép người dùng thay đổi giữa camera chế độ xem thứ nhất và thứ ba, bạn phải thay đổi thuộc tính này một cách lập trình thay vì chỉ đặt nó một lần trong Studio, và sửa đổi các điều khiển và UI để bù đắp cho sự thay đổi trong góc nhìn.

  • Trò chơi sử dụng bảng điểm tích hợp sẵn của Roblox với đơn vị "điểm", mà người chơi kiếm được mỗi khi họ tag một người chơi khác ra ngoài. Bạn có thể thấy cấu hình trong ServerScriptServiceSetupLeaderboard, nhưng Bảng điểm trong trò chơi cung cấp một cái nhìn tổng quan đầy đủ. Lưu ý rằng onPlayerTagged thêm điểm vào bảng điểm, mà bạn sẽ tìm hiểu trong Thêm vòngPhát hiện cú đánh.

Bây giờ người chơi có thể spawn, chọn một blaster, và nhắm từ góc nhìn chế độ xem thứ nhất, phần tiếp theo sẽ dạy bạn về các script đứng sau việc tạo gameplay theo vòng.

©2026 Roblox Corporation. Roblox, logo Roblox và Powering Imagination là các nhãn hiệu đã đăng ký và chưa đăng ký của chúng tôi tại Hoa Kỳ và các quốc gia khác.