이 글은 유니티 자습서의 글을 번역한 글 입니다. 원문은 여기에서 확인할 수 있습니다.



이 글에서는 게임에서 물리를 사용할 때의 모범 사례를 약간 살펴볼 것이고, 왜 이렇게 써야하는지에 대한 증명도 다룰 것 입니다.

Layer와 Collision Matrix

따로 설정하지 않은 모든 게임 오브젝트는 기본적으로 Default 레이어로 생성이 되고 이는 모든 것과 충돌됨을 의미합니다. 이는 매우 비효율적입니다. 어떤 것끼리 서로 충돌을 할 지 설정을 하세요. 이렇게 하기 위해서는 오브젝트의 타입에 맞게 다른 레이어를 설정해야 합니다. 새로운 레이어가 생길 때마다 Collision Matrix에 새로운 행과 열이 생기게 됩니다. 이 매트릭스는 레이어들 간의 상호작용을 정의하게 됩니다. 기본적으로, 새로운 레이어를 추가하면, Collision Matrix는 새 레이어를 다른 모든 레이어와 충돌하게 끔 설정합니다. Collision Matrix를 제대로 설정함으로써 불필요한 충돌 처리를 피할 수 있습니다.

시연 목적으로 간단한 데모를 만들었는데, 여기에서는 하나의 박스 컨테이너 안에 2000 개의 오브젝트(빨간색 1000개와 초록색 1000개)를 생성합니다. 녹색 오브젝트는 같은 녹색 오브젝트와 컨테이너 벽과만 상호 작용을 해야하고, 빨간색의 경우도 마찬가지 입니다. 테스트 중 하나에서, 모든 인스턴스가 Default 레이어에 속하고, 충돌 리스너에 있는 게임 오브젝트 태그를 문자열 비교함으로써 상호 작용이 이루어지게 됩니다. 다른 테스트에서는, 각 오브젝트 타입은 각각의 레이어로 설정되고, Collision Matrix를 통해서 각 레이어의 상호작용 설정을 하게 됩니다. 이 경우에는 필요한 충돌만 발생하기 때문에 문자열 테스트가 필요없습니다.

그림 1 : Collision Matrix 설정
그림 1 : Collision Matrix 설정

아래 이미지는 시연에서 가져온 결과입니다. 이 시연에는 간단한 매니저 클래스가 있는데, 이 클래스는 충돌의 수를 세고, 5초 후에 자동으로 멈추게 합니다. 공통의 레이어를 사용하는 경우에 불필요한 여분의 충돌이 발생하는 부분이 매우 인상깊습니다.

그림 2 : 5초 동안의 충돌
그림 2 : 5초 동안의 충돌

더 자세한 데이터를 위해 물리 엔진의 프로파일러 데이터도 캡쳐했습니다.

그림 3 : (공통 레이어 vs 분리한 레이어) 물리 프로파일러 데이터
그림 3 : (공통 레이어 vs 분리한 레이어) 물리 프로파일러 데이터

프로파일러 데이터에서 볼 수 있듯이, 물리에서 CPU 사용량의 차이가 큰 것을 확인할 수 있습니다. 단일 레이어를 사용하게 되면 평균 27.7 ms 정도이고, 레이어를 분리해서 사용하게 되면 평균 17.6 ms 정도 입니다.

RAYCASTS

레이캐스팅은 물리 엔진에서 굉장히 유용하고 강력한 도구입니다. 이는 우리가 특정 방향으로 특정 길이의 광선(ray)을 쏠 수 있도록 해주고, 이를 통해서 어떤 것과 부딪혔는지를 알 수 있습니다. 하지만, 이는 비싼 동작입니다 ; 이 성능은 광선의 길이와 씬에서의 콜라이더의 타입에 크게 영향을 받습니다.

이를 사용하는 데에 도움이 될 수 있는 몇가지 힌트를 드리겠습니다.

  • 이는 명확합니다. 하지만, 작업을 진행하기 위한 광선은 최소한으로 사용하십시오.
  • 필요 이상의 광선 길이를 확장하지 마십시오. 광선이 길어질 수록, 더 많은 오브젝트가 테스트 되어야 합니다.
  • FixedUpdate() 함수 안에서 Raycast를 사용하지 마십시오. 가끔은 Update() 에서의 사용도 과잉 사용이 될 수 있습니다.
  • 여러분이 사용하고 있는 콜라이더의 타입을 알고 계십시오. 메쉬 콜라이더에 대한 레이캐스팅은 정말 비쌉니다.
    • 좋은 해결책은 자식에 기본 콜라이더(primitive colliders)를 사용하고, 대략적으로 매쉬와 비슷한 모양이 되도록 노력하는 것 입니다. 부모 Rigidbody 밑에 있는 모든 자식 콜라이더는 합성 콜라이더처럼 동작할 것 입니다.
    • 메쉬 콜라이더의 사용이 절실한 경우에는 최소한 그들을 볼록하게 되도록 사용하십시오.
  • 광선이 무엇을 맞춰야하는지를 확실히 하고, 항상 raycast 함수에 레이어 마스크를 지정하도록 하십시오.
    • 이는 공식 문서에 잘 설명되어 있지만 raycast 함수에 사용해야할 값은 layer id가 아닌 bitmask 값 입니다.
    • 따라서 만약 레이어 아이디가 10인 오브젝트를 맞추고 싶다면, 10이 아닌 1<<10 (1을 왼쪽으로 10만큼 비트 이동) 을 사용하세요.
    • 레이어 10이 아닌 나머지 모든 것들을 맞추고 싶은 경우에는, 비트 보수 연산자인 ~을 사용하세요. 그러면 비트 마스크의 각 비트의 역을 구할 수 있습니다.


어떤 오브젝트가 녹색 박스에서 충돌하는 광선을 쏘는 그런 간단한 시연을 하나 만들었습니다.

그림 4 : 간단한 Raycast 시연 씬
그림 4 : 간단한 Raycast 시연 씬

이 시연에서 저는 앞에서 말한 내용을 지지할 수 있는 프로파일러 데이터를 뽑아내기 위해 광선의 수와 길이를 조절해 보았습니다. 아래의 그래프를 보면 광선의 수와 길이가 성능에 얼마나 영향을 미치는지 알 수 있습니다.

그림 5 : 성능에 영향을 미치는 광선의 수
그림 5 : 성능에 영향을 미치는 광선의 수

그림 6 : 성능에 영향을 미치는 광선의 길이
그림 6 : 성능에 영향을 미치는 광선의 길이

시연의 목적으로, 기본 콜라이더를 메쉬 콜라이더로 변경하기로 결정했습니다.

그림 7 : 메쉬 콜라이더 씬 (콜라이더 당 110 개의 버텍스)
그림 7 : 메쉬 콜라이더 씬 (콜라이더 당 110 개의 버텍스)

그림 8 : 기본 콜라이더 vs 메쉬 콜라이더 물리 프로파일러 데이터
그림 8 : 기본 콜라이더 vs 메쉬 콜라이더 물리 프로파일러 데이터

프로파일 그래프에서 볼 수 있듯이, 메쉬 콜라이더에 대한 레이캐스팅은 물리 엔진이 프레임당 더 많은 작업을 하도록 만듭니다.

Physics 2D vs 3D

어떤 물리 엔진이 여러분의 프로젝트에 최고 적절한지 선택하십시오. 만약 2D 나 2.5D 게임(2D 평면에서 만드는 3D 게임)을 개발 중이라면, 3D 물리 엔진을 사용하는 것은 과한 선택입니다. 이 여분의 차원이 여러분의 프로젝트에서 불필요한 CPU 비용을 차지하게 됩니다. 두 물리 엔진의 성능 차이를 확인하고 싶다면, 저자가 이전에 작성한 글을 참고해 보세요.

http://x-team.com/2013/11/unity3d-v4-3-2d-vs-3d-physics/

RigidBody

RigidBody 컴포넌트는 오브젝트 간의 물리적 상호작용을 추가하기 위한 필수 컴포넌트 입니다. 콜라이더를 트리거로써만 사용하는 경우에도, OnTrigger 이벤트를 적절히 사용하기 위해서 게임 오브젝트에 RigidBody를 추가해야 합니다. RigidBody를 가지고 있지 않은 게임 오브젝트는 정적 콜라이더로 간주됩니다. 정적 콜라이더를 움직이려는 시도를 하게 되면, 물리 엔진이 물리 세계 전체를 다시 계산하도록 강제하기 때문에 극도로 비효율적으로 동작하게 됩니다. 다행히도, 프로파일러는 여러분이 이러한 시도를 할 때 CPU 프로파일러 탭에서 경고를 보여주기 때문에 이러한 문제를 알아차릴 수 있습니다. 정적 콜라이더를 움직일 때의 영향을 좀 더 확실히 시연해 보기 위해, 첫번째 데모의 움직이는 모든 오브젝트에서 RigidBody를 제거했고, 이에 대한 프로파일러 데이터를 캡쳐했습니다.

그림 9 : 움직이는 정적 콜라이더 경고
그림 9 : 움직이는 정적 콜라이더 경고

그림에서 볼 수 있듯이, 총 2000개의 경고가 생성되었고, 이는 하나하나가 움직이는 게임 오브젝트에 대한 것입니다. 또한 물리에 사용된 평균 CPU 량도 대략 17.6ms에서 35.85ms로 증가했습니다. 게임 오브젝트를 움직일 때 RigidBody를 붙이는 것은 필수적입니다. 만약 여러분이 게임 오브젝트를 직접적으로 조정하고 싶다면, rigidbody 속성 중에 kinematic을 마트하시면 됩니다.

Fixed TimeStep

TimeManager의 Fixed Timestep 값을 변경하는 것은, FixedUpdate()와 물리 업데이트 비율에 직접적인 영향을 미칩니다. 이 값을 변경함으로써 물리에서 정확성과 CPU 사용 시간 사이의 조절을 할 수 있습니다.

요약

이번에 다룬 주제는 설정과 구현이 쉽고, 여러분이 개발하는 대부분의 프로젝트는 물리 엔진을 사용할 것이기 때문에 성능의 차이를 가져올 수 있을 것 입니다.

+ Recent posts