FixedUpdate는 유니티에서 물리연산을 하는데 최적화된 함수이다.
그렇다면 이 FixedUpdate가 무슨 이점을 주길레 물리연산을 할때 써야할까?
아래는 같은 코드를 FixedUpdate문과 Update문에 넣고 실행한 결과이다.
위에 있는 동그라미가 FixedUpdate, 아래에 있는 동그라미는 Update로 실행한 것이다.
using UnityEngine;
public class Move : MonoBehaviour
{
void Update()
{
if(Input.GetKey(KeyCode.A))
{
transform.position += Time.deltaTime * new Vector3(-10, 0, 0);
}
}
}
using UnityEngine;
public class MoveFixed : MonoBehaviour
{
private void FixedUpdate()
{
if (Input.GetKey(KeyCode.A))
{
transform.position += Time.deltaTime * new Vector3(-10, 0, 0);
}
}
}
이렇게 같은 코드를 넣어서 실행했지만 다른 결과가 나는 이유는 FixedUpdate의 두가지 성질 때문이다.
1. FixedUpdate가 실행하고 나서 바로 물리연산이 이루어 진다. 이는 유니티 실행주기를 살펴보면 알 수 있다.
https://docs.unity3d.com/kr/current/Manual/ExecutionOrder.html
여기서 말하는 물리연산은 위 사진의 Physics 부분이다. 유니티에서는 이부분에서 각 오브젝트들 끼리의 충돌, 마찰, 관성 등 모든 물리연산을 실행한다. 이때문에 FixedUpdate에서 실행된 결과값에 의해 각 콜라이더를 가진 두 오브젝트가 겹칠경우 값을 바로 수정해준다. (단 두 오브젝트중 적어도 한개 이상은 Rigidbody를 가지고 있어야 작동한다.)
2. FixedUpdate는 일정한 실행주기를 보장받는다. (기본값은 0.02초에 한번)
Update문은 Update문 안에 있는 모든 코드를 실행하고 나면 바로 다음 Update문을 실행한다. 이렇게 Update문이 한번 실행하는 것을 한 프레임 이라고 부르고 1초에 몇프레임이 실행됐는지를 FPS(Frames Per Second: 초당 프레임) 이라고 부른다. 그리고 이 프레임이 실행되는 시간은 아래 사진처럼 계속 바뀐다.
(이 한 프레임을 실행하는 시간은Time.deltaTime 값으로 알 수 있다.)
반면에 FixedUpdate는 0.02초에 한번씩 실행되는 효과를 준다. 만약 한 프레임이 실행되는데 0.02초보다 오래걸리면 한 프레임에 FixedUpdate가 두번 이상 실행되고 0.02초보다 적게 걸리면 그 프레임에 실행되지 않을 수 있다. 이를 통해 정확히 0.02초에 한번씩 실행되는 효과를 준다. 이후 Physics가 실행된다.
이렇게 FixedUpdate는 일정한 시간마다 한번씩 실행되며 실행 직후 각 오브젝트들간의 물리연산을 실행한다. 반면에 Update는 호출되는 시간이 계속 다르고 Update가 실행되고 직후에 물리연산을 하지 않아 오브젝트끼리 충돌을 해도 바로 체크를 할 수 없다. 그래서 이와 같은 현상이 나타나는 것이다.
따라서 유니티에서 모든 물리연산은 FixedUpdate에서 해야한다.
하지만 FixedUpdate가 만능은 아니다. 아래 사진은 위와 똑같은 상황에서 벽 크기만 줄인것이다. 하지만 벽에 있는 콜라이더를 전혀 감지하지 못했다. 나는 이전에 이와 같은 상황을 만났을 때 RayCast로 처리했었다. 물론 RayCast도 좋지만 반듯이 물리연산으로 이를 처리해야 하는 상황이 올 수 있다. 이에 대해서는 다음 글에서 다뤄보겠다.
'Unity 분석' 카테고리의 다른 글
Enum의 활용 (0) | 2023.01.07 |
---|---|
코루틴의 작동방식 (0) | 2023.01.06 |
메모리 구조와 유니티 - GC에 대한 심층적 이해 (0) | 2023.01.05 |
GameObject.Find() (0) | 2023.01.04 |
물체가 이동하면서 얇은 벽을 통과하는 경우 (0) | 2023.01.04 |