Lerping 함수에서 Time.deltaTime을 사용하는 이유는 무엇입니까?


12

내 이해 두 값 (사이 LERP 함수로 보간 ab세 번째 값 (사용) t) 사이 01. at t = 0에서는 값 a가 반환되고 at t = 1는 값 b이 반환됩니다. 0.5에서 a와 사이의 값 b이 반환됩니다.

(다음 그림은 일반적으로 3 차 보간법입니다.)

여기에 이미지 설명을 입력하십시오

포럼을 탐색 했으며이 답변 에서 다음 코드 줄을 발견했습니다.transform.rotation = Quaternion.Slerp(transform.rotation, _lookRotation, Time.deltaTime);

나는 나 자신에게 "얼마나 어리석은 지 모른다"고 생각했지만 40 개 이상의 공감대가 있었기 때문에 시도해 보았고 충분히 효과가있었습니다!

float t = Time.deltaTime;
transform.rotation = Quaternion.Slerp(transform.rotation, toRotation, t);
Debug.Log(t);

0.010.02for 사이에 임의의 값이 t있습니다. 함수가 그에 따라 보간되어서는 안됩니까? 이러한 값이 누적되는 이유는 무엇입니까? 내가 이해하지 못하는 것은 무엇입니까?


1
A는 보통 위치이며, 1/60 (60fps)에서의 샘플링을 위해 A와 B 사이의 거리를 지속적으로 좁히는 0.16의 보간에 의해서만 물체를 움직입니다 (따라서 매번 샘플이 더 작고 작아짐).
Sidar

당신은 t를 기록하고 tt로 lerped했습니다 ... 이들은 다른 변수입니다.
user253751

답변:


18

이 답변도 참조하십시오 .

사용하는 두 가지 일반적인 방법이 있습니다 Lerp.

1. 시작과 끝 사이의 선형 혼합

progress = Mathf.Clamp01(progress + speedPerTick);
current = Mathf.Lerp(start, end, progress);

가장 친숙한 버전입니다.

2. 목표를 향한 기하 급수적 완화

current = Mathf.Lerp(current, target, sharpnessPerTick);

이 버전에서는 current값이 출력 입력 모두로 나타납니다 . start변수를 대체 하므로 마지막 업데이트에서 이동 한 곳에서 항상 시작합니다. 이것이 Lerp한 프레임에서 다음 프레임 으로이 버전의 메모리를 제공하는 것입니다. 그런 다음이 이동 시작점 target에서 sharpness매개 변수 에 의해 지시 된 방향으로 거리의 일부를 이동합니다 .

Zeno와 같은 방식으로 대상에 접근하기 때문에이 매개 변수는 더 이상 "속도"가 아닙니다 . 경우 sharpnessPerTick했다 0.5후 첫 번째 업데이트에 우리는 우리의 목표에 절반 이동할 것입니다. 다음 업데이트에서는 나머지 거리의 절반 (초기 거리의 1/4)을 이동합니다. 다음에 우리는 다시 반을 움직일 것입니다 ...

이는 목표에서 멀어 질 때 움직임이 빠르며 점진적으로 접근함에 따라 점진적으로 느려지는 "지수 적 여유"를 제공합니다 (무한 정도의 숫자를 사용하면 유한 한 수의 업데이트에서는 도달하지 않습니다. 충분히 가까워집니다). 이동 목표 값을 추적하거나 " 지수 이동 평균 "을 사용하여 노이즈 입력을 평활화하는 데 유용합니다. 일반적으로 매우 작 거나 작은 sharpnessPerTick매개 변수를 사용합니다 0.1.


그러나 당신이 맞습니다, 당신이 링크 한 공감 답변에 오류가 있습니다. deltaTime올바른 방법으로 수정하지 않습니다 . 이 스타일을 사용할 때 매우 일반적인 실수입니다 Lerp.

첫 번째 스타일 Lerp은 선형이므로 다음을 곱하여 속도를 선형으로 조정할 수 있습니다 deltaTime.

progress = Mathf.Clamp01(progress + speedPerSecond * Time.deltaTime);
// or progress = Mathf.Clamp01(progress + Time.deltaTime / durationSeconds);
current = Mathf.Lerp(start, end, progress);

그러나 지수 완화는 비선형 이므로 sharpness매개 변수에 곱 deltaTime하면 정확한 시간 보정이 제공되지 않습니다. 우리의 프레임 속도가 변동하면 움직임의 판단으로 나타나거나 30에서 60으로 일정하게 유지하면 부드럽게 선명도가 변경됩니다.

대신 우리는 지수 편이성을 위해 지수 수정을 적용해야합니다.

blend = 1f - Mathf.Pow(1f - sharpness, Time.deltaTime * referenceFramerate);
current = Mathf.Lerp(current, target, blend);

여기 에 시간을 수정하기 전에 사용했던 것과 동일한 단위를 유지하는 referenceFramerate것과 같은 상수가 있습니다 .30sharpness


이 코드에는 논쟁의 여지가있는 또 다른 오류가 있습니다. Slerp구형 선형 보간은 전체 움직임을 통해 정확하게 일관된 회전 속도를 원할 때 유용합니다. 그러나 우리가 어쨌든 비선형 지수 편이성을 사용한다면 Lerp거의 구별 할 수없는 결과를 얻을 것이며 더 저렴합니다. ;) 쿼터니언은 행렬보다 훨씬 뛰어나므로 일반적으로 안전한 대체 방법입니다.


1

이 시나리오에서 빠진 핵심 개념은 A가 고정되어 있지 않다고 생각합니다. A는 각 단계마다 업데이트되지만 Time.deltaTime의 보간에 따라 많이 업데이트됩니다.

따라서 A가 각 단계마다 B에 가까워지면서 보간의 총 공간은 각 Lerp / Slerp 호출에 따라 변경됩니다. 실제 수학을 수행하지 않으면 그 효과가 Smoothstep 그래프와 같지 않지만 A가 B에 가까워짐에 따라 감속을 근사화하는 가장 저렴한 방법이라고 생각합니다.

또한 B도 정적이 아니기 때문에 자주 사용됩니다. 일반적인 경우는 플레이어를 따르는 카메라 일 수 있습니다. 카메라가 특정 위치 또는 회전으로 이동하게하는 경우, 흔들림을 피하려고합니다.


1

당신이 옳습니다, 그 방법 Quaternion Slerp(Quaternion a, Quaternion b, float t)은 사이에 a그리고 b양에 의해 보간 됩니다 t. 그러나 첫 번째 가치를 지켜보십시오. 그것은 시작 가치가 아닙니다.

여기서 메소드에 주어진 첫 번째 값은 현재 객체 회전 transform.rotation입니다. 따라서 각 프레임 에 대해 현재 회전과 목표 회전 사이 _lookRotation의 양만큼 보간 됩니다 Time.deltaTime.

이것이 부드러운 회전을 만드는 이유입니다.


2
지금 나는 바보 같은 느낌
AzulShiva

@AzulShiva 할 일이 모든 사람에게 일어나는 걱정하지)
루도빅 Feltz
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.