Tạo và hồi sinh

*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.

Tạo là quá trình tạo một đối tượng hoặc nhân vật trong một trải nghiệm, và tái sinh là quá trình thêm một đối tượng hoặc nhân vật trở lại một trải nghiệm sau khi họ gặp điều kiện loại bỏ, chẳng hạn như sức khỏe của một nhân vật giảm xuống 0 hoặc rơi khỏi bản đồ.Cả hai quá trình đều quan trọng vì chúng đảm bảo người chơi có thể tham gia vào trải nghiệm 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ải nghiệm thẻ laser mẫu như một tham khảo, phần này của hướng dẫn 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 sinh sản và tái sinh, bao gồm hướng dẫn lập trình về:

  • Tùy chỉnh vị trí sinh sản để người chơi chỉ có thể sinh sản vào khu vực sinh sản của đội họ.
  • Thêm người chơi mới và nhân vật của họ vào vòng khi họ tham gia trải nghiệm.
  • Tùy chỉnh lĩnh vực lực ngăn chặn sát thương khi người chơi sinh sản và hồi sinh.
  • Xử lý trạng thái khách hàng để trò chơi hoạt động đúng cách vào thời điểm thích hợp.
  • Hồi sinh các nhân vật sau khi chúng bị loại khỏi vòng.
  • Thực hiện các hành động nhỏ, phân tán không quan trọng đối với việc đặt các tham số gameplay và 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 tất cả từ đầu khi tạo ra một trải nghiệm, 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à xác định các hệ thống cần có triển khai tùy chỉnh phù hợp với tầm nhìn của bạn.Sau khi hoàn thành phần này, bạn sẽ học cách thực hiện trò chơi dựa trên vòng theo dõi điểm, theo dõi tình trạng người chơi và hiển thị kết quả vòng.

Tùy chỉnh vị trí sinh sản

Nếu bạn thử nghiệm trải nghiệm ngay bây giờ, tất cả người chơi sẽ ngẫu nhiên xuất hiện ở bất kỳ đối tượng SpawnLocation nào trong khu vực sinh sản của đội xanh lá, hoặc đối tượng SpawnLocation trong khu vực sinh sản của đội hồng.Điều này trình bày một vấn đề chơi game mà các người chơi có thể thẻ cho nhau trong mỗi khu vực sinh sản ngay khi trường lực của đối thủ biến mất.

Để chống lại vấn đề này, kinh nghiệm thẻ laser mẫu cấu hình cả hai vị trí sinh xuất với một Neutral bằng 0 để hạn chế các người chơi của đối thủ không sinh ra ở khu vực sinh xuất sai, và một TeamColor``Class.Team.Color giá trị tương ứng từ Gán màu đội trong phần trước của hướng dẫn:

  • TeamASpawn – Vị trí sinh sản trong khu vực sinh sản của đội xanh lá với một TeamColor được đặt thành Mint .
  • TeamBSpawn – Vị trí sinh sản trong khu vực sinh sản của đội hồng với một TeamColor được đặt thành Hoa hồng hồng .

TeamASpawn
>

TeamBSpawn
>

Khi một người chơi tham gia vào trải nghiệm, ServerScriptService > Gameplay > Vòng > spawnPlayersInMap kiểm tra để xem có bao nhiêu người chơi đã có trong mỗi đội, sau đó trả lại đội với số lượng người chơi ít nhất.

spawnPlayersInMap Trong bản đồ

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

Khi nó biết được đội với số lượng người chơi ít nhất, nó sắp xếp người chơi vào đội đó, đặt tính năng của họ thành sai để người chơi chỉ có thể sinh sản và tái sinh tại vị trí sinh sản của đội, sau đó đặt của họ thành , mà bạn sẽ học thêm về sau trong hướng dẫn.

spawnPlayersInMap Trong bản đồ

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 Không gian làm việc > Thế giới > Bản đồ > Xuất hiện , bạn có thể thấy rằng có thêm một vị trí xuất hiện trên bản đồ: NeutralSpawn .Vị trí spawn này là duy nhất so với các vị trí khác bởi vì nó không có một bộ thuộc tính TeamColor được đặt cho một trong hai đội trong trải nghiệm; thay vào đó, vị trí spawn này có một bộ thuộc tính Neutral thay đổi tùy thuộc vào việc liệu có bắt đầu một vòng hay không.

Ví dụ, nếu vòng đấu đang hoạt động, thuộc tính Neutral sẽ được đặt thành false để spawnPlayersInMap có thể sắp xếp người chơi thành các đội và phát họ ra sân.Tuy nhiên, nếu vòng 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, bộ đặt tính năng Neutral sẽ được đặt thành true để người chơi có thể sinh ra ở đó bất kể tình trạng tháiđội của họ.Quá trình này là những gì làm cho vị trí spawn Trung lập trở thành một sảnh chức năng.

Trung lập

Để minh họa, nếu bạn kiểm tra ServerScriptService > Gameplay > Vòng > SpawnPlayersInLobby , chạy ở cuối một vòng, bạn có thể thấy rằng cho mỗi người chơi được chuyển vào bảng players: { Player } , kịch bản:

  • Đặ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 tái sinh trong sảnh khi một vòng không hoạt động, vì thuộc tính Neutral của địa điểm sinh sản cũng được đặt thành true .
  • Thay đổi PlayerState của họ thành InLobby để loại bỏ blaster và hình ảnh UI người chơi thứ nhất.

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

phát triển người chơi trong sảnh

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 kích hoạt bởi sự kiện, có nghĩa là các tập lệnh lắng nghe sự kiện từ một dịch vụ Roblox, sau đó gọi một chức năng trong phản hồi.Ví dụ, khi thêm người chơi mới vào trải nghiệm nhiều người chơ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ải nghiệm thẻ laser mẫu, sự kiện tương ứng là Players.PlayerAdded:Connect .

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

Studio's Find All window with the Players.PlayerAdded results highlighted.

Để minh họa, mở ServerScriptService > SetupHumanoid .Sự phân biệt giữa PlayerCharacter là chìa khóa để hiểu kịch bản này:

  • Một người chơi là một khách hàng kết nối, và một tính cách là một Humanoid.
  • Người chơi cần chọn một blaster và được thêm vào bảng xếp hạng. Nhân vật cần phát sinh và nhận được một blaster.

SetupHumanoid ngay lập tức kiểm tra xem người chơi có nhân vật (vừa tham gia) hay không (đang tái sinh).Sau khi tìm thấy một, nó gọi onCharacterAdded() , nhận mô hình Humanoid từ nhân vật, và chuyển nó cho ServerScriptService > SetupHumanoid > setupHumanoidAsync để tùy chỉnh.Sau khi đặt các giá trị này, thì kịch bản sẽ chờ đợi sức khỏe của nhân vật đạt đến không.Bạn sẽ học thêm về việc hồi sinh sau này trong phần hướng dẫn này.

thiết lập HumanoidAsync

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

Ghi chú quan trọng với kịch bản này là các thuộc tính hoàn toàn tùy chọn, có nghĩa là nếu bạn xóa sáu dòng đầu tiên của chức năng, trải nghiệm vẫn hoạt động bình thườ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 chơi game 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, hãy giảm giá trị của Humanoid.NameDisplayDistance .
  • Nếu bạn chỉ muốn sức khỏe của một nhân vật được hiển thị nếu nó thấp hơn 100%, hãy đặt Humanoid.HealthDisplayType thành Hiển thị khi bị hư hại .
  • Nếu bạn muốn các nhân vật phá vỡ khi sức khỏe của chúng đạt 0, hãy đặt Humanoid.BreakJointsOnDeath đến True .

Nếu bạn thay đổi các giá trị của các thuộc tính này, thì quan trọng phải thử nghiệm để bạn có thể xem ảnh hưởng của 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ôi trường nhiều người chơi bằng cách chọn ít nhất hai nhân vật trong phần Khách hàng và Máy chủ của tab Thử nghiệm .

Studio's Test tab with the the players dropdown highlighted. This setting needs to be at least two players to see the impact of your new settings.

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

Người xử lý trạng thái người chơi

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 chiến tranh cần thảo luận: attributeChangedConnectionByPlayer .Bảng này lưu trữ tất cả các người chơi và họ Connections đến GetAttributeChangedSignal .Lý do để lưu kết nối này trong một bảng là để PlayerStateHandler có thể thoát kết nối khi người chơi rời khỏi trải nghiệm.Quá trình này phục vụ như một loại quản lý bộ nhớ để ngăn chặn số lượng kết nối tăng lên theo thời gian.

Người xử lý trạng thái người chơi

local attributeChangedConnectionByPlayer = {}
local function onPlayerAdded(player: Player)
-- Xử lý tất cả các bản 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
-- Tách khỏi kết nối đã thay đổi khi người chơi rời khỏ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 chức năng kết nối trong onPlayerAdded() gọi onPlayerStateChanged() .Trong quá trình cài đặt ban đầu sau khi một người chơi sắp xếp thành một đội, onPlayerAdded() đặt PlayerState đến SelectingBlaster , vì vậy tuyên bố đầu tiên if đánh giá là sai và vô hiệu hóa BlasterState .Trong phần tiếp theo Thực hiện blaster của hướng dẫn, bạn sẽ học thêm chi tiết về quá trình này.

Người xử lý trạng thái người chơi

local function onPlayerStateChanged(player: Player, newPlayerState: string)
-- Tình trạng Blaster là 'Sẵn sàng' chỉ khi tình trạng người chơi là 'Chơi'
local newBlasterState = if newPlayerState == PlayerState.Playing then BlasterState.Ready else BlasterState.Disabled
-- Lên lịch logic trường lực phá hủy 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 điểm dừng hoặc thậm chí chỉ là một tuyên bố print() , bạn có thể thấy rằng onPlayerStateChanged() được gọi thường xuyên trong suốt trải nghiệm: chẳng hạn như trong quá trình thiết lập ban đầu của một vòng, để tự đặt mình trên con đường 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 địa điểm spawn Trung lập .Ngoài ra, sau khi người chơi chọn một blaster, ServerScriptService > BlasterSelectedHandler đặt PlayerState vào Playing , và PlayerStateHandler cuối cùng có thể loại bỏ trường lực bằng cách gọi scheduleDestroyForceField() .

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

Thay vì sử dụng thực hiện tùy chỉnh, trải nghiệm nhãn laser mẫu sử dụng lớp được xây dựng sẵn của Studio ForceField để ngăn chặn người chơi bị thiệt hại trong khi họ chọn blaster của họ.Điều này đảm bảo rằng yêu cầu duy nhất đối với người chơi để sinh ra với một trường lực là bao gồm các địa điểm sinh ra với một thuộc tính SpawnLocation.Duration có giá trị lớn hơn 0.Ví dụ sử dụng một giá trị ngẫu nhiên là 9,999 để bật các trường lực, sau đó xử lý thời gian thực một cách lập trường trong ReplicatedStorage > ForceFieldClientVisuals .

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 chức năng giống như kịch bản sau, trải nghiệm sử dụng trường lực tia lửa mặc định thay vì kịch bản lục giác trong StarterGui > ForceFieldGui .

Bình luận các thuộc tính trong ForceFieldClientVisuals

local function onCharacterAddedAsync(character: Model)
-- forceField địa phương = nhân vật:WaitForChild("ForceField", 3)
-- nếu không phải forceField thì
-- trả lại
-- kết thúc
-- forceField.Visible = giả mạo
-- localPlayer.PlayerGui:WaitForChild("ForceFieldGui").Enabled = true
-- forceField.Destroying: Đợi()
-- localPlayer.PlayerGui.ForceFieldGui.Enabled = giả mạo
end

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

First-person force field visuals include a futuristic hexagonal grid on the perimeter of the screen.

Hình ảnh trường lực người thứ nhất
>

Third-person force field visuals include a blue sparkling orb around the player spawning into the experience.

Hình ảnh trường lực người thứ ba
>

Các trường lực hữu ích bởi vì chúng cung cấp cho người chơi đủ thời gian để giữa việc sinh sản và hồi sinh mà không cần phải lo lắng về các người chơi địch, nhưng cuối cùng họ cần phải biến mất để chơi trò trải nghiệm trò chơilaser chính chủ chính chủ chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chính chínTập lệnh xử lý loại bỏ trường lực có trong ReplicatedStorage > scheduleDestroyForceField , và nó kiểm tra ba điều kiện duy nhất:

  • Sau khi người chơi chọn một blaster, các trường lực cần phải tồn tại đủ lâu để cho phép người chơi thích ứng với môi trường xung quanh.
  • Trong thời gian thích ứng này, các trường lực không thể là một lợi thế, vì vậy chúng cần phải biến mất ngay lúc một người chơi phóng nổ máy phóng của họ.
  • Các 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ọ trước khi nổ hoặc trước khi trường lực hết hạn.

Mỗi lần kiểm tra trong lời gọi scheduleDestroyForceField kịch bản endForceField() cho các điều kiện này.

lịch phá hủyForceField

-- Kết thúc trường lực nếu người chơi nổ tung
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 tuyên bố dường như kỳ lạ if xung quanh forceFieldEnded boolean.Bởi vì các kiểm tra chạy tuần tự, thì kịch bản có thể gọi chức năng endForceField() hai hoặc thậm chí ba lần.Các forceFieldEnded boolean đảm bảo rằng chức năng chỉ cố gắng phá hủy một trường lực một lần.

lịch phá hủyForceField

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

Xử lý trạng thái khách hàng

Trong khi phần lớn của phần này tập trung vào ServerScriptService > PlayerStateHandler , có một kịch bản khác cùng tên trong ReplicatedStorage .Lý do cho việc chia tách là kiến trúc client-server:

  • Khách hàng cần hiểu thông tin trạng thái của người chơi để có thể phản hồi thích hợp theo thời gian thực, chẳng hạn như hiển thị các thành phần giao diện người dùng phù hợp, hoặc cho phép người chơi di chuyển và nổ súng.

  • Máy chủ cần tất cả thông tin tương tự này để có thể ngăn chặn các lỗ hổng.Ví dụ, máy chủ cũng cần trạng thái người chơi để thực hiện các hành động như tạo và trang bị nhân vật, vô hiệu hóa trường lực, và hiển thị bảng xếp hạng.Đây là lý do tại sao kịch bản này nằm trong ReplicatedStorage và không phải là vị trí hoàn toàn bên khách.

Để xem logic nền tảng này, xem kịch bản sau trong ReplicatedStorage > PlayerStateHandler > để xác minh tình trạng hiện tại của người dùng, sau đó gọi chức năng phù hợp xử lý các hành động tương ứng cho tình trạng đó.

Người xử lý trạng thái người chơi

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 xếp theo nhóm logic trong kịch bản này vì chúng yêu cầu hành vi tương tự của việc bật hoặc tắt điều khiển người chơi, di chuyển máy ảnh và lớp UI nào có thể nhìn thấy.Ví dụ, trong quá trình lựa chọn blaster, người chơi cần phải cả invulnerable và không thể di chuyển.Máy chủ đã xử lý trường lực, nhưng khách hàng xử lý chuyển động.Để minh họa, nếu bạn kiểm tra logic cho chức năng onSelectingBlaster() , bạn có thể thấy rằng khách hàng vô hiệu hóa chuyển động của người chơi trong khi họ đang chọn một blaster.

Người xử lý trạng thái người chơi

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

Chức năng onPlaying() cũng tương tự dễ dàng.Nó bật khả năng di chuyển, chuyển đổi sang màn hình hiển thị chính (HUD), bật máy phóng và gọi chức năng trường lực tương tự như máy chủ.

Người xử lý trạng thái người chơi

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

Hồi sinh nhân vật

Trải nghiệm thẻ laser mẫu xử lý việc hồi sinh nhân vật trở lại vòng qua trạng thái onTaggedOut() trong ReplicatedStorage > PlayerStateHandler .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 di chuyển của người chơi, trình bày giao diện người dùng tái sinh, và vô hiệu hóa blaster.

Người xử lý trạng thái người chơi

local function onTaggedOut()
-- Vô hiệu hóa điều khiển khi được gắn thẻ
togglePlayerMovement(false)
togglePlayerCamera(false)
setGuiExclusivelyEnabled(playerGui.OutStateGui)
-- Vô hiệu hóa blaster khi được gắn thẻ
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 , di chuyển đến tab Cài đặt , sau đó nhấp vào nút Reset Character .Lưu ý rằng khi bạn kích hoạt màn hình tái sinh, bạn không thể di chuyển, xoay camera hoặc nổ tung blaster của bạn.

Roblox's settings menu with the Reset Character button highlighted.
Nút Reset Nhân Vật
The respawn screen displays as a player respawns back into the round.
Màn hình tái sinh

Quan trọng là phải lưu ý rằng kịch bản này thực sự không hồi sinh các nhân vật, nó chỉ ngăn chúng không hành động và cung cấp phản hồi hình ảnh cho người chơi mà máy chủ respawn đang hồi sinh các nhân vật của họ.Để minh họa, nếu bạn kiểm tra ServerScriptService > SetupHumanoid > setupHumanoidAsync > onHumanoidDied , kịch bản sẽ thiết lập PlayerState đến TaggedOut (về cơ bản là thông báo ReplicatedStorage > PlayerStateHandler ), và thêm một số chỉ số hình ảnh.Logic thực sự của việc tái sinh là một hành vi Roblox được tích hợp.

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

Cài đặtHumanoid

local Players = game:GetService("Players")
Players.RespawnTime = 10 -- new line, in seconds

Cài đặt khác

Như một phần của quá trình cài đặt ban đầu, kinh nghiệm thẻ laser mẫu cũng thực hiện một số bước nhỏ, nhưng quan trọng:

  • Trải nghiệm bao gồm một kịch bản trống có tên là StarterPlayer > StarterCharacterScripts > Sức khỏe vô hiệu hóa sự phục hồi sức khỏe mặc định của Roblox.Để giải thích hành vi của thuộc tính này, xem Humanoid.Health .

  • Trải nghiệm sử dụng một máy ảnh người thứ nhất bằng cách thiết lập 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 thứ nhất và thứ ba, bạn phải thay đổi thuộc tính theo 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à giao diện người dùng để bù lại sự thay đổi về quan điểm.

  • Trải nghiệm sử dụng bảng xếp hạng Roblox tích hợp với đơn vị "điểm", mà người chơi kiếm được mỗi khi họ nhãn một người chơi khác.Bạn có thể xem cấu hình trong ServerScriptService > Thiết lập Bảng xếp hạng , nhưng Trong-Trải nghiệm Bảng xếp hạng cung cấp một tổng quát đầy đủ.Lưu ý rằng onPlayerTagged thêm điểm vào bảng xếp hạng, mà bạn sẽ học về trong Thêm vòngPhát hiện đánh .

Bây giờ khi người chơi có thể sinh sản, hãy chọn một blaster, và nhắm nó từ một góc nhìn thứ nhất, phần tiếp theo dạy bạn về các kịch bản đứng sau việc tạo trải nghiệm trò chơitheo vòng.