Unity Lerp

용준·2024년 3월 27일
0

Unity

목록 보기
16/19

참고자료
https://docs.unity3d.com/kr/530/ScriptReference/Mathf.Lerp.html
https://starlightbox.tistory.com/91
https://gamedevbeginner.com/the-right-way-to-lerp-in-unity-with-examples/
Easing 함수 ↓
https://easings.net/
https://www.febucci.com/2018/08/easing-functions/


Lerp란?

선형 보간(Linear Interpolation)은 선형 눈금의 한 지점에서 다른 두 값 사이의 값을 반환하는 Unity의 수학 함수입니다. 가장 일반적으로 일정 기간 동안 값을 이동하거나 변경하는 데 사용됩니다.

public static float Lerp (float a, float b, float t);

Lerp 계산은 최소값(a)과 최대값(b)을 사용하여 지정된 알려진 범위의 값을 반환합니다.
반환되는 값은 세 번째 값, 즉 a와 b 사이의 눈금에 있는 점을 반환하는 보간점(t)으로 정의됩니다.
전달된 보간점은 0과 1 사이의 부동 소수점 값이며 기본적으로 a와 b 사이의 백분율로 작동합니다.

예를들어 a가 0, b가 100일 때 t=0은 최소값(0)을 반환하고 t=0.5는 중간값(50)을 반환합니다.

다음은 몇가지 사용 예시입니다.

float a = 0;
float b = 50;
float t = 0.5f;

lerpValue = Mathf.Lerp(a, b, t);

// Returns 25
float a = 10;
float b = 50;
float t = 1;

lerpValue = Mathf.Lerp(a, b, t);

// Returns 50

이론

Lerp의 일반적인 용도는 고정된 기간 동안 효과를 생성하는 것입니다.

예를 들어 버튼에 애니메이션을 적용하려면 화면을 검은색으로 페이드하거나 고정된 시간 내에 개체를 새 위치로 이동합니다. 이는 해당 기간 동안 보간점 값을 0에서 1로 증가시켜 수행됩니다.

수행 방법은 다음과 같습니다.

  • 타이머를 생성하고 Lerp의 매 프레임마다 타이머를 증가시킵니다.
  • 경과된 시간을 Lerp의 총 지속 시간으로 나눕니다.
  • 해당 값을 보간점(t)으로 전달합니다.

아래 스크립트는 3초 안에 0에서 10까지 값을 증가시킵니다.

float timeElapsed;
float lerpDuration = 3;

float startValue=0;
float endValue=10;
float valueToLerp;

void Update()
{
  if (timeElapsed < lerpDuration)
  {
    valueToLerp = Mathf.Lerp(startValue, endValue, timeElapsed / lerpDuration);
    timeElapsed += Time.deltaTime;
  }
}

그러나 이 방법을 시도하면 값이 10에 도달하지 않고 종종 매우 가깝지만 정확하지는 않은 값으로 끝나는 것을 알 수 있습니다. 예를 들어 9.998과 같습니다.

이는 Lerp가 완료되었는지 측정하는 데 사용되는 값이 Lerped되는 실제 값이 아니라 시간이기 때문입니다.

이 문제를 해결하려면 Lerp가 완료된 후 Lerped되는 값을 최종 목표 값으로 스냅해야 합니다.

스냅(보정)을 했을 때:

void Lerp()
  {
    if (timeElapsed < lerpDuration)
    {
      valueToLerp = Mathf.Lerp(startValue, endValue, timeElapsed / lerpDuration);
      timeElapsed += Time.deltaTime;
    }
    else 
    {
      valueToLerp = endValue;
    }
  }

마지막으로 Lerp 함수는 여러 프레임에 걸쳐 작업을 수행하는 데 자주 사용되므로,
Coroutine에 배치하는 것이 도움이 될 수 있습니다.

float lerpDuration = 3; 
float startValue = 0; 
float endValue = 10; 
float valueToLerp;

void Start()
    {
        StartCoroutine(Lerp());
    }

IEnumerator Lerp()
    {
        float timeElapsed = 0;

        while (timeElapsed < lerpDuration)
        {
            valueToLerp = Mathf.Lerp(startValue, endValue, timeElapsed / lerpDuration);
            timeElapsed += Time.deltaTime;

            yield return null;
        }

        valueToLerp = endValue;
    }

응용

Lerp를 사용해 로딩바를 만들어보겠습니다.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class Lerp : MonoBehaviour
{
    public Image barImage;
    public Text text;
    public Text textPer;

    private void Start()
    {
        StartCoroutine(MyLerp());
    }

    private IEnumerator MyLerp()
    {
        float delta = 0; // 경과 시간 추적을 위한 변수
        float duration = 5f; // 보간에 걸리는 총 시간
        int startValue = 0; // 시작 값
        int endValue = 3270; // 목표 값

		// 보간이 완료될 때까지 반복
        while (delta <= duration)
        {
        	// 현재 시간에 대한 보간 비율 계산
            float t = delta / duration;
            
            // 시간 흐름에 따른 매개 변수 변화율 (보간)
            t = t < 0.5 ? (1 - Mathf.Sqrt(1 - Mathf.Pow(2 * t, 2))) / 2 : (Mathf.Sqrt(1 - Mathf.Pow(-2 * t + 2, 2)) + 1) / 2;

			// 현재 보간된 값 계산
            float currentValue = Mathf.Lerp(startValue, endValue, t);
            
            // UI 업데이트
            barImage.fillAmount = t; // 이미지의 fill을 보간 값으로 업데이트
            text.text = string.Format("{0} MB", currentValue); // 텍스트 업데이트
            textPer.text = string.Format("{0}%", t * 100f); // 텍스트 업데이트
			
            // 경과 시간 업데이트
            delta += Time.deltaTime;
            
            // 다음 프레임까지 대기
            yield return null;
        }

        // 보간이 완료된 후 마무리 작업
        barImage.fillAmount = 1; // 이미지의 fill을 최대로 변경
        text.text = string.Format("Complete"); // 텍스트 업데이트
        textPer.text = string.Format("{0}%", 100f); // 텍스트 업데이트
    }
}

while 루프를 사용하여 시간에 따라 값을 보간하고, 보간된 값을 UI에 업데이트합니다.

보간은 지정한 시간동안 startValue에서 endValue까지 진행되며, 보간값(t)의 선형적인 움직임을 원하지 않는다면 Easing 함수를 사용하여 부드러운 보간 효과를 생성할 수 있습니다.

결과:

0개의 댓글