Lerp를 프로처럼 사용하는 방법

나는 이런 종류의 일을 너무 자주 본다:

transform.position = Vector3.Lerp(startPos, endPos, Time.deltaTime);

그것을 게시하는 사람은 일반적으로 그것이 Vector3.Lerp“깨졌다”고 확신하지만 실제 문제는 그들이 그것을 올바르게 사용하지 않는다는 것입니다.

“선형 보간”의 약어인 Lerp는 매우 간단한 작업을 수행합니다. 두 값이 주어지면 두 값 x사이 의 백분율 y값을 반환합니다 . t출력이 변경될 것으로 예상되는 경우 전달하는 인수에 이를 반영해야 합니다!

Time.deltaTime위의 예에서는 가장 최근 프레임 동안 경과한 시간만 전달하므로 를 전달하는 것은 의미가 없습니다 . 게임이 일정한 50fps로 실행되는 경우 항상0.02 .

해당 타이머가 여러 프레임에 걸쳐 누적되도록 하면 더 나은 결과를 얻을 수 있습니다.

이와 같은 내용이 요점을 전달해야 합니다.

public class LerpExample : MonoBehaviour {
    float lerpTime = 1f;
    float currentLerpTime;
 
    float moveDistance = 10f;
 
    Vector3 startPos;
    Vector3 endPos;
 
    protected void Start() {
        startPos = transform.position;
        endPos = transform.position + transform.up * moveDistance;
    }
 
    protected void Update() {
        //reset when we press spacebar
        if (Input.GetKeyDown(KeyCode.Space)) {
            currentLerpTime = 0f;
        }
 
        //increment timer once per frame
        currentLerpTime += Time.deltaTime;
        if (currentLerpTime > lerpTime) {
            currentLerpTime = lerpTime;
        }
 
        //lerp!
        float perc = currentLerpTime / lerpTime;
        transform.position = Vector3.Lerp(startPos, endPos, perc);
    }
}

빈 장면을 만들고, 큐브에 놓고, 이 스크립트를 첨부하고, 실제로 작동하는 모습을 볼 수 있습니다.

변수는 원래 있던 perc곳에 사용됩니다 . Time.deltaTime무엇입니까 perc? 이는 Lerp를 통한 진행 상황을 나타내는 0와 사이의 숫자입니다 .1

궁금하신 분들은 lerpTime또는 변경하면 결과를 확인해보세요 moveDistance.

모든 것을 Lerp

Unity는 다양한 값을 보간하기 위한 도우미 함수를 제공합니다.

  • Mathf.Lerp
  • Vector3.Lerp
  • Color.Lerp

하지만 결국에는 Mathf.Lerp 만 있으면 됩니다. 다른 것들은 단지 편의를 위한 방법일 뿐입니다. 보간해야 할 클래스나 데이터에 대해 자체 Lerp 함수를 작성하는 것은 충분히 쉽습니다.

Unity가 회전을 표현하기 위해 사용하는 쿼터니언의 특정 경우에는 Slerp 또는 “Spherical Lerp”도 있습니다.

두 개의 값이 있고 두 값 사이를 원활하게 전환하고 싶으십니까? 보간은 당신의 친구입니다!

Lerp 너머

만약 우리가 t단순한 백분율이 아닌 Lerp a를 통과한다면 어떻게 될까요? 두 점 사이에 그래프로 표시된 직선 대신 일종의 곡선을 원하면 어떻게 될까요? 0입력은 과 사이에 있어야 1하지만 이를 수행하는 기능이 많이 있습니다.

예를 들어, sinerp를 사용하여 “완화”할 수 있습니다.

float t = currentLerpTime / lerpTime;
t = Mathf.Sin(t * Mathf.PI * 0.5f);
interp-sinerp

또는 coserp를 사용하여 “편안하게” 할 수도 있습니다.

t = 1f - Mathf.Cos(t * Mathf.PI * 0.5f)
interp-coserp

기하급수적인 움직임을 만들 수도 있습니다.

t = t*t
인터프 쿼드

그 자체를 곱하는 것에 는 흥미로운 특징이 있습니다. 과 사이에 있는 t한 , 그 자체를 여러 번 곱하면 항상 와 사이에 있는 숫자가 생성됩니다 .t01t01

스무스스텝

위에서 언급한 곱셈 속성은 유명한 “스무스 스텝” 공식 과 같이 이지 인(Ease In)  이지 아웃(Ease Out)하는 일부 보간 방법의 핵심 개념입니다 .

t = t*t * (3f - 2f*t)
매끄러운

아니면 제가 개인적으로 좋아하는 “smootherstep”도 있습니다.

t = t*t*t * (t * (6f*t - 15f) + 10f)
상호 평활화

정말 매끄러워요! (저항할 수 없었습니다.)

제가 언급한 이러한 추가 공식 중 다수는 Unity에 포함되어 있지 않지만, 이를 통해 찾거나 생성할 수 있는 모든 함수를 자유롭게 사용할 수 있습니다.

숨쉬게 해라

끝나지 않는 Lerp는 어떻습니까?

Robert Yang은 “가끔 사인파로 게임의 모든 것을 애니메이션화할 수 있었으면 좋겠다”고 말한 적이 있습니다 .

일부 게임에서는 플레이어가 실행되는 동안 약간의 “머리 흔들림”이 발생합니다. 다른 게임에서는 메인 메뉴 카메라에 부드러운 밥이 필요합니다. 나는 “코를 고는” 불빛이 점점 희미해졌다가 사라지는 것을 본 적이 있습니다. 어떤 경우이든, 나는 파동 함수가 얼마나 환상적으로 유용할 수 있는지 지적하고 싶습니다. 입력 영역은 무한하므로 끝이 없으며 출력 범위는 좁고 일정하므로 제어하기 쉽습니다.

예를 들어, 다음 스크립트는 사인파에 따라 객체를 천천히 위아래로 움직이게 만듭니다.

public class BreatheSimple : MonoBehaviour {
    Vector3 startPos;
 
    protected void Start() {
        startPos = transform.position;
    }
 
    protected void Update() {
        float distance = Mathf.Sin(Time.timeSinceLevelLoad);
        transform.position = startPos + Vector3.up * distance;
    }
}

사인파를 조정하면 더 많은 제어가 가능해집니다.

public class Breathe : MonoBehaviour {
    Vector3 startPos;
 
    public float amplitude = 10f;
    public float period = 5f;
 
    protected void Start() {
        startPos = transform.position;
    }
 
    protected void Update() {
        float theta = Time.timeSinceLevelLoad / period;
        float distance = amplitude * Mathf.Sin(theta);
        transform.position = startPos + Vector3.up * distance;
    }
}

진폭은 개체가 이동하는 거리를 제어합니다. period는 얼마나 빨리 수행되는지를 제어합니다.

interp-sineparams

플레이어의 머리 봅슬레이에는 작은 진폭과 짧은 기간이 필요할 수 있습니다. 메뉴 카메라의 느린 호흡으로 인해 매우 오랜 시간이 걸리거나 다양한 속도로 여러 축에서 움직임이 필요할 수 있습니다.

수학을 정리할 수만 있다면 원하는 동작은 무엇이든 얻을 수 있습니다.

사인파의 절대값만 취하면 어떻게 될까요? 상향 전용 수신 거부.

사인파의 출력을 0과 사이에 고정하면 어떻게 됩니까 1? 바운스 사이에 일시 중지가 있는 위쪽으로만 바운싱합니다. 이유를 알 수 있나요? 고정된 곡선을 직접 그리면 명확해집니다.

0.6해당 웨이브의 출력을 과 사이에 고정하면 어떻게 될까요 1? 일종의 “두근두근” 모션을 얻을 수 있나요? UI에서 경고를 확장하는 데 유용할 수 있습니까?

정말 멋지게 만들고 싶다면 애니메이션 곡선을 사용하여 Lerp 매개변수를 관리할 수도 있습니다.

나는 꽤 난해한 곡선과 파동 함수를 작성했습니다. 그것을 섞는 것을 두려워하지 마십시오.

닫는 중

Lerp는 다양한 응용 프로그램에서 쉽고 강력한 기능입니다.

제가 작성한 첫 번째 플러그인 중 하나는 다양한 줌과 위치 사이를 보간하는 카메라 관리자였습니다. 또한 보간을 사용하여 재료 매개변수, UI 애니메이션, 물리적 힘, 오디오 볼륨, 간단한 컷씬 등을 관리했습니다.

이것은 사용법을 알면 점점 더 자주 등장하는 망치 중 하나입니다.

많은 코드를 작성하고 싶지 않거나 빠르게 시작하고 싶다면 iTween, GoKit 또는 Hotween과 같은 플러그인을 사용하여 Unity에 많은 추가 보간 지원을 추가할 수 있습니다.