2015년 2월 7일 토요일

유니티 Mathf.Lerp Mathf.LerpAngle

목차


Mathf.Lerp 선형보간법

Interpolation 이라는 용어가 있는데 보간법(補間法)이라고 한다

본인은 수학도 잼병이고 이런 용어도 너무 약하다
거기다 검색해보니 너무 고차원적이라 간신히 흰것은 웹페이지 바탕화면이고
검은것은 글씨라는 것 정도만 해석 가능했다
그래도 어쩌랴 궁금한걸..;;;

일단 용어부터 시작하겠다
보간.. 간격을 보충한다는 말이다. 여기서부터 슬슬 복잡하게 전개되는데
본인은 그런건 관심없고 용도만 관심있으므로 최대한 내 맘대로 설명하겠다

어떤 두점 사이에서의 위치를 수학공식이나 법칙에 따라
t 라는 진행시간에 어디에 있을지 예측해내는 것이다

예를들면 친구가 놀러온다고 했을때
‘어디쯤 왔을려나? 아까 출발했으면 대충 xx슈퍼앞이겠네’
이게 보간법이다.
내 집(시작점)과 친구집(끝점)을 알고 있고 칭구의 속도라거나 길이라거나
내가 알고 있으므로 위치 예측이 가능하다
물론 지그재그로 온다거나 하면 예측공식은 더더욱 복잡해지는데
그냥 직선으로 온다고 가정하는 것을 선형보간법(Lerp)이라고 한다
그리고 여기서 t 라는 값은 진행시간 혹은 진행과정인데
그런걸 나타내는데는 역시 백분율이 짱이다
그래서 출발을 0으로 두고 도착을 1로 둔다.
그냥 정수로 했으면 나 같이 단순한 사람은 평화를 만끽했을텐데 아쉽게도
더욱 정밀한 걸 원하는 사람이 많아서 실수(float)로 0과 1사이가 되었다
대충 0은 0%, 0.5는 50%, 1은 100% 라고 생각하자

이제는 Mathf.Lerp 의 설명이 좀 쉽게 된다

Mathf.Lerp(float from, float to, float t);

from은 시작점, to는 끝점, t는 진행률이다
당연히 t가 0일때 반환값은 from 이고 1일땐 to를 반환한다
0.5일땐 from과 to의 중간값을 반환한다

예를들어

Mathf.Lerp(10f, 20f, 0.2f);

이면 10과 20의 20% 지점인 12를 반환한다.

Mathf.LerpAngle

Mathf.LerpAngle 은 위의 Mathf.Lerp 메서드의 각도버전으로
작동방법은 비슷하다
하지만 두가지가 다른데
첫째로 각도버전이므로 시작값과 끝값이 360도 범위를 벗어나면 안된다
벗어날 경우 NULL인지 예외발생인지 모르겠지만 여튼 작동하지 않는다
둘째로 Mathf.Lerp로 루프문을 돌릴 경우
Lerp( 300, 350, t) 이러면 t의 비율로 점점 300이 350으로 다가선다
이건 아무 문제가 없다. 그런데 각도는 360이 한계다
그래서 그걸 넘으면 다음과 같은 일이 생길 수 있다
Lerp( 300, 0, t)
300이 360을 향해 다가서다가
갑자기 0으로 돌아선 목표를 따라 이번엔 반대방향에서 다가서는 것이다
이 경우 물체가 회전을 하다 360을 넘으면 급격히 반대방향으로
도는 현상을 볼 수 있다
하지만 Mathf.LerpAngle은 그런 것을 내부에서 잘 처리해준다

이제 실사용예를 보자

float lerpAngle = Mathf.LerpAngle (tr.eulerAngles.y, target.eulerAngles.y, smooth * Time.deltaTime);

//간소화

float 목표각도 = Mathf.LerpAngle(나의 현재각도, 타겟의 현재각도, 민감도);

아래쪽의 간소화대로 설명하면
주로 얘는 LateUpdate() 같은데 쓰이는데 여튼 계속 업뎃함수로 무한 루프를 돈다
그럼 목표각도는 나의 각도와 타겟의 각도 사이의 값을 주는데
민감도 값이 100% (실제 float값으론 1.0f) 면 당연히 타겟 각도를 바로 돌려주어서
업뎃 한번에 타겟과 동일 각도를 유지하게 된다
반대로 민감도 값이 낮으면 낮을 수록
(그렇다고 0을 먹이면 각도 변화는 없으니 하지마-_-;;)
목표각도가 타겟의 각도에 쪼금씩 접근하게 된다.

예를들어 0.5를 먹이고 A(나) 와 B(목표)가 각각 0도 100도 라면

  1. 50도, 100도 - 변화량 100도의 절반인 50도
  2. 75도, 100도 - 변화량 50도의 절반인 25도
  3. 87.5도, 100도 - 변화량 25도의 절반인 12.5도

이런 식이다. 나름 목표에 가까워지면서 자연스럽게 느려지는 효과도
부가적으로 얻을 수 있는 것이다

아.. 수학 실타..;ㅁ;…

주의점

Lerp를 목표수치에 정확하게 도달하는지 검출하는 식으로 사용하면 안된다.
예를들어 아래 문장을 무한루프를 돌렸을때
from = Mathf.Lerp(from, to, T);
최종적으로 from이 to 값이 되진 않는다는 것이다
T가 1이 아닌이상 매우 가까워지긴 하지만 닿진 않는다
또한 거리 보간 효과를 노리고
sqrMagnitude 와 같이 사용하는 것은 금물이다.
sqrMagnitude 는 제곱값이기 때문에 float.Epsilon 과 비교했을시
최소값에 도달하지 않아서 원하는 결과가 나오지 않을 수가 있다
….ㅠㅠ;; 본인얘기임..

Written with StackEdit.

댓글 2개 :

  1. 필요한 정보였는데 정리가 깔끔하게 되어있어서 많은 도움 되었습니다. 감사합니다.^^

    답글삭제
  2. 이해 잘하고 갑니다!

    답글삭제