유니티에서 곡선 이동과 가속도 제어: 베지어 곡선과 스플라인의 고급 활용법

게임 개발에서 캐릭터나 오브젝트의 부드러운 이동 경로를 구현하는 일은 유저 경험에 큰 영향을 미칩니다. 특히 비행, 탈 것 게임, 캐릭터 회피 동작 등에서 직선이 아닌 곡선 경로를 따라 이동해야 하는 경우가 많습니다. 이를 위해 많이 사용하는 수학적 개념이 베지어 곡선과 **스플라인(Spline)**입니다. 이 글에서는 유니티를 사용해 곡선 경로를 생성하고 이를 따라 이동하는 방식, 가속도 조절을 포함한 고급 활용법까지 다뤄 보겠습니다.


1. 기본 개념: 베지어 곡선과 스플라인이란?

베지어 곡선은 주로 2D 그래픽 디자인과 3D 애니메이션에서 사용되는 곡선으로, 두 개 이상의 제어점을 기반으로 부드러운 곡선을 만들어 냅니다. 유니티에서는 베지어 곡선을 간단한 수학식을 통해 구현할 수 있으며, 특히 이차 및 삼차 베지어 곡선이 많이 쓰입니다.

**스플라인(Spline)**은 주로 다중 곡선을 연결하여 좀 더 복잡한 경로를 생성하는데 쓰입니다. 스플라인은 여러 베지어 곡선을 이어 붙여 만든 경로라 할 수 있으며, 게임에서 캐릭터나 오브젝트가 특정 경로를 따라 이동하도록 설계할 때 유용합니다.


2. 유니티에서 이차 베지어 곡선 구현하기

간단한 예시로 이차 베지어 곡선을 구현해 보겠습니다. 이차 베지어 곡선은 시작점, 끝점, 그리고 중간 제어점을 사용해 곡선을 생성합니다.

예시 코드: 이차 베지어 곡선

using UnityEngine;

public class QuadraticBezier : MonoBehaviour
{
    public Transform startPoint;
    public Transform controlPoint;
    public Transform endPoint;
    public float duration = 2.0f; // 이동 시간

    private float elapsedTime = 0f;

    void Update()
    {
        elapsedTime += Time.deltaTime;
        float t = elapsedTime / duration; // 0에서 1까지 비율 계산
        if (t > 1f) t = 1f;

        transform.position = CalculateQuadraticBezierPoint(t, startPoint.position, controlPoint.position, endPoint.position);
    }

    Vector3 CalculateQuadraticBezierPoint(float t, Vector3 p0, Vector3 p1, Vector3 p2)
    {
        // (1-t)^2 * P0 + 2 * (1-t) * t * P1 + t^2 * P2
        float u = 1 - t;
        return u * u * p0 + 2 * u * t * p1 + t * t * p2;
    }
}

코드 설명

  • CalculateQuadraticBezierPoint 메서드는 이차 베지어 곡선 수식을 구현한 함수로, t 값을 사용해 시작점에서 끝점까지 부드럽게 이동할 수 있습니다.
  • Update 메서드에서 t 값을 0에서 1까지 증가시키며, transform.position을 곡선에 따라 이동시키도록 합니다.

이 코드는 간단한 곡선 이동을 구현할 때 유용하며, 이차 곡선이라서 경로가 단순할 경우에 적합합니다. 단, 경로가 복잡한 경우에는 스플라인을 활용해야 더 효과적입니다.


3. 고급 구현: 스플라인 경로 따라가기

스플라인을 사용하면 다수의 경로를 부드럽게 이어 붙일 수 있습니다. 다음 예시에서는 여러 개의 베지어 곡선을 연결해 스플라인을 만들고, 이를 따라 이동하는 캐릭터를 구현해 보겠습니다.

예시 코드: 스플라인 경로

using UnityEngine;
using System.Collections.Generic;

public class SplinePath : MonoBehaviour
{
    public List<Transform> controlPoints; // 경로의 제어점들
    public float duration = 5.0f; // 전체 경로 이동 시간

    private int segmentCount; // 스플라인 세그먼트 개수
    private float elapsedTime = 0f;

    void Start()
    {
        segmentCount = controlPoints.Count - 1;
    }

    void Update()
    {
        elapsedTime += Time.deltaTime;
        float t = elapsedTime / duration;

        if (t > 1f) t = 1f;

        transform.position = CalculateSplinePoint(t);
    }

    Vector3 CalculateSplinePoint(float t)
    {
        int segmentIndex = Mathf.FloorToInt(t * segmentCount); // 현재 위치한 세그먼트 인덱스
        float localT = (t * segmentCount) - segmentIndex; // 세그먼트 내에서의 상대 위치

        Vector3 p0 = controlPoints[segmentIndex].position;
        Vector3 p1 = controlPoints[segmentIndex + 1].position;
        Vector3 p2 = (segmentIndex + 2 < controlPoints.Count) ? controlPoints[segmentIndex + 2].position : p1;

        // 두 개의 베지어 곡선 연결하여 스플라인 생성
        Vector3 A = Vector3.Lerp(p0, p1, localT);
        Vector3 B = Vector3.Lerp(p1, p2, localT);

        return Vector3.Lerp(A, B, localT);
    }
}

코드 설명

  • CalculateSplinePoint 메서드는 특정 t 값을 이용해 스플라인 경로 상의 위치를 계산합니다. 각 제어점 사이의 세그먼트를 기반으로, 로컬 좌표 localT를 통해 경로를 부드럽게 연결합니다.
  • Update 메서드는 t를 0에서 1까지 증가시키며, 캐릭터가 전체 스플라인 경로를 따라 이동하도록 합니다.

4. 응용: 가속도 적용과 자연스러운 곡선 이동

여기서 한 단계 더 나아가, 가속도를 적용하여 캐릭터가 일정 속도로만 이동하지 않고 점차 가속하거나 감속할 수 있도록 해보겠습니다. 이를 위해선 t 값을 비선형으로 조정하는 방법이 있습니다. t의 증가 속도를 점진적으로 변화시키면 가속과 감속을 표현할 수 있습니다.

예시 코드: 가속도 적용된 스플라인 이동

using UnityEngine;

public class AcceleratedSplinePath : SplinePath
{
    public AnimationCurve speedCurve; // 속도 조절을 위한 애니메이션 곡선

    void Update()
    {
        elapsedTime += Time.deltaTime;
        float normalizedTime = elapsedTime / duration;
        
        // speedCurve를 통해 비선형 t값 계산
        float t = speedCurve.Evaluate(normalizedTime); 
        
        if (t > 1f) t = 1f;

        transform.position = CalculateSplinePoint(t);
    }
}

코드 설명

  • speedCurveAnimationCurve를 사용하여 속도를 가감속할 수 있도록 합니다. 예를 들어, S-커브를 사용하면 천천히 출발하여 빠르게 가속한 후 도착 지점에서 서서히 감속하는 경로를 구현할 수 있습니다.
  • Update 메서드에서 speedCurve.Evaluate()를 사용하여 t 값을 조절하여 가속도를 조절합니다.

마무리

이와 같은 곡선 경로와 가속도 조절을 활용하면 캐릭터의 움직임이 훨씬 자연스러워지며, 게임 내 몰입감을 높일 수 있습니다. 이 방식은 유니티에서 곡선 이동을 손쉽게 구현할 수 있을 뿐만 아니라, 다양한 응용을 통해 더욱 정교한 경로 이동을 가능하게 합니다.

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다