안동민 개발노트

본문 시작

동적 환경 상호작용의 기본 구현

입력·충돌·데미지 이벤트를 환경 변화와 피드백에 연결해 피격 후 물리로 전환하는 상자와 반응형 오브젝트를 구현합니다.

지금까지 우리는 오브젝트에 물리 시뮬레이션을 적용하고, 콜리전 이벤트를 처리하며, 환경에 대한 정보를 쿼리하는 방법을 배웠습니다.

또한 낮/밤 주기 및 날씨 시스템을 통해 환경에 동적인 변화를 주는 기초를 다졌습니다.

이제 이러한 지식들을 통합하여 플레이어의 행동이나 게임 이벤트에 따라 반응하고 변화하는 동적 환경 상호작용을 구현하는 기본 방법에 대해 알아보겠습니다.

동적 환경 상호작용은 플레이어 입력, 물리 반응, 콜리전, 피드백을 연결하는 구현 영역입니다.


동적 환경 상호작용이란 무엇인가?

동적 환경 상호작용(Dynamic Environment Interaction)은 게임 월드 내의 오브젝트들이 플레이어의 행동, 물리적 충격, 또는 게임 로직에 의해 실시간으로 변화하고 반응하는 것을 의미합니다.

이는 단순한 물리 시뮬레이션을 넘어, 게임플레이와 직접적으로 연결되어 플레이어에게 결과를 보여주는 것입니다.

예시
  • 파괴 가능한 오브젝트: 총격이나 폭발에 의해 벽, 상자, 유리창 등이 부서지는 것.
  • 움직이는 플랫폼/문: 플레이어가 스위치를 누르거나 특정 위치에 도달하면 문이 열리거나 플랫폼이 움직이는 것.
  • 물리 기반 퍼즐: 특정 오브젝트를 밀거나 던져서 레버를 작동시키거나 길을 막는 것.
  • 환경적 위험 요소: 플레이어가 밟으면 무너지는 바닥, 닿으면 데미지를 입는 용암 등.
  • 상호작용 가능한 오브젝트: 플레이어가 특정 버튼을 누르면 작동하는 기계 등.

동적 환경 상호작용 구현의 기본 원리

대부분의 동적 환경 상호작용은 다음의 기본 단계를 따릅니다.

입력/트리거: 플레이어의 입력, 다른 오브젝트와의 콜리전, 시간 경과, 게임 이벤트 발생 등 상호작용을 시작하는 조건.

판단/로직: 트리거를 감지한 후 어떤 행동을 할지 결정하는 게임 로직.

환경 변화: 결정된 로직에 따라 환경 오브젝트의 물리적 상태, 시각적 표현, 활성 상태 등을 변경.

피드백: 플레이어에게 변화에 대한 시각적(이펙트), 청각적(사운드), 또는 햅틱(진동) 피드백 제공.


기본 구현 예시: 피격 후 물리로 전환하는 상자

체력이 0이 되면 고정 상자가 물리 바디로 움직이고 효과를 재생하도록 구현합니다. 기존 이름 BP_DestructibleBox를 사용하지만, 단일 Cube에 Simulate Physics를 켜는 것만으로 메시가 여러 파편으로 쪼개지지는 않습니다. 실제 파쇄는 Geometry Collection 등 별도의 구성이 필요합니다.

파괴 가능한 상자 액터 블루프린트 생성

새 액터 블루프린트 생성: Actor를 부모 클래스로 하는 BP_DestructibleBox를 생성합니다.

컴포넌트 추가
  • Static Mesh Component: Cube 메시를 루트로 두고 Mobility를 Movable로 설정합니다. 물리에 사용할 단순 충돌도 확인합니다.
  • Box Collision Component: 별도 트리거가 필요할 때만 추가합니다. 이 예제의 Blocking은 메시가 담당하므로 추가 Box는 No Collision으로 두어 중복 충돌을 만들지 않습니다.
콜리전 설정
  • Static Mesh Component를 BlockAll로 설정하고 총알의 Object Type도 서로 Block하는지 확인합니다.
  • Static Mesh Component의 Simulate Physics는 체크 해제합니다. (처음에는 고정되어 있다가 파괴 시 물리가 적용되도록 할 것임)
  • 이 상자는 Apply Damage를 받아 처리합니다. 물리 충돌 자체의 Hit 알림도 사용한다면 해당 컴포넌트의 Simulation Generates Hit Events를 추가로 설정합니다.

데미지 처리 및 파괴 로직 구현

BP_DestructibleBox 블루프린트의 이벤트 그래프에서 다음을 구현합니다.

Event AnyDamage 활용
  • Event AnyDamage 노드를 추가합니다. 이 이벤트는 권한 측에서 실행됩니다. 싱글플레이는 로컬 월드가 권한 측이며, 멀티플레이는 서버가 데미지를 적용해야 합니다. 액터의 Can Be Damaged도 확인합니다.
  • Health 변수 추가: Health라는 Float 변수를 추가하고 디폴트 값을 100.0 등으로 설정합니다.
  • bDestroyed가 이미 참이면 종료합니다. 이 예제는 양수 피해만 처리하여 Health = Max(0, Health - Damage)로 갱신합니다.
  • Branch 노드: Health가 0보다 작거나 같아지는지 확인합니다.
파괴 로직 (Health <= 0일 때)
  • Branch의 True에서 먼저 bDestroyed = true로 바꿔 효과와 타이머의 중복 실행을 막습니다.
  • 메시의 Set Collision Enabled(Query And Physics)를 확인한 다음 Set Simulate Physics(true)로 전환합니다.
  • Static Mesh Component의 Add Impulse 노드 (선택 사항): 데미지를 준 방향으로 상자가 튕겨 나가도록 Add Impulse를 적용하여 파괴 효과를 강화합니다.
    • AnyDamage에는 Hit Result가 없습니다. 유효한 Damage Causer의 위치에서 상자 쪽으로 방향을 계산하고, 영벡터가 아닌 경우 정규화해 충격량을 만듭니다. 정확한 접촉점·법선이 필요하면 Apply Point Damage와 Event Point Damage로 별도 연결합니다. Instigator Controller에서 임의의 총알 Hit Result를 읽을 수는 없습니다.
  • 파괴 사운드 및 이펙트: Play Sound at Location 노드와 Spawn Emitter at Location (또는 Spawn Niagara System at Location) 노드를 사용하여 파괴 효과를 추가합니다. (이펙트 에셋 미리 준비)
  • 타이머를 이용한 액터 제거 (선택 사항): Set Timer by Event를 사용하여 5초 후 Destroy Actor 노드를 호출하여 부서진 상자가 월드에서 사라지도록 합니다. (정리 목적)

총알에 데미지 적용 로직 추가

이제 플레이어의 총알이 BP_DestructibleBox에 닿으면 데미지를 주도록 구현합니다.

BP_Bullet (총알 액터) 블루프린트 열기: 총알 블루프린트가 없다면 Actor 기반 BP_Bullet을 생성합니다. Sphere Collision을 루트로 두고 Projectile Movement의 Updated Component로 사용하며 Sweep과 상자에 대한 Block 응답을 설정합니다. 스폰 시 발사 Pawn을 Instigator로 전달하고 자기 자신과 발사자를 충돌 대상에서 제외합니다.

Sphere Collision의 On Component Hit 이벤트
  • Other Actor를 Cast To BP_DestructibleBox로 캐스팅합니다.
  • 캐스팅 성공 시, Apply Damage 노드를 호출합니다.
    • Damaged Actor: 캐스팅된 BP_DestructibleBox
    • Base Damage: 25.0 등으로 설정합니다.
    • Damage Causer: 총알 액터(Self)
    • Instigated By: 총알의 Get Instigator Controller로 얻은 발사자의 컨트롤러
  • 총알 파괴: 피해 적용 뒤 총알을 파괴합니다. 벽에 닿아 캐스트가 실패한 경로도 총알을 제거하도록 연결합니다. 멀티플레이에서는 서버가 이 판정을 수행하고 필요한 상자 상태·효과를 따로 복제합니다.

테스트 및 개선

레벨에 BP_DestructibleBox를 여러 개 배치하고 플레이어 캐릭터가 총을 쏘아 체력이 감소하고 0에서 물리 이동·효과·지연 제거가 한 번 실행되는지 확인합니다.

개선 사항
  • 데미지 유형: 다른 종류의 데미지(폭발 데미지, 근접 데미지)에 따라 다르게 반응하도록 Damage Type Class를 활용합니다.
  • 다양한 파괴 단계: 상자가 한 번에 부서지지 않고, 금이 가거나 일부가 떨어져 나가는 등 여러 단계의 파괴 상태를 구현할 수 있습니다. (여러 개의 스태틱 메시 컴포넌트 사용 또는 머티리얼 변화)
  • 파티클 시스템 연동: 총알이 닿을 때마다 스파크 이펙트를 생성하고, 파괴 시 연기 및 파편 이펙트를 추가합니다.
  • 최적화: 너무 많은 파편 액터가 생성되지 않도록 수명을 제한하거나, Object Pool 패턴을 사용하여 재활용합니다.

실패 증상과 복구

  • 증상: 총알이 상자를 맞췄는데 데미지가 적용되지 않음
    • 원인: OnComponentHit가 발생하지 않거나 Cast To BP_DestructibleBox 실패
    • 복구: Projectile Movement의 Updated Component/Sweep과 양쪽 Blocking 응답을 확인합니다. 물리 시뮬레이션 충돌 경로라면 Simulation Generates Hit Events도 확인하고, 캐스트·서버 권한·Can Be Damaged를 점검합니다.
  • 증상: 상자가 0 체력인데도 움직이지 않음
    • 원인: Branch(Health <= 0) 경로 미연결 또는 Set Simulate Physics 미설정
    • 복구: Event AnyDamage -> Health 갱신 -> Branch -> True 흐름이 끊기지 않았는지 점검하고 Set Simulate Physics(true)를 확인합니다.
  • 증상: 파괴 후 상자가 공중으로 과도하게 튀어오름
    • 원인: Add Impulse 강도 과다
    • 복구: 충격 벡터 크기를 절반 이하로 줄여 시작하고(예: 1200 -> 600), 최종 게임 카메라 거리에서 다시 보정합니다.

다른 동적 환경 상호작용 예시

  • 움직이는 문/플랫폼
    • BP_MovingDoor 액터에 Static Mesh Component (문)를 추가합니다.
    • 문 앞에 Box Collision 컴포넌트를 배치하여 트리거 볼륨으로 사용합니다.
    • Box Collision의 On Component Begin Overlap (플레이어가 겹쳤을 때) 이벤트에서 Timeline 노드를 사용하여 문 Static Mesh의 Set Relative Location을 애니메이션합니다.
    • On Component End Overlap에서 Timeline을 역재생하여 문을 닫습니다.
  • 물리 기반 스위치/레버
    • BP_Lever 액터에 Static Mesh Component (레버)를 추가하고 Simulate Physics를 활성화합니다.
    • Physics Constraint Component를 추가하여 레버가 한 축으로만 회전하도록 제한합니다.
    • 레버의 On Component Hit 또는 On Component Begin Overlap 이벤트를 사용하여 플레이어가 레버를 조작하거나 특정 오브젝트가 닿았을 때 제약의 현재 Swing/Twist 각도나 기준에 대한 상대 회전을 읽고, 특정 각도에 도달하면 문을 열거나 다른 이벤트를 발생시킵니다. 각속도는 회전 각도와 다른 값이므로 Get Physics Angular Velocity를 각도 임계값과 직접 비교하지 않습니다.
  • 환경적 위험 요소 (용암)
    • BP_Lava 액터에 Static Mesh Component (용암 시각 표현)와 Box Collision Component (트리거)를 추가합니다.
    • Box Collision의 Collision Presets를 OverlapAll로 설정합니다.
    • On Component Begin Overlap 이벤트에서 Other Actor를 Cast To BP_PlayerCharacter로 캐스팅합니다.
    • 캐스팅 성공 시 겹친 Actor별 타이머 핸들을 관리하거나, 겹친 Actor 집합을 단일 타이머 콜백에서 순회하며 서버에서 Apply Damage를 호출합니다. 입력 없는 타이머 콜백 안에서 유효한 대상을 읽습니다.
    • 마지막 관련 컴포넌트가 나간 Actor를 집합에서 제거하고 더 이상 대상이 없으면 타이머를 해제합니다. EndPlay에서도 타이머와 참조를 정리합니다.

동적 환경 상호작용은 게임 월드가 플레이어 입력과 게임 이벤트에 반응하도록 만드는 방식입니다.

복잡한 시스템보다 작은 상호작용 단위부터 구현하고 확장하는 편이 안정적입니다.


이번 절에서는 플레이어의 행동이나 게임 이벤트에 따라 반응하고 변화하는 동적 환경 상호작용의 기본 구현 방법에 대해 알아보았습니다.

파괴 가능한 오브젝트, 움직이는 문, 물리 기반 스위치 등 다양한 예시를 통해 물리, 콜리전, 이벤트 처리의 통합적인 활용법을 살펴보았습니다.