[Solved]Targeting ball ?

I got this script from website. It works but need some improvement. I need to change the power of shoot. In this script there is a range “_angle” but it’s not what i want. I want to see a curve movement of the ball when hit target. automatic calculate the distance and pick the power ball needs to hit target in curve movement.

    public Transform _Goal;    // target
    [Range(20f, 70f)] public float _angle;   // shooting angle
    public float taget_range;  // how far from me

    void Update()
    {
        taget_range = Vector3.Distance(gameObject.transform.position, _Goal.position);

        if (Input.GetKeyDown(KeyCode.Space) && taget_range <= 20f)
        {
            Launch();
        }
 
    }

    // Launches the cube to the target transform (_bullseye)
    private void Launch()
    {
        // source and target positions
        Vector3 pos = transform.position;
        Vector3 target = _Goal.position;

        // distance between target and source
        float dist = Vector3.Distance(pos, target);

        // rotate the object to face the target
        transform.LookAt(target);

        // calculate initival velocity required to land the cube on target using the formula (9)
        float Vi = Mathf.Sqrt(dist * -Physics.gravity.y / (Mathf.Sin(Mathf.Deg2Rad * _angle * 2)));
        float Vy, Vz;   // y,z components of the initial velocity

        Vy = Vi * Mathf.Sin(Mathf.Deg2Rad * _angle);
        Vz = Vi * Mathf.Cos(Mathf.Deg2Rad * _angle);

        // create the velocity vector in local space
        Vector3 localVelocity = new Vector3(0f, Vy, Vz);

        // transform it to global vector
        Vector3 globalVelocity = transform.TransformVector(localVelocity);

        // launch the cube by setting its initial velocity
        GetComponent<Rigidbody>().velocity = globalVelocity;

    }

I’ve just tried the code and it works fine. However, it hits the target position at the same height as itself. In other words, this formula assumes a flat terrain.

So I guess you are wanting to increase the initial velocity (on line 44) to still hit the target if it sits at an elevated position, is that your question?

I’ve been Googling and trying this out. Here is what I have come up with so far. It works on flat ground and when the target is raised higher.

public class Test : MonoBehaviour
{
    void Start()
    {
        m_body = GetComponent<Rigidbody>();
    }

    void Update()
    {
        if (    Input.GetKeyDown(KeyCode.Space)
            &&  Vector3.Distance(transform.position, m_goal.position) <= 20f )
        {
            Launch();
        }
    }

    private void Launch()
    {
        Vector3 pos = transform.position;
        Vector3 target = m_goal.position;

        // Split the distance into 2 components along the vertical 2D plane ...
        float deltaUp = pos.y - target.y;
        target.y = pos.y;
        float deltaAlong = Vector3.Distance(pos, target);

        // Calculate velocity based on 'turret' elevation
        var elevation = Mathf.Deg2Rad * m_angle;
        var numerator = m_halfGrav * ( deltaAlong * deltaAlong );
        var denominator = deltaUp + deltaAlong * Mathf.Tan(elevation);
        var vel = Mathf.Sqrt(numerator / denominator) / Mathf.Cos(elevation);

        if (vel <= 0f || float.IsNaN(vel) || float.IsInfinity(vel))
            return;

        // Calculate world angle
        var angle = Vector3.RotateTowards(
              (target - pos).normalized // Angle 'along the ground'.
            , Vector3.up
            , elevation                 // Angled up into the air.
            , 0f);

        // Fire ...
        m_body.velocity = angle * vel;
    }

#pragma warning disable 649
    [SerializeField] Transform m_goal;
    [SerializeField] [Range(20f, 70f)] float m_angle;   // 'Turret' angle.
#pragma warning restore 649

    const float m_halfGrav = 9.81f / 2f;
    Rigidbody m_body;
}
1 Like

Thank you so much Doug_B. you solved. :wink:

1 Like