생성 은 경험에서 개체 또는 캐릭터를 생성하는 프로세스이며, 재생 은 캐릭터가 제거 조건을 충족한 후 경험에 다시 추가되는 프로세스입니다. 두 프로세스 모두 중요하지만, 플레이어가 경험에 참여할 수 있도
참조용으로 사용하는 샘플 레이저 태그 경험 을 사용하면 이 Roblox나머지 부분에서 스크립트 가이드를 포함하여 스폰과 리스폰을 처리하는 방법을 배울 수 있습니다.
- 플레이어가 팀의 스폰 영역에만 생성할 수 있도록 스폰 위치를 구성합니다.
- 새로운 플레이어와 그들의 캐릭터를 경험에 참여하게 하는 라운드에 추가합니다.
- 플레이어가 생성하고 재생할 때 피해를 방지하는 힘 필드를 사용자 정의합니다.
- 적절한 시간에 게임플레이가 제대로 작동하도록 클라이언트 상태를 처리합니다.
- 라운드에서 태그가 나간 후 캐릭터를 다시 생성합니다.
- 게임 플레이 및 캐릭터 매개 변수를 설정하는 데 중요한 작은 미니 액션을 수행합니다.
이 섹션에는 스크립트 콘텐츠가 많이 포함되어 있지만, 경험을 만들 때 모든 것을 처음부터 작성할 필요는 없습니다. 대신, 기존 구성 요소를 활용하고, 빠르게 반복하고, 어떤 시스템이 비전에 일치하는지 찾아내는 등의 작업을 수행하면 됩니다. 이
생성 위치 구성
현재 경험을 플레이테스트하면 모든 플레이어가 녹색 팀의 스폰 영역에 있거나 핑크 팀의 스폰 영역에 있는 SpawnLocation 개체 중 랜덤하게 생성됩니다. 이 게임 플레이 문제는 플레이어가 각 스폰 영역에
이 문제를 해결하기 위해 샘플 레이저 태그 경험은 모든 생성 위치를 Neutral 속성 집합으로 false로 설정하여 상대 팀의
- TeamASpawn – 초록 팀의 스폰 지점에 있는 스폰 위치에 속성 Class.SpawnLocation.TeamColor|TeamColor 설정을 TeamColor 로 변경합니다.
![](https://prod.docsiteassets.roblox.com/assets/tutorials/gameplay-scripting/Spawn-Respawn/TeamASpawn.jpg)
![](https://prod.docsiteassets.roblox.com/assets/tutorials/gameplay-scripting/Spawn-Respawn/TeamBSpawn.jpg)
플레이어가 경험에 참여할 때, ServerScriptService > 게임플레이 > 라운드 > 1>생성플레이어InMap1> 체크를 보아 플레이어가 각 팀에 얼마나 많은 플레이어가 있는지 확인한 다음 팀을 가장 적은 플레이어로 생성합니다.
생성PlayersInMap
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로 설정하여 플레이어가 팀의 스폰 위치에만 생성하고 다시 생성할 수 있도록
생성PlayersInMap
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
작업 공간 > 세계 > 맵 > 1>생성1> > 4>중립 생성4> > 7>스
예를 들어, 라운드가 활성화되면 Neutral 속성이 false로 설정되므로 spawnPlayers
![](https://prod.docsiteassets.roblox.com/assets/tutorials/gameplay-scripting/Spawn-Respawn/Neutral.jpg)
시연하려면, ServerScriptService > 게임플레이 > 라운드 > 1>스폰플레이어InLobby1> , 라운드의 끝에 실행되는 모든 플레이어에 대해 스크립트를 볼 수 있습니다.
- 그들의 Player.Neutral 속성을 진실로 설정하면 자동으로 그들의 Player.Team을 일시 로 재설정하여 플레이어가 라운드가 활성화되지 않을 때 로비에서 다시 생성할 수 있도록 합니다. 스폰 위치Class.SpawnLocation.Ne
- 플레이어의 블래스터를 제거하고 첫 번째 인 로비 시각적 개체를 표시하려면 InLobby로 PlayerState를 변경합니다.
중립 생성 영역에 대한 자세한 내용은 자습서의 다음 섹션에 있는 라운드 추가를 참조하십시오.
로비에서 플레이어 생성
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 는 경험의 여러 스크립트의 일부입니다. 경험의 초기 설정을 이해하는 데 유용한 Ctrl/Ctrl+Shift+F 단축 검색을 사용하면 결과는 좋은 시작 지점을 제공합니다.
![Studio's Find All window with the Players.PlayerAdded results highlighted.](https://prod.docsiteassets.roblox.com/assets/tutorials/gameplay-scripting/Spawn-Respawn/Find-All.png)
시연하려면 ServerScriptService > SetupHumanoid 을 엽니다. Player 와 1> Class.Player.Character|Character1> 의 차이점은 이 스크립트를 이해하는 데 중요한 요소입니다.
- 플레이어는 블래스터를 선택하고 리더보드추가되어야 합니다. 캐릭터는 생성되고 블래스터를 받아야 합니다.
SetupHumanoid 즉시 플레이어가 캐릭터를 가지고 있는지 확인하고 그렇지 않으면 (새로 합류) 아니면 (이
설정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개 줄을 제거하면 경험이 여전히 작동하는 경우가 있습니다. 기능 요구 사항이 아닌 각 속성을 사용하여 게임 플레이 목표에 부합하는 디자인 결정을 내릴 수 있습니다. 예를 들어:
- 캐릭터 이름을 가까운 거리에서 표시하려면 Humanoid.NameDisplayDistance 값을 줄이십시오.
- 캐릭터의 체력이 100% 미만인 경우 Humanoid.HealthDisplayType 를 손상 시 표시 로 설정합니다.
- 캐릭터가 체력이 0이 될 때 솔기 부서지게 하려면 Humanoid.BreakJointsOnDeath 를 진실로 설정하십시오.
이 속성의 값을 변경하면 새로운 설정의 영향을 확인하기 위해 플레이테스트를 수행해야 합니다. 멀티플레이어 환경에서 플레이어가 경험하는 것을 최소 2개의 캐릭터를 선택하여 클라이언트 및 서버 섹션의 테스트 탭에서 재현할 수 있습니다.
![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.](https://prod.docsiteassets.roblox.com/assets/tutorials/gameplay-scripting/tutorial-gs-server.png)
PlayerPlayerAdded:Connect 이벤트의 또 다른 예는 ServerScriptService > PlayerStateHandler 에 있습니다. 이 예와 마찬가지로 1> PlayerStatusHandler
플레이어 상태 처리기
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 . 이 테이블은 모든 플레이어와 그들의 Dat
플레이어 상태 처리기
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
You can see that both connected functions in onPlayerAdded() call onPlayerStateChanged() . During initial setup after a player sorts into a team, onPlayerAdded() sets 1> PlayerState
플레이어 상태 처리기
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
print() 문을 추가하거나 심지
힘 필드 사용자 정의
사용자가 블래스터를 선택할 때 피해를 입지 않도록 하려면 Studio의 내장 ForceField 클래스를 사용하는 대신 샘플 레이저 태그 경험은 Studio의
setupHumanoidAsync() 와 유사하지만 ForceFieldClientVisuals 의 대부분의 줄은 선택적입니다. 예를 들어, 다음 스크립트처럼 함수 콘텐츠를 comment하면 경험은 헥사곤 스크립트가 아닌 기본 스파크링 포스 필드를 사용
ForceFieldClientVisuals의 속성 주석
local function onCharacterAddedAsync(character: Model)
-- 로컬 포스필드 = 캐릭터:WaitForChild("ForceField", 3)
-- ForceField이 아니면
-- 반환
-- 종료
-- forceField.Visible = false
-- localPlayer.PlayerGui:WaitForChild("ForceFieldGui") 활성화 = true
-- forceField.Destroying:Wait()
-- 로컬 플레이어.PlayerGui.ForceFieldGui.Enabled = false
end
사용자 정의 힘 필드가 새로운 ParticleEmitter가 아닌 GUI이므로 ForceFieldClientVisuals 스크립트는 각 플레이어에 대한 첫 번째 시각적 모습영향을 줍니다. 제한하지 않음은 플레
![First-person force field visuals include a futuristic hexagonal grid on the perimeter of the screen.](https://prod.docsiteassets.roblox.com/assets/tutorials/gameplay-scripting/Spawn-Respawn/First-Person-Visuals.png)
![Third-person force field visuals include a blue sparkling orb around the player spawning into the experience.](https://prod.docsiteassets.roblox.com/assets/tutorials/gameplay-scripting/Spawn-Respawn/Third-Person-Visuals.png)
Force 필드는 플레이어가 적에 대해 걱정할 필요 없이 스폰과 리스폰 사이에 충분한 시간을 제공하므로 유용하지만, 결국 주요 레이저 태그 게임 플레이대해 적절하게 숨겨야 합니다. Force 필드 제거를 처리하는 스크립트는 ReplicatedStorage > ScheduleDestroyForceField
- 플레이어가 블래스터를 선택하면 장소를 적응하려면 충분히 오래 지속되어야 합니다.
- 이 오작동 시간 동안에는 필드를 피하는 것이 좋지만, 플레이어가 그들의 블래스터를 폭발시키는 순간 필드는 사라져야 합니다.
- 힘 필드는 플레이어가 캐릭터를 재설정할 때 폭발하거나 힘 필드 시간이 끝날 때 사라져야 합니다.
이 조건에 대해 scheduleDestroyForceField 스크립트 호출의 각 endForceField() 에서 각각 endForceField 합니다.
일정 파괴 필드
-- 플레이어가 폭발하면 종료 힘 필드
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 부울 주위의 이상한 0> if0> 문을 두 번 또는 세 번 호출할 수 있
일정 파괴 필드
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 레이어가 유사한 동작을 요구하기 때문에 논리적으로 함께 그룹화됩니다. 예를 들어, 블래스터 선택 시 플레이어가
플레이어 상태 처리기
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
캐릭터 재생
샘플 레이저 태그 경험은 플레이어 상태 처리기 인 onTaggedOut() 를 통해 재생성된 캐릭터를 라운드로 다시 처리합니다.
플레이어 상태 처리기
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.](https://prod.docsiteassets.roblox.com/assets/tutorials/gameplay-scripting/Spawn-Respawn/Reset-Character-Button.png)
![The respawn screen displays as a player respawns back into the round.](https://prod.docsiteassets.roblox.com/assets/tutorials/gameplay-scripting/Spawn-Respawn/Respawn-Screen.png)
이 스크립트는 실제로 캐릭터를 재생성하지는 않지만,
플레이어가 라운드로 다시 부활하면, 그들은 SpawnLocation.TeamColor 속성에 따라 팀의 스폰 위치에 다시 생성됩니다. 재생 시간을 사용자 정의하려면 SetupHumanoid 위에 다음 줄을 추가할 수 있습니다. 이 기술에
설정 인간형
local Players = game:GetService("Players")Players.RespawnTime = 10 -- new line, in seconds
기타 설정
초기 설정의 일부로, 샘플 레이저 태그 경험은 작은 하지만 중요한 단계를 수행합니다.
경험에는 StarterPlayer 라는 이름의 빈 스크립트가 포함되어 있으며, StarterCharacterScripts Health 는 기본 Roblox 건강 재생을 비활성화합니다. 이 속성의 설명은 1>1> Class.Humanoid.Health1>를 참조하십시오.
경험은 StarterPlayer.CameraMode.LockFirstPerson 속성을 설정하여 첫 번째 사람 카메라를 사용하여 사용자를 변경하는 경우 사용자를 사이드 카메라로 변경하도록 허용합니다. 사용자가 첫 번째 사람 카메라에서 변경하려면 프로그래밍 방식으로 속성을 변경해야 하며 컨트롤 및
경험은 플레이어가 다른 플레이어를 태그할 때마다 얻는 "포인트"를 기반으로 내장 Roblox 순위표를 사용합니다. 서버스크립트 서비스 > 설정 보드
이제 플레이어가 생성할 수 있으므로 블래스터를 선택하고 첫 번째 개인 시점에서 조준하세요. 다음 섹션에서는 둥근 기반 게임 플레이만드는 스크립트에 대해 설명합니다.