Unity 물리 엔진 소개 - 2019.3

Tutorial

Beginner

+10XP

30 mins

83

Unity Technologies

Unity 물리 엔진 소개 - 2019.3

물리 엔진을 사용하면 중력, 속도, 가속도 등 현실 세계와 유사하게 힘을 가해서 오브젝트를 제어할 수 있습니다. 이 튜토리얼에서는 이에 대한 여러 가지 핵심 개념을 소개합니다.

1. Unity 물리 엔진 소개

이 튜토리얼은 Unity 2019.4.11f1 LTS 버전에서 검증을 마쳤습니다. https://learn.unity.com/tutorial/intro-to-the-unity-physics-engine-2019-3

물리 엔진을 사용하면 중력, 속도, 가속도 등 현실 세계와 유사하게 힘을 가해서 오브젝트를 제어할 수 있습니다. 이 튜토리얼에서는 이에 대한 여러 가지 핵심 개념을 소개합니다.

2. 콜라이더

콜라이더를 사용하면 Unity에서 게임 오브젝트가 서로 충돌하거나 교차하는 경우를 인식할 수 있습니다.

충돌이 인식되려면 게임 오브젝트에 리지드바디 컴포넌트가 연결되어 있어야 합니다.

콜라이더 유형에는 박스 콜라이더, 캡슐 콜라이더, 메시 콜라이더, 스피어 콜라이더, 터레인 콜라이더, 휠 콜라이더 등이 있습니다(그림 01). 메시 콜라이더 사용 시 컴퓨팅 리소스가 많이 소모된다는 점에 유의하시기 바랍니다. 표시되는 메시의 디테일 수준이 높다면 충돌에 리소스가 많이 소모되지 않는 메시를 사용하는 것이 좋습니다. ProBuilder를 사용하면 더 간단한 프록시 메시를 구축하여 더 복잡한 메시 셰이프를 표현할 수 있습니다.

GameObject 드롭다운 메뉴에 있는 Unity의 다양한 3D 오브젝트 중에서 콜라이더를 확인할 수 있습니다.

별도의 게임 오브젝트 또는 비어 있는 게임 오브젝트에 대해 Unity 물리 엔진을 활성화하려면, 인스펙터(Inspector) 창에서 Add Component 버튼을 선택하고 Physics를 선택한 다음 콜라이더 유형을 지정합니다. 여기서는 Box Collider를 선택했습니다(그림 02).

3. 트리거

"Is Trigger" 체크박스를 선택하면 트리거가 활성화됩니다. 이는 콜라이더와 동일하게 작동하지만 컴포넌트의 물리를 비활성화하기 때문에 오브젝트가 영역을 통과할 수 있습니다. 오브젝트가 트리거 영역에 들어가거나 해당 영역에서 나올 때 이벤트를 호출할 수 있습니다(그림 03).

오브젝트 중 하나에는 리지드바디 컴포넌트가 연결되어 있어야 합니다. 트리거 내에서 움직이는 오브젝트에 이 컴포넌트가 연결된 경우가 가장 좋습니다.

4. 리지드바디

Rigidbody 컴포넌트(그림 04)를 이용하면 게임 오브젝트가 중력과 같은 물리 프로퍼티의 영향을 받습니다. 여기에는 질량, 속도, 항력(공기 저항) 등의 프로퍼티도 포함됩니다. 질량이 큰 오브젝트는 질량이 작은 오브젝트의 영향을 덜 받으며 그 반대의 경우도 마찬가지입니다. 항력은 시간에 따른 속도의 감쇠에 영향을 주며, 각항력은 각속도에 영향을 미칩니다.

Is Kinematic 체크박스를 선택하면 리지드바디가 Unity 물리 엔진을 통해 다른 오브젝트에 영향을 줄 수 있지만, 그 자체는 영향을 받지 않습니다. 예를 들어 VR 게임의 손 아바타는 물리를 통해 오브젝트와 상호 작용하되, 손에는 물리가 적용되지 않도록 하려는 경우에 사용할 수 있습니다.

Is Kinematic 체크박스는 애니메이션 엔진에서 제어하는 오브젝트에도 영향을 줍니다. Is Kinematic 체크박스를 선택하면 애니메이션 엔진이 오브젝트에 영향을 주고, 선택을 해제하면 물리 엔진이 제어를 계속합니다.

보간 설정에서는 충돌 점검 방식을 감지합니다. 드롭다운에서 Interpolate 또는 Extrapolate를 선택할 수 있습니다.

  • Interpolate: 애니메이션 타임라인의 이전 프레임 정보를 기반으로 오브젝트의 움직임이 매끄러워집니다.
  • Extrapolate: 다음 프레임에 대한 추측을 기반으로 오브젝트의 움직임이 매끄러워집니다.

Collision Detection 드롭다운 메뉴에서는 충돌 점검이 이루어지는 속도를 설정할 수 있습니다.

  • Discrete: 기본 설정입니다.
  • Continuous: 정적 오브젝트와 상호 작용하는 빠른 속도의 오브젝트입니다.
  • Continuous Dynamic: 빠른 속도의 다른 오브젝트와 상호 작용하는 빠른 속도의 오브젝트입니다.
  • Continuous Speculative: 예측 기반 충돌 점검을 수행합니다.

Constraints 체크박스에서는 오브젝트의 X, Y, Z 축 중에서 어떤 축을 고정할지 결정할 수 있습니다.

또한, 드롭다운 메뉴에서 Edit > Project Settings > Physics를 선택하면 Unity 물리 엔진의 요소 값을 재정의하고 변경할 수 있습니다(그림 05).

5. 스크립팅

다른 게임 오브젝트와 상호 작용할 때 콜라이더에 사용되는 함수는 다음과 같습니다.

OnCollisionEnter (Collision)

충돌이 인식되면 호출됩니다. 예를 들면 다음과 같습니다.

void OnCollisionEnter(Collision collision)
{
     if(collision.gameObject.CompareTag("Enemy")
     {
          //Hit the enemy
     }
}
OnCollisionStay (Collision)

충돌 중에 호출됩니다.

OnCollisionExit (Collision)

충돌이 정지하면 호출됩니다.

중력을 활성화하거나 비활성화하려면 useGravity 함수를 사용할 수 있습니다.

bool rigidBody.useGravity

특정 방향으로 힘을 추가하려면 .AddForce() 함수를 사용할 수 있습니다.

*rigidBody.AddForce(Vector3)

축 주위에 회전력을 추가하려면 .AddTorque() 함수를 사용할 수 있습니다.

rigidBody.AddTorque(Vector3, Force Mode)

FixedUpdate() 함수에서 AddForce 및 AddTorque를 호출하면 시간에 따라 이 힘이 적용됩니다.

6. 힘 모드

  • Acceleration: 일정한 비율로 증가하는 힘이 적용됩니다.
  • Force: 기본 설정이며, 질량을 고려하여 힘이 점진적으로 적용됩니다.
  • Impulse: 시간에 따라 점진적으로 형성되는 힘이 아닌 순간적인 힘이 적용됩니다.
  • VelocityChange: 다양한 방향으로 순간적인 힘을 가하며, 이때 질량은 무시됩니다.

7. Update 함수

  • Update: 프레임당 한 번 호출됩니다.
  • FixedUpdate: 프레임당 여러 번 호출됩니다. 물리 계산의 대부분은 FixedUpdate에서 호출됩니다. 이름에서 알 수 있듯 고정된 간격을 두고 계산이 수행됩니다.

8. 물리 머티리얼

물리 머티리얼은 표면의 마찰이 다른 표면과 상호 작용하는 방식을 제어합니다. 커스텀 머티리얼을 물리 콜라이더에 적용할 수 있습니다. 값을 지정할 수 있는 항목은 Dynamic Friction, Static Friction, Bounciness이며, Friction Combine 및 Bounce Combine 등의 파라미터를 커스터마이즈할 수 있습니다. 커스텀 물리 머티리얼을 만들려면 상단 메뉴 드롭다운에서 Assets > Create > Physic Material(그림 06) 순으로 선택합니다. 그런 다음 프로젝트(Project) 창에서 새로 생성된 물리 머티리얼을 선택하고, 게임 오브젝트의 인스펙터 창에 있는 Material 프로퍼티로 해당 머티리얼을 드래그하여 게임 오브젝트에 추가합니다.

9. 물리 조인트

조인트 컴포넌트를 사용하면 리지드바디를 또 다른 리지드바디나 공간 내 정해진 지점에 연결할 수 있습니다. 조인트는 리지드바디에 힘을 가해 움직이도록 합니다. 조인트 한계를 사용하면 특정 움직임을 제한할 수도 있습니다. 물리 조인트에는 Character Joint, Configurable Joint, Fixed Joint, Hinge Joint, Spring Joint 등이 있습니다(그림 07).

Character Joint: 엉덩이 또는 어깨 조인트 등 캐릭터의 관절을 모사합니다. 모든 선형 자유도에 따라 리지드바디의 움직임을 제한하거나 모든 각도에 대한 자유도를 부여하는 기능을 제공합니다. Character Joint에 연결된 리지드바디는 각 축을 중심으로 방향을 잡고 공통된 원점에서 피벗합니다.

Configurable Joint: 래그돌의 관절과 같은 모든 골격 조인트를 에뮬레이트합니다. 이 조인트는 자유도에 관계없이 리지드바디의 움직임을 제한하도록 설정할 수 있습니다.

Fixed Joint: 리지드바디의 움직임이 연결된 다른 리지드바디의 움직임을 따르도록 제한합니다. 이 조인트는 쉽게 분리되는 리지드바디가 필요하거나 Transform 계층 구조에서 부모 지정 없이 리지드바디 두 개의 움직임을 연결할 때 유용합니다.

Hinge Joint: 공통된 원점에서 리지드바디를 다른 리지드바디 또는 공간의 한 지점에 연결하고 리지드바디가 해당 원점에서 특정 축을 중심으로 회전하게 합니다. 문과 손가락 조인트를 모사하는 데 유용합니다.

Spring Joint: 리지드바디를 서로 떨어진 상태로 유지하지만, 간격을 약간 늘어날 수 있게 합니다. 스프링은 두 개의 앵커 포인트를 한 지점으로 끌어당기는 고무 밴드와 같은 역할을 합니다.

10. 레이캐스팅

물리 오브젝트와 다른 오브젝트 간 광선 또는 보이지 않는 연결을 캐스트합니다.

Physics.Raycast (Vector3 Origin, Vector3 Direction)
Physics.Raycast (Vector3 Origin, Vector3 Direction, RaycastHit Info, float Distance, int Layermask)

또는

Physics.Raycast (Ray RayName, RaycastHit Info, float Distance, int Layermask)

파라미터:

  • origin: 월드 공간 내 광선의 시작점입니다.
  • direction: 오브젝트 공간에 캐스트되는 광선의 방향입니다.
  • maxDistance: 광선의 충돌을 검사하는 최대 거리입니다.
  • layerMask: 광선을 캐스트할 때 콜라이더를 선택적으로 무시하는 데 사용하는 레이어 마스크입니다.
  • queryTriggerInteraction: 해당 쿼리의 트리거 충돌 여부를 지정합니다.

충돌하는 게임 오브젝트에 새 태그나 기존 태그를 할당하면 RaycastHit에서 식별하기가 수월해집니다(그림 08).

예시의 레이캐스트는 이 스크립트가 연결된 게임 오브젝트의 원점에서 아래쪽으로 광선을 캐스트하고 있습니다.

트랜스폼 위치와 바닥(environment 태그가 지정된 게임 오브젝트) 사이의 거리가 deploymentHeight에 해당하는 경우 DeployParachute() 함수를 호출합니다.

레이캐스트로 작업 시 권장 사항은 다음과 같습니다.

  • 씬에서 레이캐스트 수를 줄입니다.
  • FixedUpdate() 또는 Update() 함수 내에서 레이캐스트를 호출하지 않습니다.
  • MeshCollider는 사용을 지양합니다.

11. 레이어 및 충돌 매트릭스

https://docs.unity3d.com/Manual/LayerBasedCollision.html

게임 오브젝트의 기본 레이어에 기본 동작이 할당되면 모든 요소와 충돌하므로 비효율적일 수 있습니다. 그 대신, 새 레이어에 게임 오브젝트를 할당할 수 있습니다. 이 레이어들 간의 충돌 관계는 충돌 매트릭스에 따라 결정될 수 있습니다.

물리 엔진 설정을 열려면 상단 메뉴 드롭다운에서 Edit > Project Settings > Physics를 선택합니다. Project Settings 창의 맨 아래에 Layer Collision Matrix를 확인할 있습니다(그림 09).

12. 최적화 관련 참고 사항

어떤 오브젝트가 다른 오브젝트와 충돌할 수 있는지를 명시적으로 정의하면 계산 횟수가 줄어들고 스크립트도 적게 작성할 수 있습니다.

또한 정적 오브젝트에 특정 물리 속성을 적용하는 것은 권장하지 않습니다. 예를 들어, 정적 오브젝트에는 트랜스폼을 사용하지 않아도 됩니다. 컴퓨팅 리소스 소모가 늘며 성능이 저하될 수 있기 때문입니다.

13. 결론

Unity 물리 엔진을 사용하면 실제와 유사한 중력, 속도, 가속도, 마찰 등의 힘을 오브젝트에 적용할 수 있습니다. 여러 물리적 프로퍼티가 적용된 다양한 오브젝트들이 동적으로 상호 작용하는 씬을 설정해 보세요.

Complete this Tutorial