How do I update a Unity GameObject to move along a spline curve?

Good day,

I'm trying to implement a GameObject in Unity that traverses a Cubic CatMull-Rom Spline, given 8 bounded random values. I have implemented the ComputePointOnCatmullRomCurve function, which returns a point on a cubic Catmull-Rom curve (given the 'u' scalar from 0 to 1 and segment_number, which indicates which 4 points to use for interpolation).

I am having a problem implementing an update function that allows the GameObject to move smoothly. I currently call ComputePointOnCatmullRomCurve every update and increment the number of buckets each time. Then the position of the GameObjects is set to the result of the function.

However, this causes the GameObject to move very quickly. I believe the Update function is wrong, but I'm not sure how to move the GameObject relative to the points that the interpolation function outputs.

If someone can explain to me what I am doing wrong, or provide an example or link to an example, that would be very helpful!

Curve point calculation function:

Vector3 ComputePointOnCatmullRomCurve(float u, int segmentNumber)
{
    // TODO - compute and return a point as a Vector3       
    // Points on segment number 0 start at controlPoints[0] and end at controlPoints[1]
    // Points on segment number 1 start at controlPoints[1] and end at controlPoints[2]
    //       etc...

    Vector3 point = new Vector3();

    float c0 = ((-u + 2f) * u - 1f) * u * 0.5f;
    float c1 = (((3f * u - 5f) * u) * u + 2f) * 0.5f;
    float c2 = ((-3f * u + 4f) * u + 1f) * u * 0.5f;
    float c3 = ((u - 1f) * u * u) * 0.5f;

    Vector3 p0 = controlPoints[(segmentNumber - 1) % NumberOfPoints];
    Vector3 p1 = controlPoints[segmentNumber % NumberOfPoints];
    Vector3 p2 = controlPoints[(segmentNumber + 1) % NumberOfPoints];
    Vector3 p3 = controlPoints[(segmentNumber + 2) % NumberOfPoints];

    point.x = (p0.x * c0) + (p1.x * c1) + (p2.x * c2) + (p3.x * c3);
    point.y = (p0.y * c0) + (p1.y * c1) + (p2.y * c2) + (p3.y * c3);
    point.x = (p0.z * c0) + (p1.z * c1) + (p2.z * c2) + (p3.z * c3);

    return point;
}

      

Update function:

void Update () {
    // TODO - use time to determine values for u and segment_number in this function call
    // 0.5 Can be used as u
    time += DT;

    segCounter++;

    Vector3 temp = ComputePointOnCatmullRomCurve(time, segCounter);
    transform.position = temp;
}

      

Variables

const int NumberOfPoints = 8;
Vector3[] controlPoints;

const int MinX = -5;
const int MinY = -5;
const int MinZ = 0;

const int MaxX = 5;
const int MaxY = 5;
const int MaxZ = 5;

float time = 0;
const float DT = 0.01f;
public static int segCounter = 0;

      

Thank!

Matt

+3


source to share


1 answer


There are 2 bugs in the update function.

First error:

You increment the index of the current segment every frame ( segmentNumber

). My guess is that this should only be done when the object has finished moving it along the previous spline segment.

Hint:

For spline curves defined by multiple patches, I usually express the time ( u

) in a range [0,n]

, where n

is the number of segments that define the curve. This way you can get the index of the current patch ( segmentNumber

) simply by extracting the integral part from this parameter. Something like:



int segmentNumber =  Mathf.FloorToInt(u);
float segmentU = u - segmentNumber;

      

Second mistake

I don’t know what your DT variable is, but if you don’t scale it by delta time elsewhere, you should. Basically you can increase the time this way:

time += Time.deltaTime * speedAlongCurve;

      

Hope this helps.

+4


source







All Articles