안동민 개발노트

본문 시작

동적 오브젝트 및 상호작용

타임라인·애니메이션·물리 제어로 문·스위치·플랫폼이 입력에 반응하게 만들고 동적 상태를 안정적으로 관리합니다.

UI로 상호작용 신호를 전달했다면, 이제는 그 결과를 월드 안에서 직접 체감하게 만들어야 합니다.

이번 절의 주제는 동적 오브젝트 반응입니다.

문이 열리고, 스위치가 움직이고, 플랫폼이 올라가는 변화는 단순한 연출을 넘어 플레이어에게 입력한 행동이 실제로 반영됐다는 확신을 줍니다.

여기서는 언리얼 엔진에서 동적 반응을 안정적으로 구현하는 흐름을 다룹니다.

적용이 끝나면 레벨은 정적인 배경이 아니라 플레이어 행동에 응답하는 공간으로 바뀝니다.


동적 오브젝트 변화의 중요성

플레이어의 상호작용에 대한 환경의 동적 반응은 게임 플레이와 몰입감에 핵심적인 영향을 미칩니다.

  • 즉각적인 피드백: 플레이어의 행동이 게임 세계에 즉각적인 영향을 미쳐, 자신의 행동에 대한 보상을 느끼고 만족감을 얻습니다.
  • 게임 플레이의 흐름: 문이 열리거나 플랫폼이 움직이는 것은 단순히 시각적 효과를 넘어, 플레이어가 다음 지역으로 이동하거나 새로운 퍼즐을 해결하는 게임 플레이의 흐름을 만듭니다.
  • 반응형 환경 표현: 정적인 배경이 아니라 플레이어 행동에 따라 상태가 바뀌는 환경으로 보이게 합니다.
  • 내러티브 전달: 특정 오브젝트의 변화가 스토리 진행의 단서가 되거나, 세계의 비밀을 드러내는 역할을 할 수 있습니다.

동적 오브젝트 변화를 위한 핵심 기술

언리얼 엔진에서 오브젝트의 동적 변화를 구현할 때 주로 사용되는 기술들입니다.

타임라인 (Timeline)

  • 역할: 시간에 따른 값의 변화를 그래픽적으로 정의하여, 오브젝트의 위치, 회전, 스케일, 또는 머티리얼 파라미터 등을 부드럽게 보간(Lerp)하는 데 사용됩니다.
  • 장점: 복잡한 애니메이션 코딩 없이 직관적으로 오브젝트의 움직임을 제어할 수 있습니다.
  • 주요 기능
    • Float Track: 시간에 따른 단일 부동 소수점 값(예: 0.0에서 1.0까지) 변화를 정의합니다.
    • Vector Track: 시간에 따른 3D 벡터 값(위치, 스케일 등) 변화를 정의합니다.
    • Event Track: 특정 시간 지점에 이벤트를 발생시켜 사운드 재생, 파티클 스폰 등을 트리거할 수 있습니다.
    • Play: 타임라인의 현재 재생 위치에서 정방향으로 진행합니다. 처음부터 재생하려면 Play from Start를 사용합니다.
    • Reverse: 타임라인을 현재 위치에서 역재생합니다.
    • Stop: 타임라인 재생을 멈춥니다.
    • Update: 매 프레임마다 현재 타임라인의 값을 출력하여 오브젝트 속성에 적용할 수 있도록 합니다.
    • Finished: 타임라인 재생이 끝났을 때 이벤트를 발생시킵니다.
  • 활용 예시: 문 열기/닫기, 플랫폼 이동, 조명 밝기 변화, 깃발 흔들림 등.

머티리얼 파라미터 (Material Parameters) 제어

  • 역할: 오브젝트에 적용된 재질(Material)의 특정 값을 블루프린트에서 동적으로 변경하여 시각적 효과를 부여합니다.
  • 주요 노드
    • Set Scalar Parameter Value on Materials: 단일 Float 값 파라미터 변경.
    • Set Vector Parameter Value on Materials: Vector (색상, 위치 등) 값 파라미터 변경.
    • Set Material: 오브젝트의 재질 자체를 변경합니다.
  • 활용 예시
    • 상호작용 시 오브젝트의 색상 변경 (하이라이트, 활성화/비활성화 상태 표시)
    • 스위치를 누르면 불빛이 켜지는 효과 (Emissive 파라미터 조절)
    • 벽이 파괴될 때 금이 가거나 텍스처가 변하는 효과
    • 물에 젖었을 때 오브젝트의 러프니스(Roughness) 변경 (8장 4절 날씨 효과 참조)

물리 시뮬레이션 제어

  • 역할: 오브젝트에 힘을 가하거나, 물리 시뮬레이션 상태를 변경하여 동적인 움직임을 유발합니다.
  • 주요 노드
    • Add Impulse: 오브젝트에 순간적인 힘을 가합니다. (예: 총알에 맞거나 폭발로 날아감)
    • Add Force: 힘이 작용할 동안 매 프레임 호출합니다. (예: 바람에 의해 움직이는 오브젝트)
    • Set Simulate Physics: 오브젝트의 물리 시뮬레이션 활성화/비활성화.
    • Set Physics Linear/Angular Velocity: 오브젝트의 선형/각속도를 직접 설정합니다.
  • 활용 예시
    • 플레이어가 스위치를 누르면 특정 오브젝트가 밀려나거나 떨어지는 퍼즐.
    • 문이 파괴될 때 잔해가 물리 시뮬레이션되어 흩어지는 효과.
    • 특정 조건 만족 시 캐릭터가 래그돌 상태로 전환.

스폰/디스폰 및 가시성 제어

  • 역할: 특정 조건에 따라 오브젝트를 생성하거나 제거하고, 보이거나 보이지 않게 하여 환경을 동적으로 변화시킵니다.
  • 주요 노드
    • Spawn Actor From Class: 새로운 액터를 레벨에 생성합니다. (예: 파괴 시 파편 생성, 특정 시간에 몬스터 스폰)
    • Destroy Actor: 액터를 레벨에서 제거합니다. (예: 주운 아이템 제거, 파괴된 오브젝트 제거)
    • Set Visibility: Scene Component의 가시성을 바꿉니다. 액터 전체는 Set Actor Hidden In Game을 사용하며 숨김과 충돌·Tick·물리는 별개입니다. (예: 숨겨진 길 나타내기, 아이템 숨기기)
  • 활용 예시
    • 플레이어가 퍼즐을 풀면 숨겨진 길이 나타나는 효과.
    • 트리거 영역에 진입 시 함정이 나타나는 효과.
    • 아이템 획득 시 해당 아이템 메시를 제거.

동적 오브젝트 및 상호작용 구현 예시

이동하는 플랫폼을 만들어 플레이어 상호작용으로 제어해 봅시다.

새로운 액터 블루프린트 생성: BP_MovingPlatform 이라는 이름의 액터 블루프린트를 생성합니다.

컴포넌트 추가
  • Static Mesh (PlatformMesh): 플랫폼 메시를 루트 컴포넌트로 두고 Movable, Simulate Physics 끔, 필요한 Block 충돌로 설정합니다. 이후 Set Actor Location의 Sweep은 루트만 검사합니다.
  • Box Collision (InteractionTrigger): 플랫폼을 작동시킬 트리거 볼륨. Custom에서 Pawn만 Overlap, 나머지는 Ignore로 두고 플레이어 캡슐과 양쪽 Generate Overlap Events를 활성화합니다.
변수 추가
  • StartLocation (Vector): BeginPlay에서 저장할 시작 월드 위치.
  • EndLocation (Vector): 시작 월드 위치에 이동 오프셋을 더한 목표 위치.
  • MoveSpeed (Float): 양수 보간 계수(초⁻¹). Instance Editable로 조절하며 일정한 cm/s 속도가 아닙니다.
  • bIsMoving (Boolean): 플랫폼이 현재 움직이는지 여부.
  • TargetLocation (Vector): 현재 플랫폼이 향하고 있는 목표 위치.
이벤트 그래프 로직
  • Event BeginPlay
    • StartLocation 변수에 Get Actor Location (Self)의 현재 위치를 저장합니다.
    • EndLocation = StartLocation + (0, 0, 300)으로 정하고 TargetLocation은 StartLocation, bIsMoving은 False로 초기화합니다.
  • InteractionTrigger 오버랩 이벤트
    • OnComponentBeginOverlap (InteractionTrigger) 시 Cast To PlayerCharacter로 플레이어 감지.
    • OnComponentEndOverlap (InteractionTrigger) 시 플레이어 이탈 감지.
    • 오버랩 중인 동안 UI 프롬프트 표시 (8장 2절 참고).
  • 상호작용 입력 이벤트
    • 플레이어가 Interact 입력을 받으면 후보 플랫폼 참조의 커스텀 이벤트를 호출합니다. 플랫폼은 자신의 InteractionTrigger에서 요청 플레이어가 겹치는지 재확인합니다. 다른 액터의 컴포넌트를 참조 없이 플레이어 그래프에서 직접 사용할 수는 없습니다.
    • 만약 오버랩 중이고 bIsMoving이 False라면
      • Set bIsMoving을 True로 설정합니다.
      • TargetLocation을 StartLocation과 EndLocation 중 현재 위치에서 먼 쪽으로 전환합니다. (Distance 노드를 사용하여 현재 위치와 StartLocation, EndLocation 중 어느 것이 더 가까운지 판단하여 TargetLocation을 설정합니다.)
  • Event Tick에서 플랫폼 이동 로직
    • Branch 노드를 사용하여 bIsMoving이 True일 때만 이동 로직을 실행합니다.
    • Lerp (Vector)
      • A 핀: Get Actor Location (Self)
      • B 핀: TargetLocation
      • Alpha 핀: Clamp(Get World Delta Seconds * MoveSpeed, 0.0, 1.0)
      • 결과를 Set Actor Location의 New Location에 연결하고 Sweep을 켭니다. Sweep Hit가 blocking이면 이동을 멈추고 막힘 피드백을 줍니다. 목표까지 막힘 없이 이동하는 경우를 아래 도착 조건으로 처리합니다.
    • 도착 감지: Vector Distance (Get Actor Location과 TargetLocation) 노드를 사용하여 플랫폼이 목표 위치에 충분히 가까워졌는지 확인합니다. (예: 거리가 10.0cm 미만)
    • 거리가 10cm 미만이면 목표 위치로 마지막 Sweep 이동을 시도합니다. 막히지 않았을 때 위치를 확정하고 bIsMoving=False로 둡니다. 다음 입력에서 반대 끝점을 고릅니다.
  • 사운드 및 파티클: 플랫폼이 움직이기 시작할 때 사운드를 재생하고, 움직이는 동안 먼지 파티클을 생성하는 등의 효과를 추가합니다.

텍스트 기반 재현 기준

시각 자료 없이 동일한 결과를 재현하려면 아래 값부터 고정하고 시작하는 것이 좋습니다.

  • 에디터 경로: BP_MovingPlatform 열기 -> Components에서 InteractionTrigger 선택 -> Details > Collision
  • 필수 입력값
    • InteractionTrigger > Collision Presets: Custom, Pawn=Overlap, 나머지=Ignore
    • InteractionTrigger > Generate Overlap Events: True
    • MoveSpeed: 1.5
    • EndLocation: StartLocation 기준 Z + 300
    • 도착 판정 거리: 10.0cm
  • 기대 결과
    • 장애물이 없고 MoveSpeed=1.5이면 남은 거리의 일정 비율을 줄이며 접근합니다. 300cm에서 10cm 미만까지의 연속시간 근사는 약 2.27초이나 실제 Tick·충돌에 따라 달라지며 고정 도착 시간 보장은 아닙니다.
    • 목표 위치 도달 후 bIsMoving이 False로 전환되어 추가 이동이 멈춥니다.
    • 다시 상호작용하면 시작 위치로 역방향 이동합니다.

상호작용 실패 증상과 복구

  • 증상: 상호작용 키를 눌러도 플랫폼이 안 움직임
    • 원인: 오버랩 감지 실패 또는 bIsMoving 분기 연결 누락
    • 복구: Overlap이 후보 참조를 저장하는지, 이후 별도 Interact 입력이 그 플랫폼의 커스텀 이벤트를 호출하는지 확인합니다.
  • 증상: 플랫폼이 떨리면서 목표점에 수렴하지 않음
    • 원인: Lerp의 Alpha가 과도하거나 도착 판정 거리 값이 0에 가까움
    • 복구: Alpha의 0~1 Clamp, 양수 MoveSpeed, 목표 위치 고정, Sweep 막힘 여부와 도착 후 정지 처리를 차례로 확인합니다.
  • 증상: 플랫폼이 너무 빠르게 순간이동함
    • 원인: Set Actor Location 입력이 Lerp 결과가 아닌 TargetLocation 직접 연결
    • 복구: Set Actor Location의 New Location 핀이 반드시 Lerp(Vector) 결과를 받도록 노드 연결을 정리합니다.

동적 오브젝트 및 상호작용 최적화

  • 타임라인의 효율적 사용
    • 너무 많은 타임라인을 동시에 재생하지 않도록 합니다.
    • 불필요하게 긴 타임라인이나 복잡한 키프레임은 피합니다.
  • 물리 시뮬레이션 제한
    • 오브젝트가 반드시 물리 시뮬레이션될 필요가 없다면 Set Actor Location/Rotation/Scale 등 직접적인 트랜스폼(Transform) 조작을 사용합니다. 물리 시뮬레이션은 성능 비용이 더 큽니다.
    • 파괴 가능한 오브젝트의 경우, 파편의 물리 시뮬레이션 시간을 제한하거나, 일정 시간이 지나면 파편을 제거(Destroy Actor)하여 성능 부하를 줄입니다.
  • 가시성 (Visibility) 및 컬링 (Culling)
    • 렌더링에서 안 보이는 것과 게임플레이 계산 중지는 별개입니다. 플레이어나 네트워크 상태에 영향을 주지 않는 대상만 별도 로직으로 애니메이션·Tick·물리를 줄입니다.
  • 컴포넌트 분리: 복잡한 상호작용 로직은 여러 개의 컴포넌트나 자식 블루프린트로 나누어 관리하면 가독성과 최적화에 용이합니다.
  • 네트워크 레플리케이션 고려: 멀티플레이어 게임에서는 동적 오브젝트의 상태(위치, 움직임, 활성화 여부)가 모든 클라이언트에 정확하게 동기화되어야 합니다. Replication 설정을 신중하게 구성해야 합니다.

이동 중 입력을 막고, 도착 또는 막힘에서 bIsMoving을 해제하는 경로를 각각 테스트합니다. 멀티플레이에서는 서버가 이동 상태를 정하고 필요한 위치·상태를 복제하도록 별도 구현합니다.


동적 오브젝트 상호작용은 레벨을 살아 있는 공간으로 보이게 만드는 핵심 요소입니다.

타임라인 애니메이션, 머티리얼 파라미터 제어, 물리 시뮬레이션, 스폰/디스폰과 가시성 제어를 함께 적용하면 반응의 밀도를 높일 수 있습니다.

플레이어가 탐험 중에 행동하면 세계가 바뀐다는 경험을 계속 받도록 설계해 보세요.