유니티에서 이동(위치 변경)을 위해서 사용하는 방법은 아래와 같습니다.
transform.Translate()
transform.position에 직접 값을 입력해주는 방법
Rigidbody.MovePosition()
Rigidbody.position에 직접 값을 입력해주는 방법
Rigidbody.AddForce()
Rigidbody.AddRelativeForce()
Rigidbody.velocity
Transform.Translate()
//transform.Translate(new Vector3(float, float, float));
void Update ()
{
// 게임 오브젝트 기준으로 이동
transform.Translate(Vector3.right * Time.deltaTime);
// 월드 좌표 기준으로 이동
transform.Translate(Vector3.forward * Time.deltaTime, Space.World);
}
매 프레임마다 값만큼 이동합니다.
물리작용이 필요없는(rigid body가 없는) 오브젝트에서 사용합니다.
transform.position에 직접 입력
transform.position=new Vector3(x,y,z);
//해당 위치로 이동합니다. (거리가 매우 가까운게 아니라면, 텔레포트같은 느낌)
transform.localPosition=new Vector3(x,y,z);
//localPosition은 상대좌표를 나타냄. 게임오브젝트의 부모가 있을 경우 부모로부터의 떨어진 좌표를 의미
Transform target;
float speed=10f;
void FixedUpdate()
{
Vector3 a= transform.position;
Vector3 b= target.position;
transform.position=Vector3.Lerp(a,b,speed);
//이런식으로 Lerp를 이용해서 부드럽게? 이동 구현 가능
}
public Transform Target;
public float Speed = 1.0f;
void Update()
{
transform.position = Vector3.MoveTowards(transform.position, Target.position, Speed * Time.deltaTime);
//현재위치, 목표위치, 속도 를 인자로 넘겨주면 현재 위치에서 목표 위치로 일정한 속도로 움직임
}
만약 rigidbody가 있는 오브젝트라면 transform.position은 지양하는것이 좋습니다.
이걸 사용하면 모든 콜라이더들이 rigidbody와의 상대적 위치를 재계산하기 때문입니다.
상황에따라서 RigidBody.position이나 RigidBody.MovePosition()을 사용합시다.
Rigidbody.MovePosition()
//rb는 리지드바디 컴포넌트를 의미
rb.MovePosition(new Vector3 (x,y,z));
//target지점의 position으로 RigidBody를 이동시킴
Rigidbody.MovePosition에는 interpolation옵션이 있기 때문에 Rigidbody가 있는 오브젝트의 경우 Rigidbody.MovePosition을 사용한 움직임을 구현하는것이 좋습니다. (Rigidybody.position은 interpolation은 없는듯..? 링크) (Rigidbody의 interpolation링크,)
transform.position을 이용하는 방법과의 차이점은, transform.position을 설정하는 것은 "텔레프트"의 개념입니다. 매우 작은거리를 계속 텔레포트 시킨다면 눈으로 보기에는 Rigidbody.MovePosition과 유사해 보입니다. 그러나 transform.position을 이용한다면, 이전 위치와 새 위치 사이에 있는 다른 오브젝트는 이동의 영향을 받지 않습니다. 또한 목표 위치에 있는 콜라이더는 다음 업데이트 시 이동한 리지드바디와 즉시 물리반응을 하게 됩니다.
그러나 rigidbody.MovePosition()을 사용하면 유니티가 이전 위치와 새 위치 사이의 직선 경로를 추적하고 업데이트 간에 해당 경로를 따라 빠르게 이동한 것처럼 처리합니다. 즉, 이전 경로와 새로운 경로 사이에 어떤 물리작용을 하는 물체가 존재한다면 물리 작용이 일어나게 됩니다.(transform.position의 경우 아무일도 안일어남)
즉, rigidbody컴포넌트를 지닌 오브젝트는 왠만하면 이 함수를 이용하면 되는데, 문제점이 있습니다.
바로, rigidbody 2D일 경우에는 Rigidbody2D.MovePosition을 통한 이동이 중력이나 선형 공기저항에는 영향을 받지 않습니다.(링크). 2D일 경우에는 MovePosition+중력을 적용해주기 위한 코드를 추가해주던지 다른 방법(rigidbody.velocity를 이용...)을 사용해야 겠습니다. 3d일 경우에는 정상이기때문에 사용하셔도 됩니다.
(위 문제는 rigidbody2d.moveposition은 위치를 고정시키려하는데 rigidbody2d.gravityscale은 당기려 하기 때문에, 이 과정에서 중력이 이겨서 천천히 중력의 방향대로 끌려가는것 같습니다.)
Rigidbody.position
rigid body컴포넌트를 지닌 물체를 텔레포트할때 사용합니다.
transform.position을 사용하여 텔레포트를 구현하면 모든 콜라이더들이 rigidbody와의 상대적인 위치를 재계산하기 때문에 성능적으로 이걸 사용하는것이 이득입니다.
(즉 움직이는 물체는 rigidbody컴포넌트를 달아주고 그것을 활용하여 움직여주는게 성능적으로 이득이라는 것이겠죠?)
또한 지속적인 움직임(캐릭터 이동등..)을 위해서는 interpolation이 적용되는 Rigidbody.MovePosition()을 사용하는 것이 좋다고 합니다.
Rigidbody.AddForce()
rigidbody.AddForce(new Vector3(x,y,z), ForceMode mode=ForceMode.Force);
//AddForce(방향*힘,힘의 종류)
말 그대로 리지드바디에 힘을 가해주는 것입니다.
단순히 이 기능만을 이용하여 움직임을 구현한다면 빙판에서 움직이는 것처럼 움직일 것입니다. (남아있는 힘들과의 벡터계산등을 통해서...이동이 결정되므로)
이때 힘의종류, 즉 파라미터로 넣어주는 ForceMode는 어떤 식으로 힘을 전달할 것인가를 결정해줍니다.
질량을 고려한다면, F=ma 공식이 적용되어서 질량에따른 가속도가 달라집니다.
Force: 연속적인 힘+ 질량을 고려함 (일반적인 물리 현상)
Acceleration: 연속적인 힘, 질량을 무시함 (질량에 관계없이 가속을 주고 싶다면 이용)
Impulse: 불연속적인 힘+ 질량 고려함 (짧은 순간의 힘, 충돌이나 폭발과 같은 것에 쓰임)
VelocityChange: 불연속적인 힘+ 질량 무시함 (질량을 무시해야하고 짧은 순간의 힘을 구현할떄)
이때, AddForce의 힘의 방향은 Global Coordinate입니다.
Rigidbody.AddRelativeForce()
rigidbody.AddRelativeForce(new Vector3(x,y,z), ForceMode mode=ForceMode.Force);
//AddRelativeForce(방향*힘,힘의 종류)
Rigidbody.AddForce는 Global coordinate가 기준이기 때문에 Local Coordinate를 기준으로 힘을 주고 싶을 때 사용합니다.
극단적인 예로, 차같은 경우 좌회전을 하는데 global인 경우 좌회전하기 전에는 w가 분명 직진인데 그 후에는 오른쪽이 됩니다. 이런 것을 해결해 주기 위해서 사용합니다.
그러나, AddForce로도 해당 오브젝트의 로컬 좌표로 힘을 가해줄 수 있는데,
rigidbody.AddForce(transform.forward)
//transform.forward를 사용하면 로컬좌표 기준 앞 방향을 world coordinate로 변환해서 알려줌
이런식으로 구현해도 됩니다.
Rigidbody.velocity
rigidbody에 질량과 상관없이 속도를 부여합니다.
공식문서에서는 이 값을 직접 수정하면, 비현실적인 동작이 발생할 수 있기 때문에 왠만하면 수정하지 말라고 안내합니다.
일반적인 사용법은 1인칭 fps게임에서 점프할 때 속도를 변경하는 것인데, 이는 즉각적인 속도 변화를 원하기 때문이라고 합니다.
Rigidbody-velocity - Unity 스크립팅 API
The velocity vector of the rigidbody. It represents the rate of change of Rigidbody position.
docs.unity3d.com
rigidbody2d의 경우 rigidbody2d.MovePosition은 중력적용이 이상하기 때문에, 중력을 고려한 점프가 필요한 경우엔 rigidbody2d.velocity를 사용해도 괜찮을 것 같습니다. rigidbody2d.AddFoce를 사용해도 괜찮을 것이구요.. (위 사진 출처:링크)
'유니티' 카테고리의 다른 글
[Unity] Input받는 방법 (Input System 이용) (0) | 2023.01.25 |
---|---|
[Unity] Awake와 Start차이 (0) | 2023.01.24 |
[Unity] Update(), FixedUpdate() 그리고 Physics Loop (0) | 2023.01.21 |
[Unity] tag, layer, sorting layer차이 (0) | 2023.01.21 |
[Unity] Rigidbody의 Gravity의 기준은? (0) | 2023.01.21 |