[Unity] 물체의 이동 AddForce, velocity, MovePosition

권태형·2023년 9월 15일
0

Unity

목록 보기
6/9
post-thumbnail

Unity에서 물체를 이동시키기 위해서 쓰는 방법은 여러가지가 존재하는데 물리적인 특성을 사용하기 위해서는 Addforce함수를 사용하거나 velocity에 새로운 Vector3값을 넣어주는 방식을 사용한다.

그냥 물제자체의 위치의 변경을 위해서는 transform.position에 값을 변경하거나, transform.Translate(Vector3 translation)과 같은 방법을 사용해서 변경 할 수 도 있다.

[SerializeField]
float speed = 500.0f;
RigidBody rb;

rb = GetComponent<RigidBody>();

 float speedX = Input.GetAxis("Horizontal") * speed * Time.deltaTime ;
 float speedZ = Input.GetAxis("Vertical") * speed * Time.deltaTime;

rb.AddForce(speedX, 0, speedZ);
//또는
rb.velocity = new Vector3(speedX, 0, speedZ);
//또는
rb.MovePosition(transform.position + new Vector3(speedX, 0, speedZ))

요점은 rigidBody! 즉 Unity엔진에서 물리법칙을 적용시켜 이동시키는 방법에 대한 비교점이다.

rb.AddForce()

영문 직역 그대로 Force 힘을 +ADD 더하다 라고 생각할 수 있다.

이 함수는 해당 오브젝트의 위치정보에 추가적인 힘을 더해주는 형식으로 움직임을 취한다.

rb.AddForce()의 호출의 횟수에 따라 계속적으로 속도는 가중치를 가지고 증가하고 점점 더 빨라진다.
이 함수는 관성, 마찰력과 같은 물리법칙도 모두 계산하고 있기 때문에 일반적으로 우리가 일상에서 경험하는 이동물리법칙을 엔진내에서 구연할 수 있게 해준다.

rb.AddForce(x,y,z)
rb.AddForce(Vector3 force)
rb.AddForce(x,y,z, ForceMode mode)

위와 같은 형태를 가지고 x, y, z값은 해당 축에 추가할 힘의 크기를 float값을 가진다.
똑같이 x,y,z 값을 따로 넣지 않고, Vector3 로 만들어진 값을 넣어도 똑같이 동작한다.

4번째 인자로 ForceMode 타입의 옵션을 받을 수 있다. 이 ForceMode의 옵션은 지속가속, 순간가속, 물체질량 무시여부에 따라 나눠진다.

모드설명
Force기본값으로 질량을 사용⭕하고 지속적으로 힘을 가함
Acceleration질량을 무시❌하고 지속적으로 힘을 가함
Impulse질량을 사용⭕하고 순간적으로 힘을 가함
VelocityChange질량을 무시❌하고 순간적으로 힘을 가함

rb.velocity

veloctiy는 속도 그 자체이다. re.veloctiy 자체에 Vector3 값을 대입하면 현재오브젝트의 속도를 일정하게 해당속도로 적용하게 해준다.

rb.velocity = new Vector3(speedX, 0, speedY);

이동하는 속도 자체에 고정값을 대입해 주기 때문에 따로 가속이나 감속의 효과가 없이 일정속도로 이동할 수 있게 해준다.

다만 velocity는 rb가 적용된 물체에 대해서 강제적으로 속도를 제어하기 때문에, 기존에 오브젝트가 받고있던 물리법칙을 무시하게 된다.

따라서 물리엔진과의 상호 작용 및 예측 가능동작에 대해 엔진계산에 문제가 발생할 가능성이 생겨 우리가 예기치 못한 이동에과 물리법치에 대한 오류가 발생할 가능성 또한 내제하고 있다.


rb.MovePosition

MovePosition은 충돌연산의 영향을 받으면서 물체를 이동시키는 메소드이다.

rb.MovePosition(transform.position + new Vector3(speedX, 0, speedZ))

문제는 충돌연산의 영향을 받지만 모든 물리연산의 영향을 받지는 않는다. 중력이나 가속,감속과 같은 연속적인 물리효과에 대해서 영향을 받지 않으면서 부드럽게 물체를 이동시킨다. 충돌연산영향을 제외한다면, 직접적으로 transform.position += new Vector3()와 같이 위치를 조정하는 것과 크게 다르지 않다.

MovePosition의 인자는 목적지를 나타낸다. speedX,나 speedZ는 deltaTime값을 곱한 값이기 때문에 일반적으로 정확히 원하는 목적지에 도달하기 어렵다. 따라서 목적지 까지 정확한 이동을 위해서는 MoveTowards()함수를 곁드려서 사용한다.

Vector3 newPos = Vector3.MoveTowards(rb.position, endPoint, moveSpeed* Time.deltaTime);
rb.MovePosition(newPos);

MoveTowards()는 시작점에서 끝점까지 3번째 인자만큼의 이동한 Vector를 반환한다. 다만 이 함수에서 가장 중요한 점은 3번째 인자가 endPoint를 넘어설때는 endPoint값을 정확히 반환해 준다는 점이다.

따라서 이러한 특징을 이용해서 MovePosition과 같이쓰면 원하는 정확한 위치에 일정한 속도로 물체를 이동시킬 수 있게된다.

무엇을 써야할까?

모든 물리특성이 나타나게 적용하고 싶다면 AddForce(), 충동연산만 필요하다면 MovePosition()을 사용하는게 당연히 올바를 것이다.

하지만 일정한 속도로 이동하게 하고 싶다해도 되도록이면 rb.velocity를 사용하는 것은 한번더 생각해봐야한다.

AddForce()나 MovePosition() 을 사용해서 일정한 속도로 이동하게 하려면, 최대속도나 최소속도에 대한 제한값을 두어 일정속도로 이동할 수 있도록 컨트롤 해주거나 스크립트를 이용해서 내부적인 가속 또는 감속을 계산해 이전속도에서 빼주면서 일정속도를 유지시키면서 물제를 동작시킬 수도 있을 것이다.

profile
22년 12월 개발을 시작한 신입 개발자 ‘권태형’입니다. 포스팅 하나하나 내가 다시보기 위해 쓰는 것이지만, 다른 분들에게도 도움이 되었으면 좋겠습니다. 💯컬러폰트가 잘 안보이실 경우 🌙다크모드를 이용해주세요.😀 지적과 참견은 언제나 환영합니다. 많은 댓글 부탁드립니다.

0개의 댓글