스폰 및 리스폰

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

스폰은 경험에 객체나 캐릭터를 생성하는 과정이며, 리스폰은 캐릭터의 생명력이 0에 도달하거나 맵에서 떨어지는 등의 제거 조건을 충족한 후 객체나 캐릭터를 경험에 다시 추가하는 과정입니다. 두 과정 모두 플레이어가 당신의 경험에 참여할 수 있고, 계속해서 기술을 향상시킬 수 있도록 보장하기 때문에 중요합니다.

샘플 레이저 태그 경험을 참조로 삼아 이 튜토리얼의 이 섹션에서는 스폰 및 리스폰을 처리하기 위해 Roblox의 내장 기능을 사용하는 방법을 가이드하며, 다음과 같은 스크립팅 지침을 포함합니다:

  • 플레이어가 자신의 팀의 스폰 구역에만 스폰될 수 있도록 스폰 위치를 구성합니다.
  • 새로운 플레이어와 그들의 캐릭터를 경험에 조인하면서 라운드에 추가합니다.
  • 플레이어가 스폰 및 리스폰할 때 피해를 방지하는 힘의 장(field)을 사용자 지정합니다.
  • 적절한 시간에 게임 플레이가 올바르게 작동하도록 클라이언트 상태를 처리합니다.
  • 캐릭터가 라운드에서 태그아웃된 후 리스폰 시킵니다.
  • 게임 플레이와 캐릭터 매개변수를 설정하는 데 중요한 작은 잡다한 작업을 수행합니다.

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

스폰 위치 구성

지금 경험을 플레이 테스트하면 모든 플레이어가 녹색 팀의 스폰 구역에 있는 SpawnLocation 객체나 분홍색 팀의 스폰 구역에 있는 SpawnLocation 객체 중 하나에 무작위로 스폰됩니다. 이는 플레이어가 상대의 힘의 장이 사라지는 즉시 각 스폰 구역에서 서로 태그할 수 있는 게임 플레이 문제를 발생시킵니다.

이 문제에 대응하기 위해 샘플 레이저 태그 경험은 두 스폰 위치에 Neutral 속성을 false로 설정하여 상대 팀의 플레이어가 잘못된 스폰 구역에 스폰되지 않도록 제한하고, TeamColor 속성을 팀 색상 할당 섹션에서의 해당 Team.Color 값으로 설정합니다:

  • TeamASpawn – 무늬가 민트로 설정된 녹색 팀의 스폰 구역에 있는 스폰 위치.
  • TeamBSpawn – 무늬가 카네이션 핑크로 설정된 분홍색 팀의 스폰 구역에 있는 스폰 위치.
TeamASpawn
TeamBSpawn

플레이어가 경험에 조인하면 ServerScriptServiceGameplayRoundsspawnPlayersInMap가 각 팀에 이미 몇 명의 플레이어가 있는지 확인한 후, 플레이어 수가 가장 적은 팀을 반환합니다.

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로 설정하여 선수는 자신의 팀 스폰 위치에만 스폰 및 리스폰할 수 있게 하며, 그들의 PlayerStateSelectingBlaster로 설정합니다. 이는 튜토리얼에서 나중에 더 많이 배우게 됩니다.

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

WorkspaceWorldMapSpawns를 확인하면 맵에 추가 스폰 위치가 하나 더 있는 것을 볼 수 있습니다: NeutralSpawn. 이 스폰 위치는 경험의 두 팀 중 하나로 설정된 TeamColor 속성이 없기 때문에 다른 것과 구별됩니다. 대신, 이 스폰 위치는 라운드가 활성화되어 있는지에 따라 변경되는 Neutral 속성을 가지고 있습니다.

예를 들어, 라운드가 활성화되면 Neutral 속성은 false로 설정되어 spawnPlayersInMap가 플레이어를 팀에 분류하고 아레나로 스폰할 수 있습니다. 그러나 라운드가 활성화되지 않은 경우, 즉 하나의 라운드와 다음 라운드 사이의 시간 동안 Neutral 속성은 true로 설정되어 플레이어가 팀 상태와 관계없이 그곳에 스폰할 수 있습니다. 이 과정은 Neutral 스폰 위치를 기능적인 로비로 만드는 역할을 합니다.

Neutral

예를 들어, ServerScriptServiceGameplayRoundsSpawnPlayersInLobby를 확인하면, 이 스크립트는 라운드가 끝날 때 실행되며 players: { Player } 테이블에 전달된 각 플레이어에 대해 다음을 수행합니다:

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

중립 스폰 존과 각 라운드에 대한 기능에 대한 더 많은 정보는 튜토리얼의 다음 섹션인 라운드 추가를 참조하세요.

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

새로운 플레이어 연결

스튜디오의 Luau 코드는 종종 이벤트 기반이므로, 스크립트는 Roblox 서비스의 이벤트를 듣고 이에 응답하여 함수를 호출합니다. 예를 들어, 멀티플레이어 경험에 새로운 플레이어를 추가할 때, 플레이어가 성공적으로 연결되는 데 필요한 모든 것을 처리하는 이벤트가 있어야 합니다. 샘플 레이저 태그 경험에서 이 해당 이벤트는 Players.PlayerAdded:Connect입니다.

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

Studio의 전체 찾기 창에서 Players.PlayerAdded 결과가 강조 표시되어 있습니다.

예를 들어, ServerScriptServiceSetupHumanoid를 열어보면 PlayerCharacter의 구분이 이 스크립트를 이해하는 데 핵심입니다:

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

SetupHumanoid는 즉시 플레이어가 캐릭터가 있는지 (방금 참여한 경우) 또는 없는지 (리스폰 중인 경우)를 확인합니다. 하나를 찾은 후 onCharacterAdded()를 호출하고, 캐릭터에서 Humanoid 모델을 가져와 ServerScriptServiceSetupHumanoidsetupHumanoidAsync에 전달하여 사용자 지정합니다. 이러한 값을 설정한 후 스크립트는 캐릭터의 생명력이 0에 도달할 때까지 대기합니다. 리스폰에 대한 추가 정보는 나중에 이 섹션에서 배우게 됩니다.

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

이 스크립트의 중요 포인트는 속성이 완전히 선택사항이라는 것입니다. 첫 여섯 줄을 제거해도 경험은 제대로 작동합니다. 기능적 요구 사항이 아니라, 각 속성은 게임 플레이 목표를 충족하기 위해 디자인 결정을 내리는 데 도움을 줍니다. 예를 들어:

  • 캐릭터 이름이 더 가까운 거리에서 보이도록 하려면 Humanoid.NameDisplayDistance 값을 줄입니다.
  • 캐릭터의 생명력이 100% 아래일 때만 생명력을 표시하고 싶다면 Humanoid.HealthDisplayTypeDisplayWhenDamaged로 설정합니다.
  • 캐릭터의 생명력이 0에 도달했을 때 그 캐릭터가 분해되도록 하고 싶다면 Humanoid.BreakJointsOnDeathTrue로 설정합니다.

이러한 속성 값을 변경할 경우 플레이 테스트를 하여 새로운 설정의 영향을 확인해야 합니다. 최소 두 캐릭터를 선택하여 서버 & 클라이언트 플레이 테스트를 통해 플레이어가 경험하는 것을 재현할 수 있습니다.

Studio의 메자닌에서 테스트 모드 드롭다운의 Server & Clients 옵션.

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

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)

PlayerStateHandler에서 논의할 특정 변수는 attributeChangedConnectionByPlayer입니다. 이 테이블은 모든 플레이어와 그들의 ConnectionsGetAttributeChangedSignal에 저장합니다. 이 연결을 테이블에 저장하는 이유는 PlayerStateHandler가 플레이어가 경험을 떠날 때 이를 연결 해제하기 위해서입니다. 이 과정은 메모리 관리의 일종으로, 시간이 지남에 따라 연결 수가 증가하는 것을 방지하기 위한 것입니다.

PlayerStateHandler

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가 비활성화됩니다. 후에 블래스터 구현 섹션에서 이 과정에 대한 더 자세한 내용을 배우게 됩니다.

PlayerStateHandler

local function onPlayerStateChanged(player: Player, newPlayerState: string)
-- 플레이어 상태가 'Playing'일 때만 블래스터 상태는 'Ready'
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

중단점이나 print() 문을 추가하면 onPlayerStateChanged()가 라운드 초기 설정 동안, 주요 코드 경로에 설정되었을 때, 플레이어가 블래스터를 선택한 후, 플레이어가 로비 또는 중립 스폰 위치로 돌아갈 때와 같이 경험 전반에 걸쳐 자주 호출되는 것을 볼 수 있습니다. 더 나아가, 플레이어가 블래스터를 선택한 후에는 ServerScriptServiceBlasterSelectedHandlerPlayerStatePlaying으로 설정하고 PlayerStateHandlerscheduleDestroyForceField()를 호출하여 힘의 장을 제거할 수 있습니다.

힘의 장 사용자 지정

샘플 레이저 태그 경험은 플레이어가 블래스터를 선택하는 동안 피해를 받지 않도록 Studio의 내장 ForceField 클래스를 사용합니다. 이렇게 함으로써 플레이어가 힘의 장을 가지고 스폰될 수 있는 유일한 요구 사항은 SpawnLocation.Duration 속성이 0보다 큰 스폰 위치를 포함하는 것입니다. 샘플은 힘의 장을 활성화하기 위해 임의의 값인 9,999를 사용한 후, ReplicatedStorageForceFieldClientVisuals에서 실제 지속 시간을 프로그래밍적으로 처리합니다.

setupHumanoidAsync와 유사하게, ForceFieldClientVisuals의 대부분의 줄은 선택 사항입니다. 예를 들어, 다음 스크립트처럼 함수의 내용을 주석 처리하면 경험은 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

커스텀 힘의 장은 새로운 ParticleEmitter가 아닌 GUI이기 때문에, ForceFieldClientVisuals 스크립트는 각 플레이어에 대한 1인칭 비주얼에만 영향을 미치며, 다른 플레이어를 볼 때의 3인칭 비주얼에는 영향을 미치지 않습니다. 3인칭 비주얼은 기본 Roblox 외형을 유지합니다. 힘의 장 수정에 대한 더 많은 정보는 ForceField.Visible를 참조하세요.

1인칭 힘의 장 비주얼은 화면의 주변에 미래적인 육각형 그리드를 포함합니다.
1인칭 힘의 장 비주얼
3인칭 힘의 장 비주얼은 경험에 스폰 중인 플레이어 주위에 파란색 반짝이는 오브를 포함합니다.
3인칭 힘의 장 비주얼

힘의 장은 플레이어가 스폰되고 리스폰되는 사이 적의 플레이어를 걱정할 필요 없이 충분한 시간을 제공하기 때문에 유용하지만, 결국에는 레이저 태그의 주요 게임 플레이를 위해 사라져야 합니다. 힘의 장 제거를 처리하는 스크립트는 ReplicatedStoragescheduleDestroyForceField에 있으며, 세 가지 고유한 조건을 확인합니다:

  • 플레이어가 블래스터를 선택한 후, 힘의 장은 플레이어가 환경에 적응할 수 있도록 할 만큼 충분히 지속되어야 합니다.
  • 이 적응 시간 동안 힘의 장은 이점이 되어서는 안 되므로, 플레이어가 블래스터를 발사하는 순간에 사라져야 합니다.
  • 플레이어가 블래스터를 발사하기 전이나 힘의 장 시간이 초과되기 전 캐릭터를 리셋할 때 힘의 장이 사라져야 합니다.

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

scheduleDestroyForceField

-- 플레이어가 발사하면 힘의 장 종료
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()에는 forceFieldEnded 불리언을 둘러싼 다소 이상한 if 문이 포함되어 있습니다. 이 검사는 순차적으로 실행되므로 스크립트는 endForceField() 함수를 두 번 또는 세 번 호출할 수 있습니다. forceFieldEnded 불리언은 함수가 힘의 장을 한 번만 제거하도록 보장합니다.

scheduleDestroyForceField

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

클라이언트 상태 처리

이 섹션의 대부분은 ServerScriptServicePlayerStateHandler에 중점을 두지만, ReplicatedStorage에도 같은 이름의 다른 스크립트가 있습니다. 분할된 이유는 클라이언트-서버 아키텍처입니다:

  • 클라이언트는 플레이어 상태 정보를 이해해야 하므로, 실시간으로 적절히 반응할 수 있도록 합니다. 예를 들어, 올바른 사용자 인터페이스 요소를 표시하거나 플레이어가 이동하고 발사할 수 있게 합니다.

  • 서버는 이러한 모든 정보를 필요로 하여, 익스플로잇을 방지할 수 있습니다. 예를 들어, 서버는 캐릭터를 스폰하고 장비를 부여하는 것과 같은 작업을 수행하고, 힘의 장을 비활성화하며 리더보드를 표시하는 데에도 플레이어 상태가 필요합니다. 이러한 이유로 이 스크립트는 ReplicatedStorage에 존재하며 순수 클라이언트 측 위치가 아닙니다.

이 기본 논리를 보려면 현재 사용자의 상태를 확인한 후 해당 상태에 대한 적절한 작업을 처리하는 함수를 호출하는 ReplicatedStoragePlayerStateHandler의 다음 스크립트를 검토합니다.

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(`유효하지 않은 플레이어 상태 ({newPlayerState})`)
end
end

모든 이벤트 응답은 유사한 행동을 필요로 하기 때문에 이 스크립트에 논리적으로 그룹화되어 있습니다. 즉, 플레이어의 조작, 카메라 이동 및 어떤 UI 레이어가 표시되는지를 활성화하거나 비활성화하는 것입니다. 예를 들어, 블래스터 선택 중 플레이어는 무적이면서 동시에 이동할 수 없게 되어야 합니다. 서버는 이미 힘의 장을 처리하지만 클라이언트는 이동을 처리합니다. onSelectingBlaster() 함수의 논리를 확인해보면 플레이어가 블래스터를 선택하는 동안 이동이 비활성화된 것을 알 수 있습니다.

PlayerStateHandler

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

onPlaying() 함수도 유사하게 간단합니다. 이는 이동을 활성화하고 주요 헤드업 디스플레이(HUD)로 전환하며, 블래스터를 활성화하고 서버와 같은 힘의 장 기능을 호출합니다.

PlayerStateHandler

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

캐릭터 리스폰

샘플 레이저 태그 경험은 ReplicatedStoragePlayerStateHandleronTaggedOut() 상태를 통해 캐릭터의 리스폰 처리를 합니다. onSelectingBlaster()onPlaying() 상태와 마찬가지로, onTaggedOut()playerState 속성의 변경에 따라 고유한 동작을 트리거합니다. 특히, 플레이어 이동을 비활성화하고 리스폰 UI를 나타내며 블래스터를 비활성화합니다.

PlayerStateHandler

local function onTaggedOut()
-- 태그 아웃된 동안 조작 비활성화
togglePlayerMovement(false)
togglePlayerCamera(false)
setGuiExclusivelyEnabled(playerGui.OutStateGui)
-- 태그 아웃된 동안 블래스터 비활성화
localPlayer:SetAttribute(PlayerAttribute.blasterStateClient, BlasterState.Disabled)
end

이 행동을 테스트하려면 Esc를 눌러 설정 탭으로 이동한 다음 캐릭터 리셋 버튼을 클릭하십시오. 리스폰 화면을 호출할 때 이동하거나 카메라를 회전시키거나 블래스터를 발사할 수 없음을 주의하십시오.

리셋 캐릭터 버튼이 강조된 Roblox의 설정 메뉴.
리셋 캐릭터 버튼
플레이어가 라운드에 리스폰되는 동안 리스폰 화면이 표시됩니다.
리스폰 화면

이 스크립트는 실제로 캐릭터를 리스폰하지 않으며, 단지 그들이 행동하지 못하도록 막고 서버가 캐릭터를 리스폰하고 있음을 플레이어에게 시각적으로 피드백을 제공합니다. 예를 들어, ServerScriptServiceSetupHumanoidsetupHumanoidAsynconHumanoidDied를 조사하면, 스크립트가 PlayerStateTaggedOut으로 설정하고 (사실상 ReplicatedStoragePlayerStateHandler에 알리는 것) 몇 가지 시각적 지시기를 추가하는 것을 볼 수 있습니다. 실제 리스폰 로직은 내장된 Roblox 동작입니다.

플레이어가 라운드에 리스폰할 때, 그들은 SpawnLocation.TeamColor 속성에 따라 자신의 팀의 스폰 위치에서 리스폰됩니다. 리스폰 시간을 사용자 지정하려면 SetupHumanoid의 맨 위에 다음 줄을 추가할 수 있습니다. 이 기술에 대한 더 많은 정보는 Players.RespawnTime을 참조하세요.

SetupHumanoid

local Players = game:GetService("Players")
Players.RespawnTime = 10 -- 새로운 줄, 초 단위

잡다한 설정

초기 설정의 일환으로 샘플 레이저 태그 경험은 몇 가지 작지만 중요한 단계를 수행합니다:

  • 경험은 기본 Roblox 건강 재생을 비활성화하는 빈 스크립트를 포함합니다. 이 속성 동작에 대한 설명은 Humanoid.Health를 참조하세요.

  • 경험은 StarterPlayer.CameraMode.LockFirstPerson 속성을 설정하여 1인칭 카메라를 사용합니다. 사용자가 1인칭과 3인칭 카메라 간에 변경할 수 있도록 하려면, 이 속성을 프로그램적으로 변경해야 하며 스튜디오에서 한 번 설정하는 것만으로는 충분하지 않으며, 관점 변경에 따라 조작 및 UI를 수정해야 합니다.

  • 경험은 플레이어가 다른 플레이어를 태그할 때마다 획득하는 "포인트" 단위의 기본 Roblox 리더보드를 사용합니다. 이 구성은 ServerScriptServiceSetupLeaderboard에서 확인할 수 있지만, 인 경험 리더보드의 전체 개관도 제공됩니다. onPlayerTagged는 리더보드에 포인트를 추가하며, 이는 나중에 라운드 추가타격 탐지에서 배웁니다.

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

©2026 Roblox Corporation. Roblox 및 Roblox 로고, 'Powering Imagination'은 미국 및 기타 국가 내 당사의 등록 및 미등록 상표입니다.