본문 바로가기
유니티/기초

유니티 물리 충돌 ( Physics )

by 노튜 2020. 11. 5.
728x90

1. 물리 엔진 

1.1 Rigidbody Component

 

Rigidbody 컴포넌트는 게임 오브젝트가 유니티에서 물리 엔진에 의해 처리되도록 하며, 게임 오브젝트가 사실적으로 동작하게 한다.  두 개의 게임 오브젝트가 충돌이 발생하였을 경우, 둘 중 하나의 오브젝트에 적어도 한 개의 Rigidbody 컴포넌트가 존재해야 한다. 그렇지 않으면, 유니티는 충돌 처리를 하지 않는다. 

게임오브젝트를 생성하고, Rigidbody 컴포넌트를 추가하면, 아래와 같은 에디터 창을 볼 것이다.

 

 

  • Mass : 오브젝트의 질량입니다. 질량은 물질이 가지고 있는 양이며, 질량의 단위는 Kilogram(Kg)입니다. 질량이 작을수록, 힘의 영향을 쉽게, 많이 받습니다. 질량이 크면 클수록 물체를 움직이는데 필요한 힘이 더 많이 필요합니다.
  • Drag : 공기저항을 의미합니다. 오브젝트가 힘에 의해 움직일때, 공기 저항을 받도록 설정하는 값입니다. Drag의 값이 0이면, 공기저항이 없습니다. Drag의 값이 클수록 공기의 저항을 많이 받습니다. 
  • Angular Drag : 오브젝트가 토크로 회전을 할 때 공기의 저항을 받는 정도를 설정합니다. 0일 때에는 공기의 저항을 받지 않습니다.
  • Use Gravity : 중력입니다. 중력을 사용할 것인지, 중력을 사용하지 않을 것인지를 설정합니다. 선택(√)하면 해당 게임오브젝트는 중력의 영향을 받습니다. 중력은 Y축에 영향을 받습니다. 개발 환경에 맞게 선택을 합니다. 
  • Is Kinematic : Rigidbody Component를 사용하기는 하지만, 게임 오브젝트의 상태가 물리 엔진에 의해 변형되지 않습니다. Transform을 사용하여 게임 오브젝트를 동작합니다. 

 

Rigidbody 컴포넌트를 다루는 경우에 FixedUpdate()를 사용해야한다. (Unity document : FixedUpdate)

Rigidbody는 내부적으로 Transform을 사용하여 형태를 변경한다. 따라서 게임오브젝트의 Rigidbody 컴포넌트, Transform 컴포넌트 중 하나만 사용하여야 한다. 예를 들어, Rigidbody로 서로 충돌을 하여, 밀려나도록 하는 물리 로직을 구성하고, 이와 동시 Transform을 사용하여, 옆으로 이동하는 로직을 구현하여서는 안된다.   

 

1.2 중력(Gravity) 

게임오브젝트를 중력에 영향을 받도록 구현할 경우 Use Gravity 속성에 체크(✔️)를 한다. 그렇지 않으면, 체크를 해제하면 된다. Script에서 실시간으로 Gravity 속성을 변경할 수 있다. 

 

Unity의 중력은 -9.81로 지구의 중력과 같게 설정되어있다. 그러나 지구와 달의 중력은 다르다. 월드를 달과 같은 중력을 사용하도록 설정할 수 있다.  아래의 위치에서 중력값을 변경할 수 있다.

 

Edit ➝ Project Settings ➝ Physics ➝ 중력 설정. 

 

2. 충돌 처리 Collider

 

물리 엔진을 사용한 충돌 처리는 Collider 컴포넌트에서 한다. 두 물체를 충돌하게 하기 위해서는, 두 물체 모두 Collider 컴포넌트가 존재해야 한다. 한쪽만 있다면, 물리 엔진은 충돌 연산을 수행하지 않는다. 

2.1 Collision

스크립트를 사용해 두 게임오브젝트 사이에 충돌과 관련한  로직을 구현할 수 있다. 충돌이 발생하면, OnCollisionEnter(Collision)이 호출된다. 또한, 충돌이 일어날 때, 충돌이 끝날 때 호출되는 함수는 아래와 같다. 

 

  • OnCollisionEnter(Collision) : 충돌 시
  • OnCollisionStay(Collision) : 충돌 중
  • OnCollisionExit(Collision) : 충돌 해제

 

Collision class에는 접촉 오브젝트, 접촉 지점, 접촉 속도 등의 정보를 포함한다. 

Collision class를 통해 접촉 대상을 판단하고, 이에 대한 처리를 한다.

아래 코드는 충돌이 발생하였을 때, Tag로 대상이 Target인지 아닌지 판별하는 간단한 예제 소스이다. 

using Unityengine;

public class ExampleClass : MonoBehaviour 
{

  void OnCollisionEnter(Collision collisionInfo)
  {
   if(collisionInfo.gameObject.CompareTag("Target"))
   {
      Debug.Log(“Target Enter”);    
   }
  }

  void OnCollisionStay(Collision collisionInfo)
  {
    Debug.Log(“Collision Stay”);
  }

  void OnCollisionExit(Collision collisionInfo)
  {
     Debug.Log(“Collision Exit”);
  }
} 

 

2.2 Trigger

 

월드를 구성할 때, Collider 컴포넌트를 이용해, 물리 연산은 하지 않고, 충돌 확인만 하도록 구현하고자 하는 경우가 있다. 가령, RPG 게임을 예로 들 수 있다. 충돌만 확인하고, 물리 연산은 하지 않는 것이다. 이때, 사용되는 것이 Trigger이다. Collider의 IsTrigger 속성을 체크(✔️)하면 된다. 

Trigger를 사용하면, Collision()은 호출되지 않는다. 대신 Trigger() 함수가 호출된다. 

 

  • OnTriggerEnter(Collider other) : Trigger를 사용하는 게임 오브젝트와 충돌하였을 때 호출된다.
  • OnTriggerStay(Collider other) : Trigger를 사용하는 게임 오브젝트와 충돌하여, 그 상태가 지속될 때, 호출된다. 
  • OnTriggerExit(Collider other) : Trigger를 사용하는 게임 오브젝트와 더 이상 충돌이 발생하지 않을 때 호출된다. 충돌 영역에서 게임 오브젝트가 벗어난 상태이다.

 

using Unityengine;

public class ExampleClass : MonoBehaviour 
{
  public string targetTag ="Enemy"; 
  void OnTriggerEnter(Collider collider)
  {
    if(collider.CompareTag(targetTag))
    {
      // do something.
    }
  
  }

  void OnTriggerStay(Collider collider)
  {
     // Do something continuously Keep Collision
  }

  void OnTriggerExit(Collider collider)
  {
     // Do something when game object is going off
  }
} 

 

참조 

 

https://docs.unity3d.com/kr/530/ScriptReference/MonoBehaviour.FixedUpdate.html

 

Unity - 스크립팅 API: MonoBehaviour.FixedUpdate()

Rigidbody를 다루는 경우에, Update대신 FixedUpdate를 사용해야 합니다. 예를 들어 리지드바디에 힘을 가하는 경우에, FixedUpdate안에서 매 고정된 프레임마다 힘을 적용해야 합니다. 이 경우 Upate에서 매

docs.unity3d.com

 

https://docs.unity3d.com/kr/2018.4/Manual/class-Rigidbody.html

 

리지드바디 - Unity 매뉴얼

Rigidbody 는 GameObject 가 물리 제어로 동작하게 합니다. 리지드바디는 힘과 토크를 받아 오브젝트가 사실적으로 움직이도록 해줍니다. 리지드바디가 포함된 모든 게임 오브젝트는 중력의 영향을

docs.unity3d.com

 

  

728x90