Update()와 FixedUpdate()
Update()
Update()
메소드는 프레임 당 한 번씩 호출된다.
그리고 이동, 회전 등을 구현할 경우 프레임 간의 호출 간격을 고려하고
단위 시간 당 일정한 수치로 기능을 구현하기 위해 Time.deltaTime
을 사용한다.
FixedUpdate()
리지드바디를 사용할 때, 즉 물리 엔진의 기능을 이용할 때 사용하는 메소드.
FixedUpdate()
메소드는 Fixed Time Step 주기(기본 0.02초)마다 한 번씩 호출되도록 보정된다.
그냥 ‘호출된다’가 아니고, ‘호출되도록 보정된다’.
왜냐하면, FixedUpdate()
의 호출은 Update()
를 호출하는 게임 루프와 별도의 루프, 혹은 멀티스레드에 의해 발생하지 않기 때문이다.
Update()
를 호출하는 게임 루프에서 또다른 내부 물리 루프를 통해 FixedUpdate()
를 호출한다.
다시 말해, FixedUpdate()
의 호출 역시 각각의 프레임 내에서 이루어진다.
예를 들어 Frame Rate = 50일 경우, 즉 매 프레임이 0.02초마다 실행될 경우
매 프레임마다 Update()
, FixedUpdate()
는 한 번씩 호출될 것이다.
Frame Rate = 25일 경우, 즉 매 프레임이 0.04초마다 실행될 경우
Update()
는 역시 매 프레임마다 호출되겠지만,
FixedUpdate()
는 고정된 Fixed Time Step 주기에 맞출 수 있도록
매 프레임마다 두 번씩 호출될 것이다.
반면에 성능이 아주 좋아서 Frame Rate = 250쯤 된다면,
프레임은 0.004초 간격으로 실행된다.
그리고 FixedUpdate()
는 5프레임마다 한 번씩 호출될 것이다.
즉, 5프레임마다 4프레임은 FixedUpdate()
가 호출되지 않는다.
FixedUpdate()로 이동, 회전 시 버벅임 현상
위에서 서술했듯,
FixedUpdate()
는 기본적으로 0.02초마다 실행된다.
Frame Rate로 따지자면 50에 해당한다.
따라서 현재 Frame Rate가 50보다 클 경우,
FixedUpdate()
가 호출되지 않는 프레임들이 존재하기 때문에
분명 사용자 입력이 이루어지는데도 움직임이 업데이트되지 않는 프레임들이 존재하여
FixedUpdate()
를 이용한 이동, 회전이 버벅이는 듯이 보일 수 있다.
버벅임 현상 해결 방법
FixedUpdate()
의 이동, 회전에 의한 버벅임 현상은 어떻게 해결할 수 있을까?
Frame Rate와 Fixed Time Step을 고려하여,
FixedUpdate()
가 프레임당 최소 한 번은 호출되도록 해주어야 한다.
다시 말해, FixedUpdate()
가 호출되지 않는 프레임이 없어야 한다.
이를 위해 두 가지를 설정할 수 있다.
[1] Target Frame Rate를 지정한다
스크립트에서 Application.targetFrameRate
값을 설정하여 최대 Frame Rate 제한을 지정할 수 있다.
Fixed Time Step이 기본 값(0.02)일 때, 초당 물리 업데이트 횟수는 50이다.
만약 Fixed Time Step을 그대로 유지하고 버벅임 현상을 없애려면,
targetFrameRate
값을 50 이하로 설정하여
프레임 당 FixedUpdate()
가 최소 1번 이상 호출되도록 해주면 된다.
[2] Fixed Time Step을 조정한다
Frame Rate에 맞추어 물리 업데이트 주기를 변경할 수도 있다.
[Edit] - [Project Settings] - [Time]
창을 연다.
Fixed Time Step은 기본적으로 0.02로 지정되어 있는데,
이 값을 (1 / Frame Rate)로 계산하여 넣어주면 된다.
예를 들어 Frame Rate가 60이면 (1 / 60) = 0.016667로 설정하면 된다.
보통 이렇게 targetFrameRate
값을 먼저 결정하고,
이에 맞추어 Fixed Time Step 값을 조정하는 것이 일반적이다.
결론
[1] Target Frame Rate 설정
게임의 특징, 실행할 기기 환경 등에 따라 Target Frame Rate를 설정한다.
스크립트에서 Application.targetFrameRate
를 통해 설정할 수 있으며
캐주얼, 아케이드 등 가벼운 게임은 30,
FPS, 액션 게임처럼 부드러운 화면 업데이트가 필요하면 60으로 설정하는 경우가 많다.
모바일 대상인 경우, 액션 게임이라도 최적화를 위해 30으로 설정할 수도 있다.
[2] 계산을 통해 Fixed Time Step 설정
물리 엔진 기반으로 움직임들을 구현할 경우,
Target Frame Rate에 따라 알맞은 Fixed Time Step 값을 설정해준다.
프레임당 최소 한 번의 물리 업데이트가 발생하도록 하는 것이 목적이다.
계산 방법
Fixed Time Step = (1 / Target Frame Rate)
예를 들어,
Target Frame Rate = 60이면 (1 / 60) = 0.016667,
Target Frame Rate = 30이면 (1 / 30) = 0.033333으로 설정한다.
예시
공통
- Target Frame Rate = 120
(Delta Time = (1 / 120) = 0.008333)