Help Moving Object Along Object Curve

Hi, so i copied this script from stack overflow to help me move an object along a curve, when the game starts, the ball fires upwards and lands down on the target, could this possible be changed to fly along a sideways curve instead of an upward curve? I really have no idea how the math works. Or if someone knows a better way I could achieve a side curve? Or should I just use Lerp? Thank you in advance

public class BallisticLauncherTest : MonoBehaviour
{

    public GameObject ballGameObject;
    public Transform target;


    // Use this for initialization
    void Start()
    {
        ThrowBallAtTargetLocation(target.position, 10f);  
    }

    // Throws ball at location with regards to gravity (assuming no obstacles in path) and initialVelocity (how hard to throw the ball)
    public void ThrowBallAtTargetLocation(Vector3 targetLocation, float initialVelocity)
    {
        Vector3 direction = (targetLocation - transform.position).normalized;
        float distance = Vector3.Distance(targetLocation, transform.position);

        float firingElevationAngle = FiringElevationAngle(Physics.gravity.magnitude, distance, initialVelocity);
        Vector3 elevation = Quaternion.AngleAxis(firingElevationAngle, transform.right) * transform.up;
        float directionAngle = AngleBetweenAboutAxis(transform.forward, direction, transform.up);
        Vector3 velocity = Quaternion.AngleAxis(directionAngle, transform.up) * elevation * initialVelocity;

        // ballGameObject is object to be thrown
        ballGameObject.rigidbody.AddForce(velocity, ForceMode.VelocityChange);
    }

    // Helper method to find angle between two points (v1 & v2) with respect to axis n
    public static float AngleBetweenAboutAxis(Vector3 v1, Vector3 v2, Vector3 n)
    {
        return Mathf.Atan2(
            Vector3.Dot(n, Vector3.Cross(v1, v2)),
            Vector3.Dot(v1, v2)) * Mathf.Rad2Deg;
    }

    // Helper method to find angle of elevation (ballistic trajectory) required to reach distance with initialVelocity
    // Does not take wind resistance into consideration.
    private float FiringElevationAngle(float gravity, float distance, float initialVelocity)
    {
        float angle = 0.5f * Mathf.Asin((gravity * distance) / (initialVelocity * initialVelocity)) * Mathf.Rad2Deg;
        return angle;
    }
}

There’s many full trajectory tutorials on Youtube… if the one you chose above doesn’t work, I would just try another.

At the end of the day the repeated operation is simply:

// move according to velocity
position += velocity * Time.deltaTime;

// apply gravity to velocity
velocity += Gravity * Time.deltaTime;

That’s it. Every thrown baseball, every fired bullet, etc. does this.

(Yes, it also has air resistance drag, which can be approximated by subtracting a little bit of velocity if you want)

// optional velocity drag term
velocity -= velocity * DragCoefficient * Time.deltaTime;

If you want to follow something more arbitrary, bezier curves can be one solution and there are plenty of Asset Store offerings, such as this one:

Since you’re asking for a “sideways” curve, I’ll assume the desired trajectory isn’t necessarily a result of a force like gravity but more of a cosmetic choice. If that’s the case, I have a slightly exotic proposition:
Interpolate the position of the object that should follow the curve between its start position and the end point of the curve, and to calculate how far the object should be offset perpendicular to the straight line you would get that way (i.e. the “elevation” in the vertical case), use an AnimationCurve. Make it a public / serialized field, then you get a nice little curve editor in the inspector to specify just how the curve should look. To get the offset value, use AnimationCurve.Evaluate(float time) and reuse the “time” parameter used for the interpolation (possibly normalized to range [0…1]). You can then add the resulting value multiplied by transform.right to the object’s position (that would offset it along its local “right” direction) each frame after the lerp.
Something like this:

[SerializeField] private AnimationCurve curve;

public void Update()
{
    followObject.transform.position = Vector3.Lerp(initialPosition, endPosition, time);
    float offset = curve.Evaluate(time / lerpDuration);
    followObject.transform.position += offset * followObject.transform.right;
}

(Side note: consider using FixedUpdate instead of Update if the movement should be framerate-independent.)

Thank you for the info, I found a million curved shot tutorials that handle upward motion but couldnt really find a solution to a side curve that i can figure out so I’m giving up

Thank you for your help but I realised it was way too complicated for me so I have given up on the idea, I was looking at a free lerp asset that handled stuff for me, but I couldnt work that either so I’ll come back later down the line when I can understand this stuff better

When a thrown ball (as in baseball) curves, the net effect is essentially a tilted gravity vector.

While the main part of the gravity goes straight down, the aerodynamic “tilt” would be lateral according to the flight path of the ball, and obviously tons of other aerodynamic details that you probably don’t really care about in a game.

Here’s a quick functional example: download my MakeGeo project and then go into the Ballistic3D.cs file and replace its Update() method with this:

// REPLACE the existing Update() method in Ballistic3D.cs in my MakeGeo project
    void Update ()
    {
        transform.position += velocity * Time.deltaTime;

        velocity += gravity * Time.deltaTime;

        // curveball example for @iamthebubb:
        {
            // calculate the "flat forward" speed
            Vector3 forwardVelocity = velocity;
            forwardVelocity.y = 0;
            forwardVelocity.Normalize();

            // rotate this vector 90 degrees to one side (negative is left)
            Vector3 sidewardVelocity = Quaternion.Euler (0, -90, 0) * forwardVelocity;

            // scale it by however strong we want the curve effect
            sidewardVelocity *= 4.0f;

            // add this curve acceleration into the velocity
            velocity += sidewardVelocity * Time.deltaTime;
        }
    }

MakeGeo is presently hosted at these locations:

https://bitbucket.org/kurtdekker/makegeo

1 Like

That is amazing thank you! That’s exactly what I needed.