Getting launch angle for projectile given height, distance and speed in 3D

I am trying to calculate the launch velocity of a ball that needs to land at a certain position in 3D space. I know the height the ball will be launched from, the position it needs to land and the initial magnitude of the velocity.

I want to produce a Vector3 that I can use with AddForce that propels the ball and lands on the target.

I have the following function that I use to work out the launch angle, based on equations in this video:

private Vector3 GetLaunchAngle(float speed)
{
    //Calculate angle to z-axis
    float height = transform.position.y; //Height from 0
    float distance = Vector3.Distance(new Vector3(transform.position.x, 0, transform.position.z), new Vector3(aim.transform.position.x, 0, aim.transform.position.z)); //Distance to target (aim)
    float angle;
    Vector3 launchAngle = Vector3.forward;

    float quadB = 0.5f * Physics.gravity.y * (distance / speed); //B in quadratic equation = 1/2g * (d/v)
    float quadC = quadB + height;  //C in quadratic equation

    float tanAngle1 = (-quadB + Mathf.Sqrt((quadB * quadB) - (4 * distance * quadC))) / (2 * distance); //Calculate + in quadratic equation
    float tanAngle2 = (-quadB - Mathf.Sqrt((quadB * quadB) - (4 * distance * quadC))) / (2 * distance); //Calculate - in quadratic equation

    //Calculate both possibilities of angle
    float angle1 = Mathf.Rad2Deg * Mathf.Atan(tanAngle1);
    float angle2 = Mathf.Rad2Deg * Mathf.Atan(tanAngle2);

    //If angle 1 is invalid
    if (angle1 > 90 || angle1 < -90 || float.IsNaN(angle1))
    {
        angle = angle2;
    }
    //If angle 2 is invalid
    else if (angle2 > 90 || angle2 < -90 || float.IsNaN(angle2))
    {
        angle = angle1;
    }
    //If both are valid get min angle
    else if (!float.IsNaN(angle1) && !float.IsNaN(angle2))
    {
        angle = Math.Min(angle1, angle2);
    }
    else
    {
        angle = float.NaN;
    }

    //Try to rotate correct angles
    if (!float.IsNaN(angle))
    {
        //Apply x-axis rotation
        launchAngle = Quaternion.AngleAxis(angle, Vector3.left) * launchAngle;
        //Calculate (x,y) angle to target
        float angleTarget = Vector2.Angle(new Vector2(transform.position.x, transform.position.z), new Vector2(aim.transform.position.x, aim.transform.position.z));
        //Set left/right rotation
        angleTarget = angleTarget > 90 ? angleTarget - 180 : angleTarget;
        //Apply y-axis rotation
        launchAngle = Quaternion.AngleAxis(angleTarget, Vector3.up) * launchAngle;
    }
    else
    {
        launchAngle = Vector3.forward;
    }

    return launchAngle;
}

The main things that are wrong with this are, the (x,z) direction is off (see screenshot 1 below). I’m sure that the below is not the best way to do this:

float angleTarget = Vector2.Angle(new Vector2(transform.position.x, transform.position.z), new Vector2(aim.transform.position.x, aim.transform.position.z));
//Set left/right rotation
angleTarget = angleTarget > 90 ? angleTarget - 180 : angleTarget;
//Apply y-axis rotation
launchAngle = Quaternion.AngleAxis(angleTarget, Vector3.up) * launchAngle;

Also, I think that the calculated angle of incline is correct but I am open to other ideas around that.

Final issue is with the rigidbody.AddForce(launchAngle * speed);. So the speed is used to calculate the launch angle, but when used as the impulse for the force it barely moves, it looks like screenshot 2. I am using the ratio of 1 unit to 1m in Unity and therefore used a value of 35 for the speed (assuming this to mean 35m/s or approximately 80mph). Upon keeping the speed for the calculation of the angle but changing the impulse of the force to 1000, the ball moves like screenshot 3. How do you get the correct impulse on the rigidbody?

What is the best method for this?

EDIT: I have changed the AddForce to use the different ForceMode values with speed (35). Impulse and VelocityChange look like screens 4 & 5, it has improved the look of the arc, but it is still out (Long and left).
Force and Acceleration looks like screenshot 2.

Screenshot 1
Screenshot 1
Screenshot 2
Screenshot 2
Screenshot 3
Screenshot 3
Screenshot 4
Screenshot 5
Screenshot 5
Screenshot 5

Using the answer found here I was able to get it working with the following code and called with
Vector3 launchAngle = GetLaunchAngle(speed); rigidbody.AddForce(launchAngle, ForceMode.VelocityChange);

private Vector3 GetLaunchAngle(float speed)
{
    Vector3 toTarget = aim.transform.position - new Vector3(transform.position.x, transform.position.y - GetComponent<SphereCollider>().bounds.size.y, transform.position.z);
    Vector3 launchAngle = Vector3.up;

    float gSquared = Physics.gravity.sqrMagnitude;
    float b = speed * speed + Vector3.Dot(toTarget, Physics.gravity);
    float discriminant = b * b - gSquared * toTarget.sqrMagnitude;

    if(discriminant >= 0)
    {
        float discRoot = Mathf.Sqrt(discriminant);
        float tMax = Mathf.Sqrt((b + discRoot) * 2 / gSquared);
        float tMin = Mathf.Sqrt((b - discRoot) * 2 / gSquared);
        float tLowEnergy = Mathf.Sqrt(Mathf.Sqrt(toTarget.sqrMagnitude * 4 / gSquared));

        float time = tMin;

        launchAngle = toTarget / time - Physics.gravity * time / 2;
    }

    return launchAngle;
}

Comparison shots are below:
[88332-cricket9.png|88332]
[88333-cricket10.png|88333]

Thanks man