~2 мин чтения

Splines и процедурные пути

Встроенный Splines package в Unity 6, кривые Безье/B-Spline, Cinemachine SplineDolly и spawning along path.

В Unity 6 есть встроенный пакет Splines (com.unity.splines). Раньше для рельсовых камер, дорожек, AI-патрулей приходилось писать математику Безье вручную или ставить asset-store-плагины. Теперь — нет.

Что даёт пакет

  • SplineContainer — нод-контейнер для одной или нескольких кривых (Catmull-Rom, Bezier, B-Spline).
  • Spline Tool в Scene View — рисуете точки мышью, перетаскиваете касательные.
  • SplineExtrude — экструдирует mesh вдоль сплайна (готовая дорога/труба).
  • SplineInstantiate — расставляет prefab’ы вдоль кривой (заборы, столбы, деревья).
  • SplineAnimate — анимирует Transform вдоль сплайна (движущиеся платформы, AI на рельсах).
  • Cinemachine SplineDolly — камера на рельсах.
Веб

SVG-path с командами M, L, C, Q. Или GSAP MotionPath plugin для анимации по кривой.

Unity

Spline хранит контрольные точки и tangents, движок интерполирует. EvaluatePosition(t) / EvaluateTangent(t) дают точку и направление по параметру t ∈ [0, 1].

Базовая работа со сплайном из кода

using UnityEngine;
using UnityEngine.Splines;
using Unity.Mathematics;

public class SplineWalker : MonoBehaviour
{
    [SerializeField] private SplineContainer container;
    [SerializeField] private float speed = 2f;

    private float _t;

    private void Update() {
        _t += Time.deltaTime * speed * (1f / container.CalculateLength());
        if (_t > 1f) _t -= 1f;

        // EvaluatePosition / EvaluateTangent работают с Unity.Mathematics типами
        float3 pos = container.EvaluatePosition(_t);
        float3 tangent = container.EvaluateTangent(_t);

        transform.position = pos;
        if (math.lengthsq(tangent) > 0.0001f) {
            transform.rotation = Quaternion.LookRotation(tangent);
        }
    }
}

Сам сплайн создаётся на GameObject через Add Component → Spline → Spline Container. Затем в Scene View включаете Spline Tool (T) и расставляете точки.

CalculateLength() для постоянной скорости

Параметр t ∈ [0, 1] — это нормализованный параметр сплайна, не дистанция. Если просто делать _t += Time.deltaTime, скорость будет неравномерной (быстрее на коротких сегментах). Делите на CalculateLength(), чтобы получить постоянную скорость в м/с.

SplineAnimate — анимация без кода

Если хочется “по-простому”: добавьте на движущийся объект компонент SplineAnimate и привяжите сплайн.

Параметры:

  • Method — Distance / Time / Linear / Ease in/out.
  • Duration / Max Speed — продолжительность или максимальная скорость.
  • Alignment — None / SplineElement / SplineObject / World — как ориентировать объект.
  • Loop — Loop / Ping Pong / Once.

Идеально для движущихся платформ, лифтов, AI на рельсах.

SplineInstantiate — расставить prefab’ы

Сцена с забором из 30 столбов? Раньше — расставляли вручную в редакторе или писали скрипт. Теперь:

  1. Сделайте sprite один столб как prefab.
  2. На сплайне добавьте SplineInstantiate.
  3. В Items укажите prefab + density.
  4. Жмёте Update — Unity размножает столбы вдоль кривой.

Поля Spacing (расстояние между инстансами), Position Offset Range, Rotation Offset Range дают рандомизацию для природного выглядящего расположения.

Cinemachine SplineDolly — камера на рельсах

В Cinemachine 3 + Splines есть готовая интеграция:

  1. На сцене — SplineContainer (нарисуйте трассу камеры).
  2. На CinemachineCamera добавьте CinemachineSplineDolly.
  3. В Spline укажите ваш SplineContainer.
  4. Camera Position — параметр t (можно анимировать через Timeline или Animator).
  5. Auto Dolly — автоматически следит за Tracking Target и держит камеру на ближайшей точке сплайна.
using Unity.Cinemachine;

public class CutsceneCamera : MonoBehaviour
{
    [SerializeField] private CinemachineSplineDolly dolly;
    [SerializeField] private float duration = 5f;

    private float _t;

    public void Play() { _t = 0f; enabled = true; }

    private void Update() {
        _t += Time.deltaTime / duration;
        dolly.CameraPosition = Mathf.Clamp01(_t);
        if (_t >= 1f) enabled = false;
    }
}

Идеально для кат-сцен intro/outro, fly-through, прохода камеры по уровню.

SplineExtrude — процедурные дороги и трубы

SplineExtrude принимает 2D-сечение (например, окружность) и протягивает его вдоль сплайна. На выходе — готовый mesh.

Применение:

  • Дороги — толстое прямоугольное сечение.
  • Трубопроводы — окружность.
  • Стены пещеры — нерегулярный mesh-сегмент.
// Параметры в Inspector:
// - Spline: SplineContainer
// - Radius: радиус extruded mesh
// - Sides: количество сторон сечения (round = 16+)
// - Range: какую часть сплайна экструдировать
// - Segments per Unit: плотность mesh

Раскрученные паттерны

  1. Магнит к сплайнуSplineUtility.GetNearestPoint(spline, queryPoint, out float t) находит ближайшую точку. Используется в “snap to road” логике.
  2. Patrol AI вдоль сплайна — враг патрулирует по SplineAnimate в режиме Ping Pong. EvaluateTangent даёт ему направление, чтобы смотреть вперёд.
  3. Скроллинг параллакс — sprite двигается вдоль сплайна, дающего нелинейный путь.
  4. Курсор по карте — UI-элемент движется по нарисованной маршрутной кривой.

Когда НЕ использовать Splines

  • Если у вас только прямые линии — массив Vector3 дешевле и проще.
  • Динамически меняющиеся пути в каждом кадре — SplineContainer не оптимизирован под бесконечную модификацию (можно, но медленнее, чем custom math).
  • Сетки из сотен сплайнов в кадре — для процедурных трасс лучше Job System (см. следующую главу).