본문 바로가기
개발/Unity

유니티 - SmoothDamp를 코루틴에서 사용하기 (SmoothDamp with Coroutine)

by 피로물든딸기 2022. 6. 28.
반응형

Unity 전체 링크

 

오브젝트를 생성할 때, 위에서 아래로 빠르게 내려오는 효과를 만들어보자.

이때 Effect로 목표 지점에 가까워지면 감속하게 만들어보자.

 

현재 오브젝트를 기준으로 Y가 10 보다 큰 값에서 내려온다고 가정하자.

 

SmoothDamp를 이용하여 간단한 예제를 만들어 볼 수 있다.

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

 

Vector3-SmoothDamp - Unity 스크립팅 API

Gradually changes a vector towards a desired goal over time.

docs.unity3d.com

 

SmoothDampUpdate.cs는 업데이트 문 SmoothDamp를 사용하였다.

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

public class SmoothDampUpdate : MonoBehaviour
{
    Vector3 vel = Vector3.zero;
    Vector3 startPos, endPos;
    public float smoothTime = 1.0f;

    void Start()
    {
        startPos = this.transform.position + new Vector3(0, 10, 0);
        endPos = this.transform.position;

        this.transform.position = startPos;
    }

    void Update()
    {
        this.transform.position 
            = Vector3.SmoothDamp(this.transform.position, endPos, ref vel, smoothTime);
    }
}

 

큐브를 만들어서 스크립트를 추가한 후 게임을 실행해보자.

아래와 같이 처음에는 빠른 속도로 내려오다가 감속하는 것을 알 수 있다.

그런데 큰 문제가 있다. 큐브의 Position Y 값을 보자.

SmoothDamp의 부동 소수점 연산에 의해 정확한 값을 찾지 못한다.

따라서, 움직임을 끝내지 않고 매우 조금씩 계속 움직이고 있다.

 

또한 Update 문의 예제는 특정 상황에서 SmoothDamp를 사용하기에는 적절하지 않다. 

따라서 코루틴을 이용해서 이 문제를 해결해보자.


Vector3.Lerp를 이용한다면 코루틴은 아래와 같이 만들어야 한다.

1초 동안 현재(current) 위치에서 목표(target) 위치까지 움직이도록 시간을 누적하여 처리한다.

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

public class LerpCoroutine : MonoBehaviour
{
    public float lerpTime = 1.0f;
  
    IEnumerator lerpCoroutine(Vector3 current, Vector3 target, float time)
    {
        float elapsedTime = 0.0f;

        this.transform.position = current;
        while(elapsedTime < time)
        {
            elapsedTime += (Time.deltaTime);

            this.transform.position 
                = Vector3.Lerp(current, target, elapsedTime / time);

            yield return null;
        }

        transform.position = target;

        yield return null;
    }

    void OnEnable()
    {
        Transform original = this.transform;
        StartCoroutine(
            lerpCoroutine(original.position + new Vector3(0, 10, 0), original.position, lerpTime));
    }
}

 

선형 보간에 의해 1초 동안 일정한 속도로 내려가는 것을 알 수 있다.

OnEnable에 작성하였으므로 오브젝트를 껐다 키면 다시 재생할 수 있다.

(또한 SmoothDamp와 달리 Y = 0으로 정확히 이동한다.)

 

하지만 SmoothTime은 누적 시간이 아니라 위치로 판단해야 한다.

또한 위에서 보인 y 값이 아주 조금씩 움직이는 문제를 해결하기 위해

offset으로 일정 거리 내에 들어오면 while문을 종료하도록 방어 코드를 넣는다.

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

public class SmoothDampCoroutine : MonoBehaviour
{
    public float smoothTime = 1.0f;

    IEnumerator SmoothCoroutine(Vector3 current, Vector3 target, float time)
    {
        Vector3 velocity = Vector3.zero;
        
        this.transform.position = current;
        float offset = 0.01f;
        while (target.y + offset <= this.transform.position.y)
        {
            this.transform.position 
                = Vector3.SmoothDamp(this.transform.position, target, ref velocity, time);

            yield return null;
        }

        transform.position = target;

        yield return null;
    }

    void OnEnable()
    {
        Transform original = this.transform;
        StartCoroutine(
            SmoothCoroutine(original.position + new Vector3(0, 10, 0), original.position, smoothTime));
    }

}

 

일정한 속도의 Lerp에 비해 목표 지점에 가까워질수록 점점 느려지고 있다.

그리고 offset 보정에 의해 Y = 0으로 정확히 변경되었다.

 

마지막으로 Lerp vs SmoothDamp를 각각  time = 0.5s vs 1.0s vs 2.0s를 비교하였다.

시간이 길수록 SmoothDamp가 조금 답답하게 느껴지므로 참고하도록 하자.

 

오브젝트가 나타나는 효과로 코루틴을 이용해 위 → 아래로 움직였다.

오브젝트 생성 이펙트로 Scale이 0에서 1로 커지도록 변경하는 것도 코루틴으로 가능하니, 직접 해보자.

 

Unity Plus:

 

Easy 2D, 3D, VR, & AR software for cross-platform development of games and mobile apps. - Unity Store

Have a 2D, 3D, VR, or AR project that needs cross-platform functionality? We can help. Take a look at the easy-to-use Unity Plus real-time dev platform!

store.unity.com

 

Unity Pro:

 

Unity Pro

The complete solutions for professionals to create and operate.

unity.com

 

Unity 프리미엄 학습:

 

Unity Learn

Advance your Unity skills with live sessions and over 750 hours of on-demand learning content designed for creators at every skill level.

unity.com

반응형

댓글