유니티 엔진 (Unity Engine)

SmoothDamp 는 어떻게 구현돼있을까?

원생계 2022. 5. 24. 00:19

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

 

Unity Spring Open Source Project

Submit Resource Articles, Courses, Videos

www.opensourceagenda.com

테일러 급수(Taylor series) https://suhak.tistory.com/212

 

테일러 급수(Taylor series)

정의 테일러 급수는 어떤 점에서 무한 번 미분가능한 함수를 그 점에서 미분계수 값으로 계산할 수 있는 무한급수로 표현된 함수로 나타내는 것이다. 결과를 적으면 아래와 같다. $a=0$일 때는 맥

suhak.tistory.com

위 함수는 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.
내부가 궁금한 함수였는데, 검색을 하다보니 이런저런 자료들을 찾게돼서 마저 스크랩 해둡니다. Interpolation 함수들을 그때그때 이슈가 생기면 검색해서 문제 해결만 해버리고 바로 잊어버리게 돼서 깊게 들어가본 적이 없는 것 같습니다. 조금씩 생각날 때마다 이렇게 들여다 봐야겠습니다.

https://docs.unity3d.com/ScriptReference/Vector3.SmoothDamp.html
 

Unity - Scripting API: Vector3.SmoothDamp

Success! Thank you for helping us improve the quality of Unity Documentation. Although we cannot accept all submissions, we do read each suggested change from our users and will make updates where applicable. Close

docs.unity3d.com

https://github.com/Unity-Technologies/UnityCsReference/blob/2019.3/Runtime/Export/Math/Mathf.cs#L302-L331

https://issuetracker.unity3d.com/issues/smoothdamp-behaves-differently-between-positive-and-negative-velocity

 

www.iki.fi/sol - Tutorials - Interpolation Tricks

Interpolation Tricks or How I Learned to Stop Worrying and Love the 0..1 Range Contents Why 0..1 Range Getting to the 0..1 Range Linear Interpolation Smoothstep Higher Powers Sin Weighted Average Splines Conclusion 1. Why 0..1 Range While making demos I've

sol.gfxile.net

 

 

728x90
반응형