카테고리 없음

유니티 기초 #4 리지드 바디

2024 자탐 2024. 11. 11. 14:20
리지드 바디

리지드 바디는 물리효과를 주고 싶은 오브젝트를 선택한 후 Inspector창의 제일 하단에 있는 Add Component에 ri까지만 쳐도 바로 밑에 컴포넌트가 뜬다. 그걸 클릭하면 오브젝트에 추가가된다. 여기서 주의할 점은 3d에서는 Rigidbody를 사용해야 하고 2d에서는 Rigidbody 2d를 사용해야란다. 그렇지 않으면 추가할 수 없는 컴포넌트라고 경고가 뜬다. 

 

리지드 바디를 추가하면 Use Gravity라고 되어 있는 체크 박스가 있는데, 이것은 중력을 사용한다는 말이다. 실행해보자.

 

위 사진들과 같이 가만히 있던 큐브가 밑으로 떨어지는 것은 볼 수 ㅇ,ㅆ습니다. 큐브가 Rigdbody 컴포넌트에 의하여 중력의 영향을 받게 되었기 때문이다. 

 

큐브가 떨어지는 속도는 얼마일까? 이것을 알아보기 위해서는 왼쪽 상단의 Edit-ProjectSettings를 클릭하면 아래와 같은 창이 나타난다. 그 창의 왼쪽 리스트에서 Physics라는 키워드을 찾아서 클릭한다. 여기서 Cloth of Gravity의 y값을 보면 -9.81이라고 되어 있다. 중력의 크기는 9.8n이니 실제와 같다.

 

Rigidbody 

 

-Mass

질량의 양을 정할 수 있다.

Mass의 값이 크면 클수록 가속력, 관성 등의 힘들의 크기도 커진다.

 

-Drag

저항을 정할 수 있는 기능을 가지고 있다. 

공기의 저항, 물의 저항과 비슷하다.

Drag가 커지면 아래로 떨어지는 속도도 줄어든다.

 

-Angular Drag

회전할 때 저항을 정할 수 있는 기능을 가지도 있다.

이 값이 높을수록 느리게 회전한다.

 

-Use Gravity 

Use Gravity는 말 그대로 중력을 사용한다는 것이다.

 

-Is Kimematic

물리효과를 사용하지 않는 기능을 가지고 있다.

이것을 체크하면 중력, 관성, 가속도 등 물리효과들이 적용되지 않는다.

 

-Interpolate

캐릭터의 움직임이 부자연스러울 때 사용하는 기능이다.

None은 영향을 주지 않는 것이고, Interpolate는 이전 프레임의 움직임을 통해 다음 프레임을 제작하고, Extrapolate는 다음 움직임을 예측하여 움직임을 자연스럽게 만드는 기능을 가지고 있다.

 

-Collision Detection 

충돌을 탐지하는 기능을 가지고 있다.

Discrete는 충돌을 체크하고, Continous는 연속적으로 충돌을 체크하는 기능을 가지고 있다.

Continous Dynamic은 속도가 빠른 물체에게 적용시키면 물리효과를 더욱 정밀한 계산을 해준다.

 

-Constraints 

제약사항을 정하는 기능을 가지고 있다.

Freeze Postion에 있는 축을 체크하면 해당 축은 얼려진다. 

즉 값이 고정된다는 소리이다.

Freeze Rotation도 회전할 때 해당 축의 값을 고정시키는 것이다.

 

Rigidbody 제어하기

 

스크립트에서 리지드 바디를 사용하기 위해 리지드 바디를 선언해야한다.

방법은 2가지이다.

public class Test : MonoBehaviour 
{ 
   [SerializeField] private Rigidbody Rigid; 
   void Start() 
   { 
   
   } 
   void Update() 
   { 
   
   } 
}

 

아래 코드는 Rigid변수에 이 스크립트가 포함되어 있는 오브젝트에서 Rigidbody를 가져오는 방법을 사용했다.

 

public class Test : MonoBehaviour 
{ 
   private Rigidbody Rigid; 
   void Start() 
   { 
      Rigid = GetComponent<Rigidbody>(); 
   } 
   void Update() 
   { 
   
   } 
}

 

여기서 velocity는 속도를 나타낸다. 

이 코드를 실행하면 위쪽 화살표 키를 한 번만 누르면 앞으로 계속 간다. 저항이 없기 때문이다. 이는 무중력과 같은 상태이다. 

만약 Rigidbody에서 Drag에 값을 준다면 저항이 생겼기에 앞으로 가다가 멈추게 된다.

 

public class Test : MonoBehaviour 
{ 
   private Rigidbody Rigid; 
   void Start() 
   { 
      Rigid = GetComponent<Rigidbody>(); 
   } 
   void Update() 
   { 
      if (Input.GetKey(KeyCode.UpArrow)) 
      { 
         Rigid.velocity = new Vector3(0, 0, 1); 
      } 
   } 
}

 

angularVelocity는 회전 값을 나타낸다.

여기서 저항을 준다면 Rigidbody에서 AngularDrag를 높여주면 저항 때문에 더 느리게 회전할 것이다.

 

public class Test : MonoBehaviour 
{ 
   private Rigidbody Rigid; 
   
   void Start() 
   { 
      Rigid = GetComponent<Rigidbody>(); 
   } 
   void Update() 
   { 
      if (Input.GetKey(KeyCode.UpArrow)) 
      { 
         Rigid.angularVelocity = new Vector3(0, 0, 1); 
      } 
   }
}

 

저항을 유니티 프로그램에서 정하는게 귀찮다면 직접 코드로 저항을 정할 수도 있다. isKinematic이나 useGravity도 false를 이용해 사용 유무를 정할 수 있다.

 

public class Test : MonoBehaviour
{
    private Rigidbody Rigid;
    void Start()
    {
        Rigid = GetComponent<Rigidbody>();
    }
    void Update()
    {
        if (Input.GetKey(KeyCode.UpArrow))
        {
            Rigid.drag = 10f;
            Rigid.angularDrag = 1f;
            Rigid.isKinematic = true;
            Rigid.useGravity = true;
        }
    }
}

 

maxAngularVelocity는 리지드 바디가 빠르게 회전할 때 생기는 불안정감을 피하기 위해 사용한다.

(기본값은 7)

 

public class Test : MonoBehaviour 
{ 
   private Rigidbody Rigid; 
   
   void Start() 
   { 
      Rigid = GetComponent<Rigidbody>(); 
   } 
   void Update() 
   { 
      if (Input.GetKey(KeyCode.UpArrow)) 
      { 
         Rigid.maxAngularVelocity = 50; 
         Rigid.angularVelocity = Vector3.forward*1000; 
      } 
   } 
}

 

메서드

아래의 메서드는 MoveRotation이다. MoveRotation은 특정한 방향으로 회전하는 기능을 가지고 있다.

 

public class Test : MonoBehaviour 
{ 
   private Rigidbody Rigid; 
   private Vector3 rotation; 
   
   void Start() 
   { 
      Rigid = GetComponent<Rigidbody>(); 
      rotation = this.transform.eulerAngles; 
   } 
   void Update() 
   { 
      if (Input.GetKey(KeyCode.UpArrow)) 
      { 
         rotation += new Vector3(90, 0, 0) * Time.deltaTime; 
         Rigid.MoveRotation(Quaternion.Euler(rotation)); 
      } 
   } 
}

 

MovePosition은 특정한 방향으로 이동하는 기능을 가지고 있다. MovePositiom과 MoveRotation은 물리법칙을 적용받지 않고 강제로 움직이게 하는 메서드들이다.

public class Test : MonoBehaviour 
{ 
   private Rigidbody Rigid; 
   
   void Start() { Rigid = GetComponent<Rigidbody>(); } void Update() 
   { 
      if (Input.GetKey(KeyCode.UpArrow)) 
      { 
         Rigid.MovePosition(transform.forward); 
      } 
   } 
}

 

믈리법칙을 적용받으며 움직이려면 AddForce메서드를 사용하면 된다. 그리고 drag를 1.5f로 설정하면 아주 조금가다가 멈춘다. 저항이 있기 때문이다. 그리고 Mass의 값도 줄이면 아까보다 더 빠르게 가고 이동한 거리가 많아진다. AddForce는 질량의 영향도 받기 때문이다.

 

public class Test : MonoBehaviour 
{ 
   private Rigidbody Rigid; 
   void Start() 
   { 
      Rigid = GetComponent<Rigidbody>(); 
   } 
   void Update() 
   { 
      if (Input.GetKey(KeyCode.UpArrow)) 
      { 
         Rigid.AddForce(Vector3.forward); 
         Rigid.drag = 1.5f; 
      } 
   } 
}

AddTorque는 MoveRotation과 같이 키를 누르지 않으면 바로 회전이 멈추는게 아니라 물리법칙에 의하여 힘이 계속 남아있다. 만약 AngularDrag가 높으면 천천히 움직인다. 그리고 키를 누르지 않을 때 회전하는 시간도 느려진다.

 

public class Test : MonoBehaviour 
{ 
   private Rigidbody Rigid; 
   
   void Start() 
   { 
      Rigid = GetComponent<Rigidbody>(); 
   } 
   void Update() 
   { 
      if (Input.GetKey(KeyCode.UpArrow)) 
      { 
         Rigid.AddTorque(Vector3.forward); 
      } 
   } 
}

 

AddExplosionForce는 폭발력을 전달해주는 메서드이다.

파라미터는 3개인데 첫 번째는 폭발력의 세기, 두 번째는 폭발 후 영향을 받을 위치, 마지막은 폭발 반경이다. 그리고 질량을 줄이고 저항도 줄이면 더 멀리 날아간다.

 

public class Test : MonoBehaviour 
{
   private Rigidbody Rigid; 
   
   void Start() 
   { 
      Rigid = GetComponent<Rigidbody>(); 
   } 
   void Update() 
   { 
      if (Input.GetKey(KeyCode.UpArrow)) 
      { 
         Rigid.AddExplosionForce(20, this.transform.right, 20); 
      } 
   } 
}