2015년 1월 22일 목요일

유니티 - Time.deltaTime

델타의 용어뜻

delta : an incremental change in a variable

불행히도 네이버 사전에는 없고
그냥 구글을 뒤져보면 여러뜻중에 저런 것이 있다
사실 우리도 지겹게 보아온 단어다
수학에서.. 델타가 어쩌구..
간단히 변화값이다. 혹은 경과값이라고 할 수 있다

유니티의 Time.deltaTime

여기서 유니티의 문서를 보면 Time.deltaTime을
이렇게 정의해놨다

The time in seconds it took to complete the last frame

바로 전프레임이 완료되기까지걸린 시간이다
1초 걸렸으면 1이 되고 10초 걸렸으면 10이 된다

즉, 컴터가 느릴수록 deltaTime이 커지는 특성이 있다
deltaTime 자체의 정보도 유용하지만 저 특성을 이용하면
컴퓨터의 성능차를 해결할 수가 있는 핸디캡으로 쓸 수 있다

델타타임의 용도1 - 성능보정

이건 쉬움

초인밥과 우리가 그림 경쟁을 벌이고 나면
다 부질없어 보이고 공허하고 뭐 그렇다

게임 역시 그렇다. 성능이 짱짱인 밥 같은 컴터랑
구석기 시대에 쓰던 컴터가 아무런 보정도 없이 맞붙으면
‘실력은 되는데 렉 때문에..’
라는게 정말 현실이 된다

하지만 그런 개소리를 방지하기위해
똥컴과 최신컴을 강제로 맞추는 방법이 있다

위에서 말한 핸디캡 바로 Time.deltaTime 이다

시간과 프레임의 개념

먼저 확실히 해둬야 할 것이
시간과 프레임의 개념이다
바로 시간은 누구에게나 공평하게 흐르지만
프레임은 그렇지 않다는 것이다

프레임이란 건
연속된 그림을 빠르게 넘기는 것에 비유할 수 있다
밥 형님은 복잡한 그림도 금방 금방 그려서 넘어갈 수 있다
하지만 우린 성능이 딸려서 빨리빨리 못그린다
그래서 화면이 버벅거리는 것처럼 보이는 것이다
결국 성능에 따라 1초에 10프레임이 나올 수도 있고
100프레임이 나올 수도 있다

만컴은 공평해야 한다

버벅거리는 것은 어쩔 수 없지만
결과가 성능에 따라 좌우되는 것만은 절대 안된다
상대랑 결투를 하는데 다른 이유가 아니라
컴퓨터 성능때문에 이쪽이 칼질 1번할 동안
저쪽은 30번해서 내가 걸레가되면 겜 할 맛이 날리가 없다

그래서 각 프로그램이 실행될땐 각 컴터성능에 따라 한프레임에 나오는
결과값을 보정해줘야한다

그럼 각 컴터의 성능은 어떻게 측정할까.
성능이라고 하면 당연히 빠르기이다. 그리고 우린 그 속도의 공식을 알고 있다
바로

컴터의 속도는 그렇다치고 거리가 뭥미 할 수 있지만
거리도 있다. 바로 프레임이다.
10초동안 10000 프레임을 달린 컴이
10초동안 100 프레임을 달린 컴보다 훨 빠르다
즉, 위의 식은 아래처럼 될 수 있다

우리가 하고자하는 것은 똑같은 10초의 시간동안 성능이 좋은 컴과
나쁜컴이 동일한 결과를 내는 것이다
초당 10프레임의 컴과 초당 20프레임의 컴의 결과를 같게 할려면?
결과값(처리한 프레임)이란건 속도x시간 이다
여기서 성능에 따라 다른 건 속도니까 각자의 속도로 나눠버리면
결과값 = 시간
이 되어 이제 시간과 결과값이 비례하게 된다.

근데 우린 주로 Update문에서 작업을 많이 한다
Update문은 한 프레임이다
그러므로 한 프레임의 속도는 이 된다
여기서 우린 1 프레임 실행 시간은 이미 알고 있다
바로 Time.deltaTime 님이시다

자 그럼
이게 1프레임의 속도이고 이대로 나눠주면 되는데
Time.deltaTime 은 속도의 역이므로 그대로 곱해주면 된다

시간, 속도 제어

Time.deltaTime은 각 프레임마다 곱해주면 성능에 관계없이
시간마다(프레임이 아니라) 동일한 결과를 낼 수 있게하는 편리한 놈이다

한데 한프레임의 시간을 알 수 있으면
시간이나 속도 제어도 할 수 있다

1프레임에 0.1초 걸린다고 하면 10초간 뭔가 하고 싶을때

deltaTime * frame = 10
frame = 10 / deltaTime

이렇게 몇 프레임이 걸리는 지 알수 있다
한데 우린 몇 프레임 걸리는 것보다 1프레임당 어떻게 해줘야되는지가
궁금하다.
가장 간단한건 아래처럼 목표 프레임 수를 구하고
매프레임 목표프레임이 되었는지 검사하는 방법이다

int frame = (int)(10 / Time.deltaTime);
float no = 0;
void Update(){
    if(frame != now){
        now++;
        작업내용...
    }
}

한데 Mathf.Lerp 같은 메서드들이 백분율로 작업해줘야하는 것들이라서
(Mathf.Lerp 에 관한 내용은 여길 참조)
보통 1 프레임당 걸려야 할 시간 이라는 기준으로 작업한다
그래서 을 수행하는 시간으로써
결국

이렇게 되어 매 프레임마다 목표시간을 나눠주게 된다.
예제는 다음과 같다

float movingTime = 10.0f;
float progress = 0.0f;          // 진행 백분율
void Update(){
        if(progress < 1){
            progress += Time.deltaTime / movingTime;
            작업내용..
        }
    }

Mathf.Larp 를 쓸 경우

float movingSpeedOrTime = 10.0f;
...
void Update(){
        from = Mathf.Larp(from , to, Time.deltaTime / movingSpeedOrTime);
        ...
    }

Written with StackEdit.

0 개의 댓글 :

댓글 쓰기