Good afternoon,
I am attempting to implement a GameObject in Unity that moves along a Cubic CatMull-Rom Spline given 8 constrained random values. I have implemented a function, ComputePointOnCatmullRomCurve, that returns a point on a cubic Catmull-Rom curve (given a scalar 'u' from 0 to 1 and segment_number which indicates which 4 pts to use for interpolation).
I am having trouble implementing the update function to allow for the GameObject to move smoothly. I am currently calling ComputePointOnCatmullRomCurve each update and am incrementing the segment_number each time. The GameObjects position is then set to the result of the function.
However this leads to a GameObject that moves extremely quick. I believe my Update function is incorrect, but I am unsure about how to move the GameObject with respect to the points that are being output by the interpolation function.
If someone would be able to explain to me what I am doing incorrectly, or provide an example or link to an example, it would be very helpful!
Function to compute point on curve:
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;
Thanks!
Matt
Your are doing 2 errors in the Update function.
First error:
You are incrementing the index of the current segment at each frame (segmentNumber
). I guess this should be done only when the object complete it's travel along the previous spline segment.
Hint:
For spline curves defined by multiple patches I usually express the time (u
) in the range [0,n]
where n
is the number of segment defining the curve. This way you can retrieve the index of the current patch (segmentNumber
) simply extracting the integral part from the parameter. Something like:
int segmentNumber = Mathf.FloorToInt(u);
float segmentU = u - segmentNumber;
Second Error
I don't know what your DT variable is, but unless you are scaling it by the frame delta time somewhere else, you have to do it. Basically you can increase time this way:
time += Time.deltaTime * speedAlongCurve;
I hope it helps.