0
\$\begingroup\$

I have created a simple player controller, which contains the player logic for a movement, aim and shooting bullets from a gun. Everything almost works, except the bullets shoot in random directions, so either the player is a really bad shooter or there is something wrong with the logic (or rigidbody).

Posted below is the code. Is there anything wrong with the code / logic?

Here is the update code:

void Update()
{
    // Move the character
    Move();
    // Aim the character
    Aim();
    // Start the shooting animation and the shooting coroutine if the shoot button is pressed
    if (shootInput && !isShooting)
    {
        anim.SetTrigger("Shoot");
        StartCoroutine(ShootCoroutine());
    }
    // Change ammo
    ChangeAmmo();
}

Aim code:

void Aim()
{
    // Get the input direction
    Vector3 inputDirection = new Vector3(aimInput.x, 0f, aimInput.y);
    // Check if there is aim input
    if (aimInput != Vector2.zero)
    {
        // Calculate the angle between the input direction and the forward direction
        float angle = Vector3.Angle(inputDirection, transform.forward);
    
        // Check if the angle is within the max aim angle
        if (angle < maxAimAngle)
        {
            // Rotate the weapon to aim in the input direction
        transform.rotation = Quaternion.Euler(0f, Mathf.Atan2(aimInput.x, aimInput.y) * Mathf.Rad2Deg, 0f);
            // Rotate the shootPosition to match the weapon's rotation
            shootPosition.rotation = transform.rotation;
        }
    }
}

Shoot code:

IEnumerator ShootCoroutine()
{
    isShooting = true;

    // Make sure the player has ammo
    if (ammo > 0)
    {
        // Create a new bullet at the shoot position
        GameObject bullet = Instantiate(projectilePrefab, shootPosition.position, shootPosition.rotation);
        // Add force to the bullet
        bullet.GetComponent<Rigidbody>().AddForce(shootPosition.forward * shootForce, ForceMode.Impulse);
        // Reduce ammo
        ammo -= 1;
        //Start the animation
        anim.SetTrigger("Shoot");
        // Visualize the direction of the bullet using Debug.DrawRay()
        Debug.DrawRay(shootPosition.position, shootPosition.forward * 50f, Color.red, 2f);
    }
    // Wait for the cooldown time before allowing the player to shoot again
    yield return new WaitForSeconds(cooldownTime);
    isShooting = false;
}
}
\$\endgroup\$
1
  • 1
    \$\begingroup\$ Is it possible the bullet has a collider that's colliding with the thing shooting it and knocking it off-course? If you've ruled that out, the next thing I'd do is try to eliminate possible sources of error to isolate the problem. Does the aim function work on its own? If you comment out the aim function and just shoot in a fixed direction, does that behave as expected? Work toward thinning this down to the minimal set of code that reproduces the problem. \$\endgroup\$
    – DMGregory
    Commented Jan 20, 2023 at 20:38

1 Answer 1

0
\$\begingroup\$

As DMGregory suggested, the most likely explanation is that the bullet is either bouncing off of the gun's collider or the player's collider. There's an easy way to determine if that's happening - attach this script to your bullet prefab:

public class CollisionLogger : MonoBehaviour {
    void OnCollisionEnter(Collision collision) {
        Debug.Log($"{this.name} collided with {collision.gameObject.name}", this);
    }
}

If the bullet is bouncing off of the gun or player, you can fix this with the layer collision matrix or using Physics.IgnoreCollision(). For example:

[SerializeField] private Collider gunCollider;
//...
IEnumerator ShootCoroutine()
{
    isShooting = true;

    // Make sure the player has ammo
    if (ammo > 0)
    {
        // Create a new bullet at the shoot position
        GameObject bullet = Instantiate(projectilePrefab, shootPosition.position, shootPosition.rotation);
        //make sure bullet can't bounce off of gun
        var bulletCollider = bullet.GetComponent<Collider>();
        Physics.IgnoreCollision(gunCollider, bulletCollider);
        // Add force to the bullet
        bullet.GetComponent<Rigidbody>().AddForce(shootPosition.forward * shootForce, ForceMode.Impulse);
        // Reduce ammo
        ammo -= 1;
        //Start the animation
        anim.SetTrigger("Shoot");
        // Visualize the direction of the bullet using Debug.DrawRay()
        Debug.DrawRay(shootPosition.position, shootPosition.forward * 50f, Color.red, 2f);
    }
    // Wait for the cooldown time before allowing the player to shoot again
    yield return new WaitForSeconds(cooldownTime);
    isShooting = false;
}
        

As the documentation for Physics.IgnoreCollision() says:

This is useful, say, for preventing projectiles from colliding with the object that fires them.

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .