UnityEngine Vector3.SmoothDamp(...)
부드러운 이동을 구현하기 위해 손쉽게 활용하는 함수입니다. 주로 Target 을 부드럽게 따라가는 카메라의 LookAt 혹은Position계산에 활용된다고 합니다. 저도 그렇게 썼었고요.
// Smooth towards the target
using UnityEngine;
using System.Collections;
public class ExampleClass : MonoBehaviour
{
public Transform target;
public float smoothTime = 0.3F;
private Vector3 velocity = Vector3.zero;
void Update()
{
// Define a target position above and behind the target transform
Vector3 targetPosition = target.TransformPoint(new Vector3(0, 5, -10));
// Smoothly move the camera towards that target position
transform.position = Vector3.SmoothDamp(transform.position, targetPosition, ref velocity, smoothTime);
}
}
위 스크립트는 현재 위치 transform.position 에서 targetPosition 까지 부드럽게 이동시킵니다. smoothTime 동안 목적지에 얼추 도착하도록 처리해주는데, 실제로는 더 오랜 시간이 걸리게 됩니다. API Document 에도 대략적인 시간이라고만 적혀있습니다.
smoothTime Approximately the time it will take to reach the target. A smaller value will reach the target faster.
velocity 는 ref 키워드로 참조를 전달하는데, Debug.Log 로 값을 찍어보면 지속적으로 갱신되는 속도값을 얻고, 다음 프레임에 다시 전달하고 있다는 걸 알 수 있습니다.
문득 이 SmoothDamp 함수가 어떻게 동작하는지 궁금해졌습니다. 검색을 좀 해봤는데, 활용법이나 예제코드만 많이 나와서 어려웠는데, 어찌저찌 찾아냈습니다.
// Gradually changes a value towards a desired goal over time.
public static float SmoothDamp(float current, float target, ref float currentVelocity, float smoothTime, [uei.DefaultValue("Mathf.Infinity")] float maxSpeed, [uei.DefaultValue("Time.deltaTime")] float deltaTime)
{
// Based on Game Programming Gems 4 Chapter 1.10
smoothTime = Mathf.Max(0.0001F, smoothTime);
float omega = 2F / smoothTime;
float x = omega * deltaTime;
float exp = 1F / (1F + x + 0.48F * x * x + 0.235F * x * x * x);
float change = current - target;
float originalTo = target;
// Clamp maximum speed
float maxChange = maxSpeed * smoothTime;
change = Mathf.Clamp(change, -maxChange, maxChange);
target = current - change;
float temp = (currentVelocity + omega * change) * deltaTime;
currentVelocity = (currentVelocity - omega * temp) * exp;
float output = target + (change + temp) * exp;
// Prevent overshooting
if (originalTo - current > 0.0F == output > originalTo)
{
output = originalTo;
currentVelocity = (output - originalTo) / deltaTime;
}
return output;
}
위 코드는 float 값을 입력받고 리턴하고 있는데, Vector3 버전으로 바꾸면 동일한 결과값을 반환합니다. currentVelocity 값을 ref 참조로 받아서 계속 갱신됩니다.
잠깐 검색을 좀 더 해봤는데, 테일러 급수를 3차 항까지 전개한 지수 근사치라는 내용이 있네요. 일단 메모 해두고 자세한 내용은 추후에 좀 더 봐야겠습니다.
관련 자료 : https://www.opensourceagenda.com/projects/unity-spring
테일러 급수(Taylor series) https://suhak.tistory.com/212
위 함수는 Game Programming Gems 4 Chapter 1.10 에서 다루는 내용이라고 합니다.
본문을 보니 이런 구절이 있습니다. 지수함수 비용이 비싸기 때문에, 위처럼 계산해서 근사치를 구한다고 합니다.
The one remaining problem is that exponential function call, which is computationally expensive. Fortunately, it can be approximated precisely for the range that we’ll use. This results in our completed function.
https://docs.unity3d.com/ScriptReference/Vector3.SmoothDamp.html
'유니티 엔진 (Unity Engine)' 카테고리의 다른 글
[Unity] 에셋스토어 에셋 구입 시 Tax Number? (0) | 2022.11.03 |
---|---|
[Unity] Component의 컨텍스트 메뉴(ContextMenu) 만들기 (0) | 2022.11.02 |
[Unity] PlayerPref 레지스트리 저장 경로 (0) | 2022.07.26 |
셰이더 입문서 추천 "아티스트를 위한 유니티 URP 셰이더 입문" (0) | 2022.03.29 |
강력 추천 유니티 입문서 "유니티 교과서" 개정5판 (0) | 2022.03.14 |
[Unity] Play Mode 시작 시 씬 고정하기 (0) | 2022.01.30 |
Unity TextMeshPro(TMP) 한글 폰트 출력하기 (0) | 2022.01.28 |