스폰 및 리스폰

*이 콘텐츠는 AI(베타)를 사용해 번역되었으며, 오류가 있을 수 있습니다. 이 페이지를 영어로 보려면 여기를 클릭하세요.

생성 은 경험에서 개체나 캐릭터를 생성하는 프로세스이고, 재생성 은 캐릭터의 체력이 0에 도달하거나 맵에서 떨어지는 등의 제거 조건을 충족한 후 경험에 개체나 캐릭터를 다시 추가하는 프로세스입니다.둘 다 중요하며, 플레이어가 경험에 참여할 수 있고 스킬을 향상시키기 위해 계속 플레이할 수 있기 때문입니다.

참조로 샘플 레이저 태그 경험을 사용하여 이 자습서의 이 섹션은 Roblox의 기본 기능을 사용하고 사용자 정의하여 스폰과 리스폰을 처리하는 방법을 가르쳐줍니다. 스크립트 가이드에는 다음이 포함됩니다.

  • 플레이어가 팀의 스폰 영역에만 스폰할 수 있도록 스폰 위치 구성.
  • 경험에 참여하는 새로운 플레이어와 그들의 캐릭터를 라운드에 추가하여 경험에 참여합니다.
  • 플레이어가 스폰하고 리스폰할 때 손상을 방지하는 포스필드 사용자 정의.
  • 적절한 시기에 게임플레이가 올바르게 작동하도록 클라이언트 상태 처리.
  • 라운드가 종료된 후 캐릭터를 재생성하는 중.
  • 게임플레이 및 캐릭터 매개변수 설정에 중요한 작은 다양한 작업을 수행합니다.

이 섹션에는 많은 스크립팅 콘텐츠가 포함되어 있지만, 경험을 만들 때 모든 것을 처음부터 작성하는 대신 기존 구성 요소를 활용하고, 신속하게 반복하고, 어떤 시스템이 비전에 맞게 사용자 지정 구현이 필요한지 파악하도록 권장합니다.이 섹션을 완료하면 포인트를 추적하고 플레이어 상태를 모니터링하며 라운드 결과를 표시하는 라운드 기반 게임플레이를 구현하는 방법을 배웁니다.

스폰 위치 구성

지금 경험을 플레이테스트하면 모든 플레이어가 녹색 팀의 스폰 영역이나 핑크 팀의 스폰 영역에서 무작위로 생성됩니다.이것은 플레이어가 상대의 포스필드가 사라질 즉시 각 스폰 존 내에서 서로를 태그할 수 있는 게임플레이 문제를 제시합니다.

이 문제를 해결하기 위해 샘플 레이저 태그 경험은 스폰 위치를 모두 속성 집합을 사용하여 false 로 설정하여 상대 팀의 플레이어가 잘못된 스폰 영역에서 스폰하는 것을 제한하고, 자습서의 이전 섹션에서 속성 집합을 해당 값으로 설정하여 Assign Team Colors 에서 반대 팀의 플레이어가 스폰하는 것을 제한합니다:

  • TeamASpawn – 초록 팀의 스폰 영역에서 속성 TeamColor민트 로 설정된 스폰 위치.
  • TeamBSpawn – 핑크 팀의 스폰 영역에서 속성이 카네이션 핑크 로 설정된 스폰 위치.

팀ASpawn
>

팀BSpawn
>

플레이어가 경험에 참여하면 ServerScriptService > 게임플레이 > 라운드 > 맵에서 플레이어 생성 에서 각 팀에 이미 있는 플레이어 수를 확인한 다음 가장 적은 수의 플레이어가 있는 팀을 반환합니다.

맵에서 플레이어 생성 spawnPlayersInMap

local function getSmallestTeam(): Team
local teams = Teams:GetTeams()
-- 가장 작은 순으로 팀 정렬 변경 팀 순서 변경 팀 순서 변경 팀 순서 변경 팀 순서 변경 팀 순서 변경 팀 순서 변경 팀 순서 변경 팀 순서 변경 팀 순서 변경 팀 순서 변경 팀 순서 변경 팀 순서 변경 팀 순서 변경 팀 순서 변경 팀 순서 변경 팀 순서 변경 팀 순서 변경 팀 순서 변경 팀 순서 변경 팀 순서 변경 팀 순서 변경 팀 순서 변경 팀 순서 변경 팀 순서 변경 팀 순서 변경 팀 순서 변경 팀 순서 변경 팀 순서 변경 팀 순서 변경 팀 순서 변경 팀 순서 변경 팀 순서 변경 팀 순서 변경 팀 순서 변경 팀 순서 변경 팀 순서 변경 팀 순서 변경 팀 순서 변경 팀 순서 변경 팀 순서 변경 팀 순서 변경 팀 순서 변경 팀 순서 변경 팀 순서 변경 팀 순서 변경 팀 순서 변경 팀 순서 변경 팀 순서 변경 팀 순서 변경 팀 순서 변경 팀 순서 변경 팀 순서 변경 팀 순서 변경 팀 순서 변경 팀 순서 변경 팀 순서 변경 팀 순서 변경 팀 순서 변경 팀 순서 변경 팀 순서 변경 팀 순서 변경 팀 순서 변경 팀 순서 변경 팀 순서 변경 팀 순서 변경 팀 순서 변경 팀 순서 변경 팀 순서 변경 팀 순서 변경 팀 순서 변경 팀 순서 변경 팀 순서 변경 팀 순서 변경 팀 순서 변경 팀 순서 변경 팀 순서 변경 팀 순서 변경 팀 순서 변경 팀 순서 변경 팀 순서 순서 변경 팀 순서 순서 변경 순서 순서 변경 순서 순서 변경 순서 순서 변경 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순서 순
table.sort(teams, function(teamA: Team, teamB: Team)
return #teamA:GetPlayers() < #teamB:GetPlayers()
end)
-- 가장 작은 팀 반환
return teams[1]
end

플레이어가 가장 적은 수의 플레이어가 있는 팀을 알게 되면, 해당 팀에 플레이어를 정렬하고, 플레이어의 Player.Neutral 속성을 false 로 설정하여 플레이어가 자신의 팀의 스폰 위치에만 스폰하고 재스폰할 수 있도록 합니다. 그런 다음 자습서에서 나중에 자세히 설명할 예정인 PlayerState을 플레이어의 SelectingBlaster로 설정합니다.

맵에서 플레이어 생성 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

작업 공간을 조사 > 세계 > > 스폰 > 중립 스폰 > 에서 하나 더 스폰 위치가 있는 것을 볼 수 있습니다.이 스폰 위치는 경험의 두 팀 중 하나에 설정된 TeamColor 속성이 없기 때문에 다른 것과 유일합니다; 대신, 이 스폰 위치에는 Neutral 속성이 있으며, 라운드가 활성인지 여부에 따라 변경됩니다.

예를 들어, 라운드가 활성화되어 있으면 Neutral 속성이 false 로 설정되므로 spawnPlayersInMap 에서 플레이어를 팀으로 정렬하고 아레나에 배포할 수 있습니다.그러나 라운드가 활성화되지 않은 경우, 예를 들어 한 라운드와 다음 라운드 사이의 시간, Neutral 속성이 true 로 설정되어 플레이어가 팀 상태에 관계없이 거기에서 스폰할 수 있습니다.이 프로세스는 중립 생성 위치를 기능적인 로비로 만드는 것입니다.

중립

쇼케이스를 보여주기 위해, ServerScriptService > 게임플레이 > 라운드 > 로비에서 플레이어 생성 > 을 검사하면, 라운드가 끝날 때 패스된 모든 플레이어에 대해 스크립트:

  • 그들의 Player.Neutral 속성을 true로 설정하여 자동으로 그들의 Player.Teamnil 로 재설정하고, 플레이어가 라운드가 활성화되지 않을 때 로비에서 재생할 수 있도록 스폰 위치의 Neutral 속성도 true 로 설정합니다.
  • 플레이어의 블래스터와 1인칭 UI 비주얼을 제거하기 위해 PlayerStateInLobby로 변경

중립 생성 영역과 각 라운드에 대한 기능에 대한 자세한 정보는 다음 섹션의 자습서에서 라운드 추가를 참조하십시오.

로비에서 플레이어 생성 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

새로운 플레이어 연결

Studio의 Luau 코드는 종종 이벤트 구동 방식이며, 즉 스크립트가 Roblox 서비스에서 이벤트를 수신한 다음 응답으로 함수를 호출합니다.예를 들어, 멀티플레이어 환경에 새로운 플레이어를 추가할 때, 플레이어가 성공적으로 연결하는 데 필요한 모든 것을 처리하는 이벤트가 있어야 합니다.샘플 레이저 태그 경험에서 해당 이벤트는 Players.PlayerAdded:Connect입니다.

Players.PlayerAdded:Connect는 경험의 여러 스크립트의 일부입니다.Ctrl/Cmd+Shift+F 단축키를 사용하고 검색하면 Players.PlayerAdded:Connect 결과는 경험의 초기 설정을 이해하는 데 좋은 출발점을 제공합니다.

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

시연하려면 ServerScriptService > Humanoid 설정 을 엽니다.PlayerCharacter 의 구분은 이 스크립트를 이해하는 데 중요합니다:

  • A 플레이어 는 연결된 클라이언트이고, A 캐릭터Humanoid입니다.
  • 플레이어는 블래스터를 선택하고 리더보드에 추가되어야 합니다. 캐릭터는 블래스터를 생성하고 받아야 합니다.

SetupHumanoid 플레이어가 캐릭터를 가지고 있는지(방금 참여했음) 또는 가지고 있지 않은지(재생중)를 즉시 확인합니다.하나를 찾으면 onCharacterAdded() 를 호출하고, 캐릭터에서 Humanoid 모델을 가져와 ServerScriptService > SetupHumanoid > setupHumanoidAsync 에 대한 사용자 지정을 위해 전달합니다.이러한 값을 설정한 후 스크립트는 캐릭터의 체력이 0에 도달할 때까지 대기합니다.이 자습서의 이 섹션에서 나중에 재생성에 대해 자세히 알아볼 수 있습니다.

설정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

이 스크립트와 함께 중요한 점은 속성이 완전히 선택적이라는 것입니다. 즉, 함수의 처음 6줄을 제거하면 경험이 여전히 제대로 작동한다는 것입니다.기능적인 요구 사항이 아니라, 각 속성을 통해 게임플레이 목표에 부합하는 디자인 결정을 내릴 수 있습니다.예를 들어:

이러한 속성의 값을 변경하는 경우 새 설정의 영향을 볼 수 있도록 플레이테스트하는 것이 중요합니다.테스트 탭의 클라이언트 및 서버 섹션에서 최소 두 개의 캐릭터를 선택하여 플레이어가 멀티플레이어 환경에서 경험하는 것을 다시 만들 수 있습니다.

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.

Players.PlayerAdded:Connect 이벤트의 또 다른 예는 ServerScriptService > PlayerStateHandler 에 있습니다.이전 예제와 마찬가지로 PlayerStateHandler 즉시 문자를 확인합니다.플레이어가 로비에 없으면 스크립트가 플레이어 특성을 SelectingBlaster 상태로 설정하여 플레이어가 생성 후 아레나에서 두 가지 다른 블래스터 유형 중 하나를 선택할 수 있는 라운드의 초기 상태를 설정합니다.이 상태에는 플레이어가 선택하는 동안 피해를 입지 않도록 하는 포스필드도 포함됩니다.

플레이어 상태 처리기

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)

PlayerStateHandler 전쟁에서 특정 변수 하나가 토론을 요구합니다: attributeChangedConnectionByPlayer .이 테이블에는 모든 플레이어와 그들의 ConnectionsGetAttributeChangedSignal에 저장됩니다.이 연결을 테이블에 저장하는 이유는 플레이어가 경험을 떠날 때 연결을 끊을 수 있도록 하기 위해서입니다.이 프로세스는 연결 수가 시간이 지남에 점점 증가하는 것을 방지하기 위한 종류의 메모리 관리 역할을 합니다.

플레이어 상태 처리기

local attributeChangedConnectionByPlayer = {}
local function onPlayerAdded(player: Player)
-- 플레이어 상태의 모든 향후 업데이트 처리
attributeChangedConnectionByPlayer[player] = player
:GetAttributeChangedSignal(PlayerAttribute.playerState)
:Connect(function()
local newPlayerState = player:GetAttribute(PlayerAttribute.playerState)
onPlayerStateChanged(player, newPlayerState)
end)
end
-- 플레이어가 떠날 때 특성의 변경된 연결에서 연결 해제
local function onPlayerRemoving(player: Player)
if attributeChangedConnectionByPlayer[player] then
attributeChangedConnectionByPlayer[player]:Disconnect()
attributeChangedConnectionByPlayer[player] = nil
end
end

연결된 함수 둘 다 호출 onPlayerAdded() 에서 onPlayerStateChanged() 를 볼 수 있습니다.플레이어가 팀으로 정렬된 후 초기 설정 중에, onPlayerAdded()PlayerStateSelectingBlaster 로 설정하여 첫 번째 if 문이 false로 평가되고 BlasterState 가 비활성화됩니다.튜토리얼의 나중 섹션 블래스터 구현에서 이 프로세스에 대한 자세한 내용을 배우게 됩니다.

플레이어 상태 처리기

local function onPlayerStateChanged(player: Player, newPlayerState: string)
-- 플레이어 상태가 '플레이'인 경우에만 블래스터 상태가 '준비'로 설정됩니다
local newBlasterState = if newPlayerState == PlayerState.Playing then BlasterState.Ready else BlasterState.Disabled
-- 플레이어가 플레이를 시작할 때 파괴 포스필드 논리 일정 예약
if newPlayerState == PlayerState.Playing then
scheduleDestroyForceField(player)
end
player:SetAttribute(PlayerAttribute.blasterStateServer, newBlasterState)
end

중단점이나 심지어 단지 문을 추가하면 경험 내내 자주 호출되는 것을 볼 수 있습니다: 라운드의 초기 설정 중, 주요 코드 경로에 자신을 설정하기 위해, 플레이어가 블래스터를 선택한 후, 플레이어가 로비로 돌아가거나, 중립 스폰 위치로 돌아가는 동안.또한, 플레이어가 블래스터를 선택한 후, ServerScriptService > 블래스터선택처리자PlayerStatePlaying 로 설정하고, PlayerStateHandler 마지막으로 포스필드를 제거할 수 있습니다, 즉 호출하여 scheduleDestroyForceField() .

포스필드 사용자 정의

사용자 지정 구현을 사용하는 대신, 샘플 레이저 태그 경험은 Studio의 기본 제공 클래스 ForceField를 사용하여 플레이어가 레이저를 선택하는 동안 피해를 입지 않도록 합니다.이렇게 하면 플레이어가 포스필드로 스폰하기 위한 유일한 요구 사항은 0보다 큰 SpawnLocation.Duration 속성이 있는 스폰 위치를 포함하는 것뿐입니다.샘플은 임의의 값 9,999를 사용하여 포스필드를 활성화한 다음 ReplicatedStorage > ForceFieldClientVisuals 에서 실제 기간 프로그래밍 방식으로 처리합니다.

setupHumanoidAsync 와 비슷하게, ForceFieldClientVisuals 의 대부분의 라인은 선택적입니다.예를 들어, 다음 스크립트와 같이 함수의 내용을 주석으로 처리하면 경험은 StarterGui > ForceFieldGui 에서 헥사곤 스크립트 대신 기본 반짝이는 포스필드를 사용합니다.

ForceFieldClientVisuals에서 속성 주석 달기

local function onCharacterAddedAsync(character: Model)
-- 로컬 포스필드 = 캐릭터:WaitForChild("ForceField", 3)
-- forceField가 아니면
-- 반환
-- 종료
-- forceField.Visible = false
-- 로컬플레이어.PlayerGui:WaitForChild("ForceFieldGui")가 활성화됨 = true
-- forceField.Destroying: 대기()
-- 로컬플레이어.PlayerGui.ForceFieldGui.Enabled = false
end

사용자 지정 포스필드가 새로운 대신 GUI이기 때문에, 스크립트는 각 플레이어의 1인칭 시각에만 영향을 주고, 플레이어가 다른 플레이어를 보면 3인칭 시각에는 영향을 주지 않습니다.세 번째 인격 시각은 기본 Roblox 모습유지합니다.포스 필드를 수정하는 자세한 정보는 ForceField.Visible에 참조하십시오.

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

1인칭 포스필드 시각화
>

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

세 번째 인물 포스필드 시각화
>

포스 필드는 플레이어에게 스폰과 리스폰 사이에 충분한 시간을 제공하므로 적의 플레이어를 걱정할 필요 없이 유용하지만, 결국 메인 레이저 태그 게임 플레이위해 사라져야 합니다.포스필드 제거를 처리하는 스크립트는 ReplicatedStorage > scheduleDestroyForceField 에 있으며, 세 가지 독특한 조건을 확인합니다:

  • 플레이어가 블래스터를 선택한 후, 필드가 충분히 지속되어 플레이어가 주변 환경에 적응할 수 있어야 합니다.
  • 이 적응 시간 동안 포스 필드는 장점이 될 수 없으므로 플레이어가 발사기를 발사하는 순간 사라져야 합니다.
  • 플레이어가 폭발하기 전에 또는 포스필드 시간이 끝나기 전에 캐릭터를 재설정할 때 포스필드가 사라져야 합니다.

각각의 이러한 검사는 scheduleDestroyForceField 스크립트 호출에서 이러한 조건에 대해 endForceField() 확인합니다.

일정DestroyForceField

-- 플레이어가 폭발하면 포스필드 종료
local blasterStateAttribute = getBlasterStateAttribute()
attributeChangedConnection = player:GetAttributeChangedSignal(blasterStateAttribute):Connect(function()
local currentBlasterState = player:GetAttribute(blasterStateAttribute)
if currentBlasterState == BlasterState.Blasting then
endForceField()
end
end)
-- 플레이어가 재설정하면 포스필드 종료
characterRespawnedConnection = player.CharacterRemoving:Connect(endForceField)
-- 8초 후 포스 필드 종료
task.delay(MAX_FORCE_FIELD_TIME, endForceField)

endForceField() 은 보기 이상한 if 문자열 주위에 있는 보이는 이상한 forceFieldEnded 불리언 문을 포함합니다.검사가 순차적으로 실행되기 때문에 스크립트는 endForceField() 함수를 두 번 또는 세 번 호출할 수 있습니다.forceFieldEnded 부울은 함수가 한 번만 포스필드를 파괴하려고 시도하도록 보장합니다.

일정DestroyForceField

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

클라이언트 상태 처리

이 섹션의 대부분은 ServerScriptService > PlayerStateHandler 에 초점을 맞추고 있지만, ReplicatedStorage 에는 동일한 이름의 다른 스크립트가 있습니다.분할의 이유는 클라이언트-서버 아키텍처입니다:

  • 클라이언트는 플레이어 상태 정보를 이해해야 하므로 적절하게 실시간으로 응답할 수 있습니다(예: 올바른 사용자 인터페이스 요소 표시 또는 플레이어의 이동 및 폭발 활성화).

  • 서버는 악용을 방지할 수 있도록 이 모든 정보가 필요합니다.예를 들어, 서버는 플레이어 상태를 필요로 하여 캐릭터 생성 및 장착, 포스 필드 비활성화, 리더보드 표시와 같은 작업을 수행합니다.이런 이유로 이 스크립트는 ReplicatedStorage 에 있고 순수히 클라이언트 측 위치가 아닙니다.

이 핵심 논리를 보려면 ReplicatedStorage > 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

모든 이벤트 응답은 플레이어 제어활성화 또는 비활성화, 카메라 이동 및 표시되는 UI 레이어와 유사한 동작을 요구하기 때문에 이 스크립트에서 논리적으로 그룹화됩니다.예를 들어, 블래스터 선택 중에 플레이어는 무적이면서 이동할 수 없어야 합니다.서버는 이미 포스 필드를 처리하지만 클라이언트는 이동을 처리합니다.보여주기 위해, onSelectingBlaster() 함수의 논리를 확인하면 클라이언트가 플레이어 이동을 비활성화하는 동안 블래스터를 선택하는 것을 볼 수 있습니다.

플레이어 상태 처리기

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

onPlaying() 함수도 마찬가지로 간단합니다.이를 통해 이동, 메인 헤드업 디스플레이(HUD)로의 전환, 블래스터 활성화 및 서버와 동일한 포스필드 함수 호출이 가능합니다.

플레이어 상태 처리기

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

캐릭터 재생성 Respawn characters

샘플 레이저 태그 경험은 재생성된 캐릭터를 onTaggedOut() 상태를 통해 ReplicatedStorage > PlayerStateHandler 에서 다시 처리합니다.onSelectingBlaster()onPlaying() 상태와 마찬가지로, onTaggedOut()playerState 특성의 변경에 따라 독특한 동작을 트리거합니다.특히, 플레이어 이동을 비활성화하고, 리스폰 UI를 제공하고, 블래스터를 비활성화합니다.

플레이어 상태 처리기

local function onTaggedOut()
-- 태그가 지정된 상태에서 컨트롤 비활성화
togglePlayerMovement(false)
togglePlayerCamera(false)
setGuiExclusivelyEnabled(playerGui.OutStateGui)
-- 태그가 지정된 상태에서 블래스터 비활성화
localPlayer:SetAttribute(PlayerAttribute.blasterStateClient, BlasterState.Disabled)
end

이 동작을 테스트하려면 Esc , 설정 탭으로 이동한 다음 캐릭터 재설정 버튼을 클릭하십시오.재생성 화면을 트리거할 때 이동, 카메라 회전 또는 블래스터 발사를 수행할 수 없음을 알아두십시오.

Roblox's settings menu with the Reset Character button highlighted.

캐릭터 재설정 버튼
>

The respawn screen displays as a player respawns back into the round.

재생성 화면
>

이 스크립트는 실제로 캐릭터를 재생성하지 않으며, 단지 행동을 중지하고 서버 에서 캐릭터를 재생성하는 플레이어에게 시각적 피드백을 제공합니다.보여주기 위해, ServerScriptService > SetupHumanoid > setupHumanoidAsync > onHumanoidDied 에서 스크립트가 설정을 변경하고 일부 시각적 표시기를 추가하면, ReplicatedStorage > PlayerStateHandl 에 알림을 보내고 일부 시각적 표시기를 추가합니다.재생성의 실제 논리는 기본 Roblox 동작입니다.

플레이어가 라운드에 재생성되면 SpawnLocation.TeamColor 속성에 따라 팀의 스폰 위치에서 재생성됩니다.재생성 시간을 사용자 지정하려면 SetupHumanoid의 맨 위에 다음 줄을 추가할 수 있습니다.이 기술에 대해 자세히 알아보려면 Players.RespawnTime를 참조하십시오.

Humanoid 설정

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

기타 설정

초기 설정의 일부로 샘플 레이저 태그 경험은 약간의 작지만 중요한 단계도 수행합니다:

  • 경험에는 기본 Roblox 건강 재생을 비활성화하는 빈 스크립트 StarterPlayer > StarterCharacterScripts > 건강 이 포함되어 있습니다.이 속성의 동작에 대한 설명은 Humanoid.Health 을 참조하십시오.

  • 경험은 StarterPlayer.CameraMode.LockFirstPerson 속성을 설정하여 1인칭 카메라를 사용합니다.사용자가 첫 번째와 세 번째 인격 카메라 간에 변경할 수 있도록 하려면 Studio에서 한 번만 설정하는 대신 속성을 프로그래밍 방식으로 변경하고 시점 변경을 보상하기 위해 컨트롤과 UI를 수정해야 합니다.

  • 경험은 플레이어가 다른 플레이어를 태그할 때마다 획득하는 "포인트"라는 단위의 내장 Roblox 리더보드를 사용합니다.서버스크립트 서비스(ServerScriptService)에서 구성을 볼 수 있지만, 경험 내 리더보드에서는 전체 개요를 제공합니다.onPlayerTagged 는 순위표에 포인트를 추가하며, 이는 라운드 추가히트 감지 에서 배울 수 있습니다.

이제 플레이어가 스폰할 수 있으며, 블래스터를 선택하고 1인칭 시점에서 조준할 수 있으므로 다음 섹션에서는 라운드 기반 게임 플레이만드는 데 있는 스크립트에 대해 알려줍니다.