블래스터 동작 구현

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

블래스터 동작 구현은 1인칭 슈팅 게임에서 폭발 메커니즘을 프로그래밍하는 과정입니다. 플레이어는 단일 클릭이나 버튼 누름으로 폭발할 수 있지만, 만족스럽고 정확한 폭발 동작을 만드는 것은 게임 전반의 즐거움을 향상시키기 때문에 중요합니다.

샘플 레이저 태그 경험을 참조하여, 이 튜토리얼 섹션에서는 두 가지 유형의 블래스터에 대한 블래스터 동작 구현 뒤의 스크립트에 대해 배우며, 다음에 대한 안내를 포함합니다:

  • 플레이어가 폭발 버튼을 누를 때 감지하기
  • 플레이어가 최근에 폭발 버튼을 눌렀을 때 블래스터를 사용할 수 있는지 확인하기
  • 폭발을 시작한 사람, 그 출처, 각 레이저 빔의 최종 목적지를 서버에 알려주는 폭발 데이터를 생성하기
  • 폭발이 다른 플레이어와 충돌했을 때 적절한 행동을 수행할 수 있도록 서버에 폭발 데이터를 통지하기
  • 각 폭발 사이에 블래스터를 재설정하여 블래스터가 다시 폭발할 수 있기 전에 충분한 쿨다운 시간을 주기

이 섹션을 완료하면 블래스터가 폭발이 다른 플레이어와 충돌했을 때 이를 감지하고, 각 블래스터 유형에 따라 해당하는 건강을 차감할 수 있도록 하는 스크립트에 대해 배우게 됩니다.

플레이어 입력 감지

블래스터 동작을 구현하기 위한 첫 단계는 플레이어가 폭발 버튼을 누를 때를 듣는 것입니다. 플레이어가 폭발 버튼을 누르는 데 사용하는 입력 유형은 그들이 경험에 접근하는 장치에 따라 다릅니다. 예를 들어, 샘플 레이저 태그 경험은 마우스 및 키보드, 게임패드, 터치 컨트롤을 지원합니다. 이러한 입력 유형 모두는 ReplicatedStorageUserInputHandler에서 확인할 수 있습니다.

이 클라이언트 스크립트는 ContextActionService를 사용하여 MouseButton1ButtonR2를 폭발 동작에 연결합니다. 즉, 플레이어가 왼쪽 마우스 버튼이나 게임패드의 R2 버튼을 누를 때마다 블래스터에서 레이저 빔이 발사됩니다. HUDGui에 모바일 장치에서 폭발을 위한 버튼이 포함되어 있으며, 이는 스크립트에서 나중에 연결됩니다.

UserInputHandler

ContextActionService:BindAction("_", onBlasterActivated, false,
Enum.UserInputType.MouseButton1,
Enum.KeyCode.ButtonR2
)

또한 onBlasterActivated() 정의에서 Enum.UserInputState.Begin의 사용도 중요한 주의 사항입니다. 이 예에서 블래스터를 선택하는 등의 많은 사용자 인터페이스 상호작용은 마우스 버튼이 올라간 후(Enum.UserInputState.End)에 발생하며, 이는 사용자가 마지막 순간에 상호작용을 피할 수 있는 기회를 제공합니다. 그러나 폭발 메커니즘은 버튼이 눌리는 즉시 발생하지 않는 한 응답성이 없다고 느껴질 수 있습니다.

예를 보여주기 위해 Enum.UserInputState.BeginEnum.UserInputState.End로 변경한 후 플레이테스트를 하여 폭발의 반응성이 게임플레이에 미치는 영향을 확인할 수 있습니다. 예를 들어, 플레이어가 버튼을 누르고 있어도 폭발이 발생하지 않는다면, 다른 플레이어를 태그할 때 그들의 경험이 어떻게 바뀔 수 있을까요?

UserInputHandler

local function onBlasterActivated(_actionName: string,
inputState: Enum.UserInputState, _inputObject: InputObject)
if inputState == Enum.UserInputState.End then -- 업데이트된 줄, 반드시 원래대로 변경
attemptBlastClient()
end
end

플레이어가 폭발할 수 있는지 확인

UserInputHandler가 버튼 누름이나 화면 탭을 감지한 후, ReplicatedStorageBlasterattemptBlastClient를 호출하여 플레이어가 폭발할 수 있는지 확인합니다. 샘플 레이저 태그 경험의 대부분의 체크와 마찬가지로, 클라이언트에서 먼저 발생하고 나중에 서버에서 발생합니다. attemptBlastClientReplicatedStorageBlastercanLocalPlayerBlast를 호출하여 blasterStateClient 플레이어 특성에 대한 간단한 체크를 수행합니다:

canLocalPlayerBlast

local function canLocalPlayerBlast(): boolean
return localPlayer:GetAttribute(PlayerAttribute.blasterStateClient) == BlasterState.Ready
end

ReplicatedStorageBlasterBlasterState를 살펴보면, 경험에는 세 가지 블래스터 상태가 있음을 알 수 있습니다: Ready, Blasting, Disabled. 각 상태의 효과를 보려면, 플레이 테스트 경험을 실행하고 Players 서비스 아래에서 플레이어를 선택한 다음 Properties 창에서 blasterStateClient 특성을 관찰할 수 있습니다. 블래스터를 선택하는 동안 Disabled, 대부분의 시간에 Ready, 버튼을 누른 후에는 1초 미만으로 Blasting으로 표시되는 것을 확인하세요.

이 약간의 지연은 사용자가 클릭한 만큼 신속하게 폭발할 수 없게 만듭니다. 예를 들어, 함수를 항상 true를 반환하도록 변경하면 지연 없이 블래스터를 빠르게 폭발시킬 수 있어, 이는 레이저 태그 게임플레이에 부적절합니다.

canLocalPlayerBlast

local function canLocalPlayerBlast(): boolean
return true -- 업데이트된 줄, 반드시 원래대로 변경
end

폭발 데이터 생성

플레이어의 블래스터가 Ready 상태에 있다고 확인되면, attemptBlastClientReplicatedStorageattemptBlastClientblastClient를 호출합니다. blastClient의 첫 번째 단계는 blasterStateClient 플레이어 특성을 Blasting으로 설정하여 앞서 언급한 빠른 발사를 방지하는 것입니다.

다음 단계는 폭발 데이터를 생성하는 것입니다. ReplicatedStorageBlasterBlastData를 검토하면, 각 폭발은 세 가지 정보로 구성됨을 알 수 있습니다:

  • 폭발을 시작한 플레이어
  • 폭발의 출발 지점을 나타내는 DataType.CFrame
  • 레이저 빔의 최종 목적지와 다른 플레이어가 맞은 경우 그 플레이어를 포함하는 RayResult 테이블

이 데이터를 생성하기 위해 blastClientReplicatedStorageattemptBlastClientblastClientgenerateBlastData를 호출합니다. 아래를 참조하십시오.

generateBlastData

local function generateBlastData(): BlastData.Type
local blasterConfig = getBlasterConfig()
local rayDirections = getDirectionsForBlast(
currentCamera.CFrame, blasterConfig)
local rayResults = castLaserRay(
localPlayer, currentCamera.CFrame.Position, rayDirections)
local blastData: BlastData.Type = {
player = localPlayer,
originCFrame = currentCamera.CFrame,
rayResults = rayResults,
}
return blastData
end

이 함수는 getBlasterConfig를 사용하여 플레이어의 블래스터 유형을 가져오는 것으로 시작합니다. 샘플은 넓고 수평적으로 퍼지는 여러 광선을 생성하는 블래스터와 단일 광선을 생성하는 블래스터 두 가지 유형을 제공합니다. 그들의 구성은 ReplicatedStorageInstancesLaserBlastersFolder에서 확인할 수 있습니다.

그 후, 함수는 폭발의 출발 지점으로 currentCamera.CFrame을 사용하여 getDirectionsForBlast에 전달합니다. 이 시점부터 코드는 더 이상 블래스터에 관한 것이 아니라 레이저 빔에 관한 것이며, 이는 튜토리얼의 충돌 감지 섹션에서 더 배울 수 있습니다. 마지막으로 rayResults 테이블이 생성된 후, generateBlastDatablastClient에 폭발 데이터를 반환할 필요한 모든 정보를 갖추게 됩니다.

서버에 알리기

blastClient가 폭발에 대한 완전한 데이터를 갖추게 되면, 두 개의 이벤트를 발사합니다:

blastClient

local laserBlastedBindableEvent = ReplicatedStorage.Instances.LaserBlastedBindableEvent
local laserBlastedEvent = ReplicatedStorage.Instances.LaserBlastedEvent
laserBlastedBindableEvent:Fire(blastData)
laserBlastedEvent:FireServer(blastData)

BindableEvent는 폭발에 대한 다른 클라이언트 스크립트에 통지합니다. 예를 들어, ReplicatedStorageFirstPersonBlasterVisuals는 이 이벤트를 사용하여 폭발 애니메이션 및 쿨다운 바와 같은 시각 효과를 표시할 시점을 알립니다. 유사하게, RemoteEvent는 폭발에 대한 서버 스크립트에 통지하며, ServerScriptServiceLaserBlastHandler에서 폭발 처리 작업을 시작합니다.

LaserBlastHandler

local function onLaserBlastedEvent(playerBlasted: Player, blastData: BlastData.Type)
local validatedBlastData = getValidatedBlastData(playerBlasted, blastData)
if not validatedBlastData then
return
end
if not canPlayerBlast(playerBlasted) then
return
end
blastServer(playerBlasted)
processTaggedPlayers(playerBlasted, blastData)
for _, replicateToPlayer in Players:GetPlayers() do
if playerBlasted == replicateToPlayer then
continue
end
replicateBlastEvent:FireClient(replicateToPlayer, playerBlasted, blastData)
end
end

치팅을 방지하기 위해 서버는 각 클라이언트가 보내는 모든 데이터를 검증해야 합니다. 이러한 체크에는 다음이 포함됩니다:

  1. BlastData는 테이블인가? Class.CFramerayResults라는 다른 테이블이 포함되어 있는가?
  2. 플레이어는 블래스터를 장착하고 있는가?
  3. 플레이어는 캐릭터와 위치를 가진 세계 내에 있는가?
  4. 폭발 데이터를 전송한 후, 플레이어가 레이저 빔을 발사했던 장소에서 과도한 거리를 이동했는가?

이 마지막 체크는 판단이 요구되는 부분이며, 서버 지연 및 플레이어 이동 속도에 따라 귀하의 경험에 적절한 신뢰할 수 있는 값이 무엇인지 결정할 수 있습니다. 이 판단을 시연해 보려면, getValidatedBlastData에 인쇄 문을 추가하고 경험을 플레이 테스트하여 일반적인 위치 변화의 정도를 파악할 수 있습니다.

getValidatedBlastData

local distanceFromCharacterToOrigin = blastData.originCFrame.Position - rootPartCFrame.Position
print(distanceFromCharacterToOrigin.Magnitude) -- 업데이트된 줄, 반드시 제거
if distanceFromCharacterToOrigin.Magnitude > ToleranceValues.DISTANCE_SANITY_CHECK_TOLERANCE_STUDS then
warn(`Player {player.Name} failed an origin sanity check while blasting`)
return
end

이동하고 폭발하게 되면, 출력 결과를 메모하십시오. 출력은 다음과 비슷하게 나타날 수 있습니다:


1.9019629955291748
3.1549558639526367
2.5742883682250977
4.8044586181640625
2.6434271335601807

ReplicatedStoragePlayerStateHandlertogglePlayerMovement에서 플레이어의 이동 속도를 증가시키면 다시 플레이 테스트할 때 폭발 간 과도한 이동 때문에 많은 체크 실패를 만날 가능성이 높습니다.

togglePlayerMovement

local ENABLED_WALK_SPEED = 60 -- 업데이트된 줄, 반드시 원래대로 변경

그런 다음 서버는 다음을 수행합니다:

  • rayResults를 검증합니다.
  • 플레이어가 폭발할 수 있는지 확인합니다.
  • 블래스터 상태를 재설정합니다.
  • 태그된 플레이어의 건강을 줄입니다.
  • 다른 모든 플레이어에게 폭발을 복제하여 그들이 제3자 시각을 볼 수 있도록 합니다.

이러한 서버 작업에 대한 자세한 내용은 튜토리얼의 충돌 감지 섹션을 참조하세요.

블래스터 재설정

샘플 레이저 태그 경험에서는 블래스터가 열 메커니즘을 사용합니다. 정해진 수의 폭발 후에 재장전하기보다는 각 폭발 사이에 "냉각"할 시간이 필요합니다. 이 쿨다운 지연은 클라이언트(blastClient)와 서버(blastServer) 모두에서 발생하며, 서버가 진실의 출처로 작용합니다.

blastServer

local blasterConfig = getBlasterConfig(player)
local secondsBetweenBlasts = blasterConfig:GetAttribute("secondsBetweenBlasts")
task.delay(secondsBetweenBlasts, function()
local currentState = player:GetAttribute(PlayerAttribute.blasterStateServer)
if currentState == BlasterState.Blasting then
player:SetAttribute(PlayerAttribute.blasterStateServer, BlasterState.Ready)
end
end)

secondsBetweenBlasts 특성은 ReplicatedStorageInstancesLaserBlastersFolder의 블래스터 구성의 일부입니다. secondsBetweenBlasts 지연이 지나면 플레이어는 다시 폭발할 수 있으며, 전체 프로세스가 반복됩니다. 플레이어가 다시 폭발할 수 있는 시점을 이해할 수 있도록 경험에는 쿨다운 바가 포함되어 있습니다.

이 시점에서 플레이어는 생성 및 재생성할 수 있으며, 조준 및 폭발할 수 있지만, 경험은 여전히 각 폭발의 결과를 결정해야 합니다. 튜토리얼의 다음 섹션에서는 블래스터가 폭발이 다른 플레이어에 충돌했을 때 이를 감지하고, 블래스터 설정에 따라 플레이어의 건강을 적절히 줄일 수 있도록 프로그래밍하는 방법을 배우게 됩니다.

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