Moving an Object along a Bezier Curve

I have the following code which is attempting to move an object along a path of 3 defined points using my interpretation (which is most likely the problem) of a Bezier curve. I am aiming longterm to change the EndPoint variables to the StartPoint variables to start a new curve from the end of this one.

I have solved the problem I had and this code now works for anyone who wants the same kind of effect.

var StartPointX: float = 0;
var StartPointY: float = 0;
var ControlPointX: float = 20;
var ControlPointY: float = 50;
var EndPointX : float = 50;
var EndPointY : float = 0;
var CurveX:float;
var CurveY: float;
var BezierTime: float = 0;
var mySphere: Transform;

function Update()
{
    BezierTime = BezierTime + Time.deltaTime;

    if (BezierTime >= 1)
    {
        BezierTime = 0;
    }

    CurveX = (((1-BezierTime)*(1-BezierTime)) * StartPointX) + (2 * BezierTime * (1 - BezierTime) * ControlPointX) + ((BezierTime * BezierTime) * EndPointX);
    CurveY = (((1-BezierTime)*(1-BezierTime)) * StartPointY) + (2 * BezierTime * (1 - BezierTime) * ControlPointY) + ((BezierTime * BezierTime) * EndPointY);
    transform.position = Vector3(CurveX, CurveY, 0);

}

<p>I hate to do this, but which variables control the speed of how fast the object moves along the curve? </p> <p>I assume it's Beizertime, but I've attempted to manipulate this variable, and it doesn't seem to slow the object down. </p>

I have edited to the above question to show a now working solution

So helpful!!! Is the 3D version simple?

CurveZ = (((1-BezierTime)*(1-BezierTime)) * StartPointZ) + (2 * BezierTime * (1 - BezierTime) * ControlPointZ) + ((BezierTime * BezierTime) * EndPointZ); << - add this and you'll have the 3D version. Of course, you'll have to declare the necessary variables for Z.

This is a great solution. But I have to ask, how do you control the speed variable? by default, the object is way too fast. Thanks again!

4 Answers

4

The original question was a mistyping of the actual equation. I have changed the code so that it is now workable for anyone whom wants to adapt or use it.

Hi AdvsNoob, could you please attach the entire file, either to myself in a private message, or to this post, so that I can look at it a bit more in depth? Thanks.

Well, just found this question, i know you got it to work but you’ve heard about Vector2 / Vector3 and functions?

// UnityScript
function Bezier2(Start : Vector2, Control : Vector2, End : Vector2 , t :float) : Vector2
{
    return (((1-t)*(1-t)) * Start) + (2 * t * (1 - t) * Control) + ((t * t) * End);
}

function Bezier2(Start : Vector3, Control : Vector3, End : Vector3 , t :float) : Vector3
{
    return (((1-t)*(1-t)) * Start) + (2 * t * (1 - t) * Control) + ((t * t) * End);
}

function Bezier3(s : Vector2, st : Vector2, et : Vector2, e : Vector2, t : float) : Vector2
{
    return (((-s + 3*(st-et) + e)* t + (3*(s+et) - 6*st))* t + 3*(st-s))* t + s;
}

function Bezier3(s : Vector3, st : Vector3, et : Vector3, e : Vector3, t : float) : Vector3
{
    return (((-s + 3*(st-et) + e)* t + (3*(s+et) - 6*st))* t + 3*(st-s))* t + s;
}

That’s are two versions: a quadratic bezier(one control point) and a cubic bezier(two control points). Each comes in two versions: Vector2 and Vector3.

The cubic equatation is transformed so you don’t have those ugly (1-t)(1-t)(1-t). When you just multiply the brackets you get (1 + (-3 +(3-t)*t)*t) which looks even more ugly but with the other terms it resolves quite nicely :wink:

edit

//C#
public static Vector2 Bezier2(Vector2 Start, Vector2 Control, Vector2 End, float t)
{
    return (((1-t)*(1-t)) * Start) + (2 * t * (1 - t) * Control) + ((t * t) * End);
}

public static Vector3 Bezier2(Vector3 Start, Vector3 Control, Vector3 End, float t)
{
    return (((1-t)*(1-t)) * Start) + (2 * t * (1 - t) * Control) + ((t * t) * End);
}

public static Vector2 Bezier3(Vector2 s, Vector2 st, Vector2 et, Vector2 e, float t)
{
    return (((-s + 3*(st-et) + e)* t + (3*(s+et) - 6*st))* t + 3*(st-s))* t + s;
}

public static Vector3 Bezier3(Vector3 s, Vector3 st, Vector3 et, Vector3 e, float t)
{
    return (((-s + 3*(st-et) + e)* t + (3*(s+et) - 6*st))* t + 3*(st-s))* t + s;
}

thanks a lot for this solution, it was really helpful.

Thanks for the proper solution. To add to add to this: For people who are just starting out with this type of math or want to understand what the code does, [here][1] is an excelent post on what Bezier actually does, complete with pictures and animations. [1]: http://www.theappguruz.com/blog/bezier-curve-in-games

The solution was simple I was doing > inv.database.craftingDatabase ["craft"] ["itemID_1"] when it should of been > inv.database.craftingDatabase*.ItemId1* Error on my part.

You can also use a tweening class like LeanTween to accomplish the same effect:

LeanTween.move( gameObject, [pt1, control2, control3, pt4], 1.0 );

You can also chain different paths together very easily, like

LeanTween.move( gameObject, [pt1, control2, control3, pt4, pt4, control5, control6, pt7..... etc], 1.0 );

And if you do not wish it to move at a constant speed you can pass an easing function like:

LeanTween.move( gameObject, [pt1, control2, control3, pt4], 1.0, {"ease":LeanTweenType.easeInOutQuad} );

Just a hint for anyone out there who doesn’t want to have to write their own bezier interpreting code!

Do I just add this to a cube or sphere to text? What do I use for the transform? I tried adding the script to an empty game object. Then I draged the cube to the "Transform" zeroed the "Y' values. I get nothing. Help please.

Thanks