Unity - Projectile Motion, find the angle needed to hit coordinates x,y

我是研究僧i 提交于 2021-02-11 15:48:32

问题


Plenty of questions asked around the same topic, but nothing seems to be working for me.

The problem is simple, a player and an enemy are on the x,y plane. I want to launch my projectile at a calculated angle in such way that the projectile will hit the enemy at it's coordinates.

I've tried implementing both

Angle of Reach and Angle required to hit x,y

Both of these implementation end up doing the same for me; Shooting but not hitting the target in this manner

Any help or pointers would be much appreciated! Thank you

Here is the code:

public Rigidbody projectile;
public float projectileSpeed;
public float Firerate = 9f;
private float nextfire;

private GameObject enemy;
private float gravity = Physics.gravity.y;
private Vector3 directionalVector;

// Start is called before the first frame update
void Start()
{
    enemy = GameObject.FindGameObjectWithTag("enemy");

}


void Update()
{
    directionalVector = enemy.transform.position - transform.position;

}
void FixedUpdate()
{

    nextfire = Time.time + (1 / Firerate);

    float projectileSpeed2 = projectileSpeed * projectileSpeed;
    float projectileSpeed4 = projectileSpeed2 * projectileSpeed2;
    float x = enemy.transform.position.x;
    float y = enemy.transform.position.y;
    float x2 = x * x;



    float theta = Mathf.Atan(projectileSpeed2-Mathf.Sqrt(projectileSpeed4-gravity*(gravity*x2+2*y*projectileSpeed2))/gravity*x);
    print(theta);

    Vector3 releaseVector = (Quaternion.AngleAxis(theta, Vector3.up) * directionalVector).normalized;

    Debug.DrawRay(transform.position, releaseVector, Color.red,0.5f);
    Rigidbody instantiatedProjectile = Instantiate(projectile, transform.position, transform.rotation) as Rigidbody;
    instantiatedProjectile.velocity = releaseVector * projectileSpeed;
}

}


回答1:


Why not avoid the problem of finding the angle, and just move the bullet based on the direction on where it first saw the enemy.

(target.transform.position - transform.position).normalized;

It will return a Vector direction to the target.

When the projectile moves, just move it based on this direction.
No headache needed in calculating angles :)

Edit

I made a function before to 'convert' an angle to direction:

protected Vector2 DetermineBulletMoveDirection(float shootingAngle) {
    // Determine the direction of the bullet travel on the x and y axis.
    float bulletDirectionX = transform.position.x + Mathf.Sin((shootingAngle * Mathf.PI) / 180);
    float bulletDirectionY = transform.position.y + Mathf.Cos((shootingAngle * Mathf.PI) / 180);

    // Determines the direction this bullet should be moving.
    Vector2 bulletDirection = new Vector2(bulletDirectionX, bulletDirectionY);
    return (bulletDirection - (Vector2)transform.position).normalized;
}

It takes in an angle, and converts it into a direction based on where the shooter is currently at.
The angle should start from Vector.down, and rotates clockwise.

The next problem is to find out the angle between you and the enemy.
This is the simplest solution I could think of, here is a diagram first:

Notice that you can use TOACAHSOH on this?

So all you have to do, is to 'virtually' align the Y axis of the shooter to the origin.
(Apply the movement to the shooter too!)

Do the same thing for the shooter, but on the x-axis this time.

And you would be able to achieve that state where you have a triangle with a 90-degree.
From there on, you can calculate the angle to rotate from Vector.down to the enemy.

Just make sure you move both of the objects back to it's initial position.




回答2:


After fighting this for a while I found a solution.

In the end I ended up using the Angle of Reach. The second error was that Mathf.Atan returns radians and not degrees, while Quantion.AngleAxis takes in angles. The third and the final one was the fact that Unity uses left hand coordinate system as opposed to the usual right hand system which I was used to.

Here is the final piece of code:

public class TargetAndShoot : MonoBehaviour
{
    public Rigidbody projectile;
    public float projectileSpeed;
    public float firerate;
    private float nextfire;

    private GameObject enemy;
    private float gravity = Physics.gravity.y;


    // Start is called before the first frame update
    void Start()
    {
        enemy = GameObject.FindGameObjectWithTag("enemy");

    }


    void Update()
    {
        if (Time.time >= nextfire)
        {
            nextfire = Time.time + (1 / firerate);
            float distance = enemy.transform.position.x - transform.position.x;
            Vector3 directionalVector = enemy.transform.position - transform.position;

            float v2 = projectileSpeed * projectileSpeed;
            float v4 = v2 * v2;

            float x = enemy.transform.position.x;
            float x2 = x * x;
            float y = enemy.transform.position.y;

            float theta = 0.5f*Mathf.Asin((gravity * distance) / (projectileSpeed * projectileSpeed));
            Vector3 releaseVector = (Quaternion.AngleAxis(theta * Mathf.Rad2Deg, -Vector3.forward) * directionalVector).normalized;
            Debug.DrawRay(transform.position, releaseVector*5, Color.cyan, 0.5f);

            Rigidbody instantiatedProjectile = Instantiate(projectile, transform.position, transform.rotation) as Rigidbody;
            instantiatedProjectile.velocity = releaseVector * projectileSpeed;
        }
    }

}


来源:https://stackoverflow.com/questions/59117784/unity-projectile-motion-find-the-angle-needed-to-hit-coordinates-x-y

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!