creating a bezier curve in real time and making it move an object (read notes)


Wed Jan 25 2023 02:37:05 GMT+0000 (UTC)

Saved by @miguel9177 #c# #unity #physics

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class CurveBallTest : MonoBehaviour
    private enum CurveBallState { idle, startCross,crossingBall, endedCross}

    [Header("bezier curve points")]
    public Transform pointA; // The starting point of the Bezier curve
    public Transform pointB; // The first control point of the Bezier curve
    public Transform pointC; // The second control point of the Bezier curve
    public Transform pointD; // The end point of the Bezier curve

    public Transform crossingTarget;

    private CurveBallState state;

    [Header("cross settings")]
    public float speedOfCross = 1.0f; // The speed at which the object moves along the curve
    public float crossHeight = 3f;
    public float crossCurve = 3f;

    [Header("variables to get the ball speed while on bezier")]
    private Vector3 currentVelocity;
    private Vector3 lastPos;
    //public float duration = 5.0f; // The total duration of the curve

    Rigidbody rb;
    float startTime;

    void Start()
        rb = GetComponent<Rigidbody>();
        state = CurveBallState.startCross;

    void FixedUpdate()

    //this calls the correct functions depending on the current state
    private void CallFunctionsDependingOnState()
            case CurveBallState.startCross:
            case CurveBallState.crossingBall:
            case CurveBallState.endedCross:

    //this will initialize the cross
    private void StartCross()
        startTime = Time.time;
        state = CurveBallState.crossingBall;

    //this is called while the cross isnt finished (bezier curve hasnt ended)
    private void CrossingBall()
        float t = (Time.time - startTime) * speedOfCross;


        Vector3 position = CalculateBezierPoint(t, pointA.position, pointB.position, pointC.position, pointD.position);
        if (t >= 1)
            state = CurveBallState.endedCross;

    //this is called at the end of the cross (bezier curve ended)
    private void EndedCross()
        rb.isKinematic = false;
        rb.velocity = currentVelocity;
        state = CurveBallState.idle;

    #region Utility functions
    Vector3 CalculateBezierPoint(float t, Vector3 p0, Vector3 p1, Vector3 p2, Vector3 p3)
        // Calculate the position on the Bezier curve based on the t value
        float u = 1 - t;
        float tt = t * t;
        float uu = u * u;
        float uuu = uu * u;
        float ttt = tt * t;

        Vector3 p = uuu * p0;
        p += 3 * uu * t * p1;
        p += 3 * u * tt * p2;
        p += ttt * p3;

        return p;

    private void CalculateBallVelocityWhileOnBezier()
        currentVelocity = (rb.position - lastPos) / Time.fixedDeltaTime;
        lastPos = rb.position;

    private void CreateBezierCurvePoints()
        pointA.position = this.transform.position;

        Vector3 pointBPos_;
        pointBPos_ = pointA.position + (Vector3.forward * crossCurve);
        pointBPos_.y = pointA.position.y + crossHeight;
        pointB.position = pointBPos_;

        pointD.position = crossingTarget.position;

        Vector3 pointCPos_;
        pointCPos_ = pointD.position + (Vector3.forward * crossCurve);
        pointCPos_.y = pointD.position.y + crossHeight;
        pointC.position = pointCPos_;


this will create a bezier curve in real time and move the ball through it, in this example the point B and C are Moved at real time, if you want to setup this positions yourself, just comment the CreateBezierCurvePoints function.