유니티를 다루다 보면 Update(), FixedUpdate(), LateUpdate()가 있다는 것을 알게되지만 크게 신경쓰지 않고 대부분은 Update()를 통해서 내가 원하는 반복 동작을 실행시킨다.
다양하게 활용도가 조금 다르겠지만, 오늘은 물체의 이동 처리를 중점으로 세가지를 비교해보고자한다.
Update는 프레임마다 한 번씩 동작하며 그 간격이 일정하지 않다. 렌더링 엔진에서 얼마나 많은 그래픽 리소스를 로드하는지에 따라 느려지거나 빨라지기 때문에 일정하지 않은 시간에 물리적 충돌이 발생할 수 있다.
Rigidbody, BoxColider가 달린 플레이어에의 Update()
안에서 이동 처리를 해둔뒤
BoxColider가 달려있는 벽에 충돌하도록 앞으로 계속 이동 시켜보면 벽에 비벼지면서 왔다갔다 하는 모습을 볼 수 있다.
FixedUpdate는 보통 물리 처리에서 자주 사용되는데 프레임당 실행되는 Update와 달리 고정 시간 마다 동작하기 때문이다.
물리 엔진은 정확한 시간에 동작하기에 불안정한 Update가 아닌 FixedUpdate에서 회전, 힘, 이동 등의 처리를 해주어야 한다.
FixedUpdate에서는 이렇게 벽에 부딪히게 두어도 흔들리지 않는 편안함을 보여준다. 단, 아주 자세하게 보면 아주 사-알짝 흔들리고 있는 모습이 보이는데 이때 LateUpdate()가 사용될 순간이 온다.
LateUpdate는 모든 Update 문이 호출되고 가장 마지막에 호출이 된다. 여기에는 보통 카메라를 가장 많이 넣는다.
왜나면 Update에서 Input 체크, FixedUpdate에서 이동 처리 등의 과정이 다 끝나도 LateUpdate에서 카메라를 움직여 준다면 더욱더 부드러운 움직임을 보여줄 수 있다.
위 쪽 영상에서 보이던 약간의 흔들림도 보이지 않게 된다. 이렇게 세가지의 Update의 차이를 알아보았다.
효율에 신경쓴 코드는 아니지만, 오늘 공부한 내용을 통해서 각 Update 별로 그 역할에 맞게 코드를 넣은 예시이다.
public class Move : MonoBehaviour
{
[SerializeField] float speed = 5f;
bool IsRightArrowTouched = false;
bool IsLeftArrowTouched = false;
public Transform cam;
void Update()
{
if (Input.GetKey(KeyCode.RightArrow))
IsRightArrowTouched = true;
else
IsRightArrowTouched = false;
if (Input.GetKey(KeyCode.LeftArrow))
IsLeftArrowTouched = true;
else
IsLeftArrowTouched = false;
}
private void FixedUpdate()
{
if (IsRightArrowTouched)
transform.Translate(new Vector3(speed * Time.deltaTime, 0, 0));
if (IsLeftArrowTouched)
transform.Translate(new Vector3(-speed * Time.deltaTime, 0, 0));
}
private void LateUpdate()
{
Vector3 targetPos = new Vector3(transform.position.x, 0, cam.position.z);
cam.position = targetPos;
}
}