본문 바로가기
Unity • C#

[Unity] LateFixedUpdate

by SAENS 2023. 10. 4.

Unity에는 다음과 같이 세 가지 Update 함수가 있습니다.

Update()
LateUpdate()
FixedUpdate()

이 세 가지 업데이트 함수의 특징들을 간단히 짚어 보면, Update()는 매 프레임의 시작마다 호출되고, LateUpdate()는 매 프레임이 끝날 때마다 호출되며, FixedUpdate()는 프레임과 상관 없이 일정한 시간 간격마다 호출됩니다. FixedUpdate()는 물리엔진이 실행되는 기준이 되는 기본값이죠.

그런데 임의로 만든 어떤 MonoBehaviour 스크립트의 FixedUpdate()는 물리엔진보다 먼저 실행됩니다. 가령, OnCollisionEnter(~)에서 오브젝트의 충돌을 감지할 때 "Collision"을 출력하고, FixedUpdate()에서는 "f"를 출력하는 스크립트를 만들어서,

이 맨 오른쪽 버튼을 누르면서 천천히 관찰해보면,

공이 위에서부터 떨어지다가 아래의 1x1x1 블록 두 개의 중간에 충돌

58초에 f가 먼저 출력되고 그 다음에 Collision이 출력되는 것을 볼 수 있습니다.

그런데 저는 먼저 Collision이 일어나는 정보를 모두 수집한 뒤에 어떤 작업을 수행해야 했는데, 말하자면 LateUpdate도, Update도, FixedUpdate도 아닌 LateFixedUpdate가 필요한 것이었습니다.

하지만 안타깝게도 LateFixedUpdate는 없는 함수죠. 그래서 물리엔진이 실행되는 것을 수동으로 만져줌으로써 해결해야 합니다.

유니티의 물리엔진이 실행되는 것은 기본적으로 FixedUpdate()가 기준이지만, simulationMode 프로퍼티를 수정하여 그 기준을 바꿀 수 있습니다. SimulationMode는 0: FixedUpdate, 1: Update, 2: Script 이렇게 세 가지가 있죠.

void Awake()
{
    Physics.simulationMode = SimulationMode.Script;
}

위와 같이 SimulationMode.Script로 설정해주면, 스크립트에서 수동으로 Physics.Simulate(float step)을 호출해야 물리엔진이 실행됩니다.

이렇게 하면 다음 코드는 simulateMode = SimulationMode.Update일 때랑 같고,

void Update()
{
    Physics.Simulate(Time.deltaTime);
}

다음 코드는 simulateMode = SimulationMode.FixedUpdate일 때랑 같습니다.

void FixedUpdate()
{
    Physics.Simulate(Time.fixedDeltaTime);
}

 

물리엔진이 다 Simulate되고 난 이후에 어떤 함수를 실행하고 싶다면, 다음과 같이 코드를 작성해주면 됩니다.

void FixedUpdate()
{
    Physics.Simulate(Time.fixedDeltaTime);
    MyMethod();
}

void MyMethod() { ... }

Collision이 f보다 먼저 출력됨

댓글