내일배움캠프 7주차 3일차 TIL - Rigidbody

백흰범·2024년 5월 29일
1

오늘 한 일

  • 챌린지반 과제 풀이
  • 프로젝트 진행하기 (~ 선택 구현 사항 3)


Rigidbody

개념

Rigidbody는 게임 오브젝트가 물리 제어로 동작하게 합니다. Rigidbody는 Force와 Torque를 받아 오브젝트가 사실적으로 움직이도록 해주고, Rigidbody가 포함된 모든 게임 오브젝트는 중력의 영향을 받을 수 있게되며, 스크립팅을 통해 가해진 힘으로 움직이거나 NVDIA PhysX 물리 엔진을 통해 다른 오브젝트와 상호작용하게 됩니다.

컴포넌트의 각종 프로퍼티

Mass

  • 오브젝트의 질량 (디폴트 값을 킬로그램)
  • 코드
    _rigidbody.mass = 10;

테스트 영상


각종 이동 처리

  • 각 물체의 mass는 흰색은 1 회색은 100으로 설정해주었다.

_rigidbody.velocity = direction * speed * Time.deltaTime;

흰색과 회색에서 각각 250으로 설정해주었다.

  • 둘이 속도가 균일하게 나온다.


_rigidbody.AddForce(direction * speed * Time.deltaTime, ForceMode.Force);

흰색과 회색에게 각각 50으로 설정해주었다.

  • 가속이 생기는데 mass에 따라서 차이가 발생한다.

Force 모드에서 흰색은 50 회색은 5000으로 설정

  • 서로 mass 차이가 나는 상태에서 Force로 동일한 속도를 내고자 한다면 a(mass) : b(mass) = a(Force) : b(Force)를 통해서 계산해줘야할 것 같다.


_rigidbody.AddForce(direction * speed * Time.deltaTime, ForceMode.Acceleration);

흰색과 회색에게 각각 50으로 설정해주었다.

  • mass 상관 없이 둘이 동일한 속도로 가속이 발생한다.


_rigidbody.AddForce(direction * speed * Time.deltaTime, ForceMode.Impulse);

흰색과 회색에게 각각 10으로 설정해주었다.

  • 가속이 폭발적으로 증가하고 mass에 따라서 차이가 발생한다.


_rigidbody.AddForce(direction * speed * Time.deltaTime, ForceMode.VelocityChange);

흰색과 회색에게 각각 10으로 설정해주었다.

  • mass 상관없는 impulse mode인 것 같다.



Drag

  • 위치 이동의 저항 (중력과 움직임에 저항이 생긴다)
  • 코드
    _rigidbody.drag = 10;

테스트 영상


중력 저항

초기 설정

  • Drag 설정
    • 파란색은 기본값(0)
    • 빨간색은 20
  • 각자에게 중력을 추가해주었다.
  • Drag가 없는 파란색 직육면체는 바로 떨어지고 Drag가 20인 빨간색은 천천히 떨어진다.

이동 저항

초기 설정

  • Drag 설정
    • 파란색은 기본값(0)
    • 빨간색은 20

사용된 이동 코드

   IEnumerator MovePlatform()
   {
       Vector3 direction = (directions[curDirectionIdx] - transform.position).normalized; // 방향 단위 벡터
       while (true) // 목표 지점에 도착할 때까지 반복합니다.
       {
           if (Vector3.Distance(transform.position, directions[curDirectionIdx]) < 0.2f) { break; }
           _rigidbody.velocity = direction * speed * Time.deltaTime; // 초를 따라 추가
           yield return null;
       }
       _rigidbody.velocity = Vector3.zero; // velocity 0으로 만들기 (이게 없으면 날라가니 주의)
       yield return new WaitForSeconds(waitTime); // 멈추는 시간 설정
       curDirectionIdx++;	// 다음 목적지로
       if (curDirectionIdx >= directions.Count) // Count를 넘는다면
       {
           curDirectionIdx = 0; // 다시 0으로
       }
       StartMove(); // 움직임 재시작
   }
  • speed는 500으로 설정해주었다.
  • 해당 영상에서 보이듯이 Drag가 없는 파란색은 빠르게 움직이고 Drag가 있는 빨간색은 천천히 움직인다.

+ 정지 코드 제외

speed를 250으로 바꿔주었다.

  • 빨간색은 Velocity를 주는 것을 멈추면 잘 멈추는 반면 파란색은 그대로 나아가버린다.


각종 이동 처리

_rigidbody.velocity = direction * speed * Time.deltaTime;

파란색과 빨간색에게 각각 250으로 설정해주었다.

  • 빨간색이 저항을 받아서 그런지 속도가 감속되는 현상이 생긴다. (프레임 단위로 velocity = 처리이다.)


_rigidbody.AddForce(direction * speed * Time.deltaTime, ForceMode.Force);

파란색과 빨간색에게 각각 50으로 설정해주었다.

  • 파란색은 가속이 잘 전달되는 반면 빨간색은 이상하게 속도 제한이 걸리는 것 같다.


_rigidbody.AddForce(direction * speed * Time.deltaTime, ForceMode.Impulse);

파란색과 빨간색에게 각각 10으로 설정해주었다.

  • 위와 마찬가지로 빨간색에게 속도 제한이 걸린다.

Impulse 모드 빨간색만 200으로 설정

  • 아무리 힘을 줘도 저항 때문에 속도가 중첩이 되질 않는다..



Angular Drag

  • 회전의 저항
  • 코드
    _rigidbody.angularDrag = 10;

테스트 영상


_rigidbody.angularVelocity = Vector3.up * rotateSpeed;

  • AngularDrag 설정
    • 파란색은 기본값(0.05)
    • 빨간색은 20
    • rotateSpeed를 20으로 설정했다.
  • 멈추는 버튼을 추가해서 멈추는 실험

    해당 영상을 보면 파란색 직육면체가 좀 더 빨리 회전하는 것을 볼 수 있고 움직임을 멈췄을 경우 파란색은 천천히 멈추고 빨간색은 바로 멈추는 것을 알 수 있다.

_rigidbody.AddTorque(Vector3.up * rotateSpeed);

  • AddTorque는 각도 버전의 Addforce라 생각해주면 된다. (기본 Forcemode는 Force이다.)
  • 속도는 각각 20으로 설정해뒀다.
  • 해당 영상을 보면 알 듯이 빨간색은 저항을 받아서 속도의 제한을 받고 파란색은 잘 회전되는 모습을 볼 수 있다.
  • 그리고 멈췄을 경우 저항이 있는 빨간색(20)은 바로 멈추고 파란색(0.05)은 천천히 멈추고 있는 것을 볼 수 있다.



UseGravity

  • 중력 유무

앞선 Drag 영상에서 봤듯이 물체에 중력을 부여해줄 수 있다. 중력을 사용하지 않겠다면 체크란을 비워주면 된다.

  • 코드
    Rigidbody(의 인스턴스).useGravity = true;



Is Kinematic

  • 오브젝트가 물리 엔진으로 제어되지 않고 오로지 Trasnform으로만 조작된다. 플랫폼을 옮기는 경우나 HingeJoint가 추가된 리지드바디를 애니메이션화하는 경우에 유용하다
  • 코드
    Rigidbody(의 인스턴스).isKinematic = true;
  • 당연하겠지만 velocity에 변화를 주려하면 이러한 에러가 발생한다.



Interpolate

  • 리지드바디의 움직임이 어색해 보일 경우에 사용한다.
    • None - 보간 없음
    • Interpolate - 이전 프레임의 트랜스폼에 맞게 움직임을 부드럽게 처리합니다.
    • Extrapolate - 다음 프레임의 트랜스폼을 추정해 움직임을 부드럽게 처리합니다.
  • 코드
    Rigidbody(의 인스턴스).interpolation = RigidbodyInterpolation.Interpolate;



Collision Detection

  • 빠르게 움직이는 오브젝트가 충돌의 감지 없이 다른 오브젝트를 지나쳐가는 것을 방지합니다.

Discrete

  • 물리 시스템이 불연속 충돌 검사를 사용하여 이 리지드바디의 콜라이더에 대한 충돌을 계산합니다. 이 리지드바디가 빠르게 움직이는 충돌에 관여하지 않는 경우 Discrete를 선택합니다.Discrete 충돌 검사는 컴퓨터 리소스를 많이 사용하지 않습니다.

Continous

  • 물리 시스템은 스위핑 기반 CCD를 사용하여 이 리지드바디의 콜라이더와 정적 콜라이더(연관된 리지드바디가 없는 콜라이더) 간의 충돌을 계산합니다. 이 리지드바디가 정적 콜라이더와의 빠르게 움직이는 충돌에 관여하는 경우 Continuous를 선택합니다. 스위핑 기반 CCD는 Discrete 또는 Continuous Speculative보다 컴퓨터 리소스를 많이 사용합니다.

Continuous Dynamic

  • 물리 시스템은 스위핑 기반 CCD를 사용하여 이 리지드바디의 콜라이더와 Discrete 충돌 검사로 설정된 콜라이더를 제외한 다른 모든 콜라이더 간의 충돌을 계산합니다. 이 리지드바디가 임의의 콜라이더와의 빠르게 움직이는 충돌에 관여하는 경우 Continuous Dynamic을 선택합니다. 스위핑 기반 CCD는 Discrete 또는 Continuous Speculative보다 컴퓨터 리소스를 많이 사용합니다.

Continuous Speculative

  • 리지드바디와 콜라이더에 추측성 연속 충돌 검사를 사용합니다. 키네마틱 바디를 설정할 수 있는 유일한 CCD 모드입니다. 이 메서드는 스위핑 기반 연속 충돌 검사보다 리소스를 덜 소모합니다.



Constraints

  • 리지드 바디의 움직임에 대한 제약사항
    • Freeze Position - 월드 좌표계의 X, Y, Z 축에서 이동하는 리지드 바디의 움직임 제한 유무
    • Freeze Rotation - 로컬 좌표계의 X, Y, Z 축에서 회전하는 리지드 바디의 움직임 제한 유무
  • 코드

혹여나 Rigidbody에 힘을 가했는데 의도된 대로 움직여지지 않으면 이 체크란을 확인해주자.
Transform.position을 이용한 이동의 제한은 막힌 게 아니니 그것을 사용해도 된다.



참고 자료

유니티 공식 문서

유니티 공식 문서 스크립트 레퍼런스

유니티 입문 강좌 part 3 - 리지드 바디 - 케이디




작성하면서 느낀점

유니티라는 엔진을 알면 알수록 생각보다 자기가 모르는 것에 대한 실험을 하기가 좋은 환경이라고 생각이 든다.

profile
게임 개발 꿈나무

0개의 댓글