[Unity] 캐릭터 제어 최적화 및 상호작용 시스템 구축 가이드

정광훈(Unity_9기)·2026년 3월 27일

TIL (Today I Learned)

목록 보기
109/110

유니티에서 플레이어 캐릭터를 만들 때 반드시 체크해야 할 물리 설정과 개발 편의를 위한 디버깅 팁,
그리고 코드 가독성을 높이는 관례를 정리했습니다.


1. 플레이어 Rigidbody2D 핵심 설정

2D 탑다운 또는 플랫포머 게임에서 플레이어 이동을 구현할 때,
물리 엔진에 의한 의도치 않은 회전을 막는 것이 중요합니다.

① Body Type: Dynamic

  • 설정: Dynamic
  • 설명: 중력, 마찰, 충돌 등 유니티 물리 엔진의 모든 영향을 받는 상태입니다.
  • 이유: 플레이어 캐릭터는 다른 물체와 부딪히고 이동해야 하므로 가장 기본이 되는 설정입니다. (탑다운 게임이라면 Gravity Scale0으로 두어 공중으로 떨어지지 않게 조절합니다.)

② Collision Detection: Continuous

  • 설정: Continuous
  • 설명: 충돌 감지를 '연속적'으로 수행합니다.
  • 이유: 기본값인 Discrete는 프레임 단위로 끊어서 감지하기 때문에, 캐릭터가 너무 빨리 움직이면 벽을 뚫고 지나가는 '터널링 현상'이 발생할 수 있습니다. 플레이어는 벽을 뚫으면 안 되기 때문에 Continuous로 설정하여 이를 방지합니다.

③ Interpolate: Interpolate

  • 설정: Interpolate (보간)
  • 설명: 이전 프레임의 위치를 바탕으로 현재 위치를 부드럽게 연결하여 그려줍니다.
  • 이유: 유니티의 물리 연산(FixedUpdate)과 화면 렌더링(Update) 주기가 일치하지 않아 발생하는 '미세한 떨림(Jittering)' 현상을 잡아줍니다. 카메라가 플레이어를 따라다닐 때 캐릭터가 덜덜 떨려 보인다면 이 설정을 반드시 켜야 합니다.

✅ Constraints: Freeze Rotation Z

  • 문제 상황: 캐릭터가 벽에 대각선으로 부딪히거나 NPC와 충돌할 때, 팽이처럼 빙글빙글 도는 현상이 발생합니다.
  • 해결 방법: Rigidbody2D 컴포넌트의 Constraints 항목에서 Freeze Rotation Z를 체크해야 합니다.
  • 이유: 물리 연산으로 인해 캐릭터의 Z축 회전 값이 변하는 것을 고정하여, 항상 정면(또는 설정된 방향)을 유지하게 합니다.

2. 기즈모(Gizmos) 활용하기: 항상 보이기 vs 선택 시 보이기

상호작용 범위나 공격 사거리를 씬(Scene) 창에서 시각적으로 확인할 때 사용합니다.

🔍 OnDrawGizmos()

  • 특징: 오브젝트 선택 여부와 관계없이 항상 씬 창에 그려집니다.
  • 용도: NPC의 감지 범위, 고정된 함정의 구역 등 맵 배치 시 상시 확인이 필요한 경우에 적합합니다.
private void OnDrawGizmos()
{
    Gizmos.color = Color.yellow;
    Gizmos.DrawWireSphere(transform.position, 1.5f);
}

🔍 OnDrawGizmosSelected()

  • 특징: 하이라키에서 해당 오브젝트를 클릭(선택)했을 때만 그려집니다.
  • 용도: 플레이어의 사거리처럼 평소에는 가려져 있어야 씬 창이 깔끔한 경우에 사용합니다.
private void OnDrawGizmosSelected()
{
    Gizmos.color = Color.red;
    Gizmos.DrawWireSphere(transform.position, 1.5f);
}

3. name vs gameObject.name

유니티에서 오브젝트의 이름을 가져올 때 두 방식 모두 결과는 동일하지만,
실무에서는 gameObject.name을 더 선호합니다.

비교 항목namegameObject.name
정체this.name (단축키)this.gameObject.name (명시적 접근)
가독성변수명과 혼동될 여지 있음게임 오브젝트의 이름임이 명확함
성능차이 없음차이 없음

💡 왜 gameObject.name을 더 많이 쓰나요?

  1. 명확성: name이라고만 적으면 클래스 내부에 선언된 임의의 문자열 변수인지,
    유니티 제공 속성인지 헷갈릴 수 있습니다.
  2. 객체지향적 관점: "이 스크립트가 붙은 게임 오브젝트의 이름을 가져온다"는 주체가 명확해져 유지보수가 용이합니다.
  3. 실수 방지: 협업 시 다른 개발자가 작성한 변수와 충돌하는 것을 방지할 수 있습니다.

4. 요약 및 팁

  • 물리 기반 이동 시 Freeze Rotation Z는 필수입니다.
  • 상호작용 범위 확인은 OnDrawGizmos로 항상 띄워두면 기획 수정이 편합니다.
  • 코드 작성 시에는 가급적 gameObject.name을 사용하여 의도를 명확히 전달하세요.

0개의 댓글