0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Unity - Simplifying Movement with the "Splines" System

Posted at

Warning
The information provided here is subject to change. Please refer to official information when updates occur.
This article targets version 2.7 (the functionality may not differ much).

image.png1


Talking About Splines

The Splines functionality is part of Unity’s official package. It was released in January 2022, and as of March 2025 (when this article was written), version 2.8 has been released.
Apparently, there were many requests for this feature to be included as a standard function.

Users had been requesting this functionality as part of the standard features for a long time. Now, it’s finally available as an official package.2

Let’s Use Splines

First, install Splines. Open the Package Manager and search for Splines.
You’ll see a screen like the one below—click the Install button circled in red. (Since I’ve already loaded Splines, my display may look different.)
Screenshot 2025-03-23 173833.png

After importing, right-click on the hierarchy or select GameObject and then Spline > New Spline. Write the spline in the scene and press the Enter key to finish.
For additional methods, refer to this link.

Moving an Object Along a Spline

To move an object along a spline:

  1. Click the Add Component button in the Inspector tab of the object you want to move, and search for Spline Animate.
  2. Attach the spline created earlier to the Spline section.

Run it, and the object should move along the spline.3

Creating Your Own Script

In the previous section, we used pre-programmed scripts to move objects. But how about creating your own script to move objects along a spline? Let’s get started!

Moving a Spline with a Script4

Here’s a basic script for moving objects along a spline:

SplineSystem.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Splines;

public class SplineSystem : MonoBehaviour
{
    [SerializeField] private SplineContainer splineContainer;
    [SerializeField] private Transform _followTarget; // Add the object (specifically its position data: transform) to follow the spline.
    [SerializeField] private float SplinesPercentage;
    [SerializeField] private Vector3 AddUpPosition; // Additional functionality.

    void Update()
    {
        if (splineContainer == null || _followTarget == null)
            return;

        // Update position.
        Vector3 position = splineContainer.EvaluatePosition(SplinesPercentage);

        position += AddUpPosition; // Add the specified vector (subtract if the value is negative).

        _followTarget.position = position;

        // Update rotation.
        Vector3 tangent = ((Vector3)splineContainer.EvaluateTangent(SplinesPercentage)).normalized;
        Vector3 up = ((Vector3)splineContainer.EvaluateUpVector(SplinesPercentage));
        _followTarget.rotation = Quaternion.LookRotation(tangent, up);
    }
}

Warning
When handling splines via scripts, make sure to include:

using UnityEngine.Splines;

If you’re wondering what [SerializeField] is, refer

Change the SplinePosition value to move objects, and the rotation along the spline should also be applied.
For the detailed mechanism, see the linq;

Enhancing the Previous Script

Here, we’ll introduce:
1️⃣ A script where you input a distance from the starting point on the spline to move the object there.
2️⃣ A script where you input a speed (km/h) to move the object along the spline at that speed.

Enhancing the Script: Part 1️⃣

The previous script calculates positions based on percentages.
So, if you know the total length of the spline, can’t you figure out the distance from the starting point?

The function to calculate the spline’s length is:

CalculateLength();

Here’s a sample script:

SplineSystem.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Splines;

public class SplineSystem : MonoBehaviour
{
    [SerializeField] private SplineContainer splineContainer;
    [SerializeField] private Transform _followTarget;
    private float SplinesPercentage; // Change: fully private.
    [SerializeField] private float SplineLength_Position; // Add: input distance from the starting point on the spline.
    /*[SerializeField]*/ private float SplineLength; // Add: variable for the length of the specified spline.
    [SerializeField] private Vector3 AddUpPosition;
    [SerializeField] private float AddLength; // Extra functionality.
    public TrainSystem trainSystem;

    void Start()
    {
        SplineLength = splineContainer.CalculateLength(); // Add: get the length of the specified spline.
    }

    void Update()
    {
        if (splineContainer == null || _followTarget == null)
            return;
        
        SplinesPercentage = (SplineLength_Position + AddLength) / SplineLength; // Add: convert distance to percentage and assign to the position variable.

        // Update position.
        Vector3 position = splineContainer.EvaluatePosition(SplinesPercentage);

        position += AddUpPosition; // Add the specified vector (subtract if the value is negative).

        _followTarget.position = position;

        // Update rotation.
        Vector3 tangent = ((Vector3)splineContainer.EvaluateTangent(SplinesPercentage)).normalized;
        Vector3 up = ((Vector3)splineContainer.EvaluateUpVector(SplinesPercentage));
        _followTarget.rotation = Quaternion.LookRotation(tangent, up);
    }
}

Enhancing the Script: Part 2️⃣

Warning
The script assumes a 1m = 1 Unity Unit scale.

Here’s a script to move objects at a specified speed (km/h):

SplineSystem.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Splines;

public class SplineSystem : MonoBehaviour
{
    [SerializeField] private SplineContainer splineContainer;
    [SerializeField] private Transform _followTarget;
    private float SplinesPercentage;
    [SerializeField] private float SplineLength_Position;
    /*[SerializeField]*/ private float SplineLength;
    [SerializeField] private Vector3 AddUpPosition;
    [SerializeField] private float AddLength;
    [SerializeField] private float ObjectSpeed; // Add: insert speed in km/h.

    void Start()
    {
        SplineLength = splineContainer.CalculateLength();
    }

    void Update()
    {
        if (splineContainer == null || _followTarget == null)
            return;

        SplineLength_Position += (ObjectSpeed * (1000f / 3600f)) * Time.deltaTime; // Add: convert km/h to m/s and calculate.

        SplinesPercentage = (SplineLength_Position + AddLength) / SplineLength;

        // Update position.
        Vector3 position = splineContainer.EvaluatePosition(SplinesPercentage);

        position += AddUpPosition; // Add the specified vector (subtract if the value is negative).

        _followTarget.position = position;

        // Update rotation.
        Vector3 tangent = ((Vector3)splineContainer.EvaluateTangent(SplinesPercentage)).normalized;
        Vector3 up = ((Vector3)splineContainer.EvaluateUpVector(SplinesPercentage));
        _followTarget.rotation = Quaternion.LookRotation(tangent, up);
    }
}

Final Remarks

Thank you for reading this article! Personally, I just finished my school graduation ceremony and wrote this while relaxing.
I’m preparing for exams soon—ugh—but it’s part of life, isn’t it? To fellow examinees out there—be it primary, junior, or senior high school—let’s work hard together!

The end!
translated with Bing AI

  1. Image and reference: Unity 2022.2 の Splines を使って、フロー状態でより美しいパスを描き出そう

  2. Quote: Unity 2022 新機能!スプラインを使ってみよう! - YouTube

  3. Detailed methods: 【Unity2022】スプラインツールの導入方法と使い方|ねこじゃらシティ

  4. Reference:【Unity2022】スプラインをスクリプトから扱う方法|ねこじゃらシティ

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?