Why when doing GetKey and not GetKeyDown the shooting is not working good ?

The script:

using UnityEngine;
using System.Collections;

public class Shooter : MonoBehaviour {

    public GameObject bullet = null;
    public float bulletSpeed = 500f;

    void Update ()
    {
     if (Input.GetKeyDown(KeyCode.G))
        {
            GameObject shot = (GameObject)Instantiate(bullet, transform.position
                + (transform.forward * 2), transform.rotation);

            Rigidbody _rigidbody = shot.AddComponent<Rigidbody>();
            _rigidbody.AddForce(transform.forward * bulletSpeed);
        }
    }
}
[code]

And the script that destroy the gameobject:

[code]
using UnityEngine;
using System.Collections;

public class Bullet : MonoBehaviour {

    void OnCollisionEnter(Collision c)
    {
        GameObject.Destroy(gameObject);
    }
}

When i click now on the G key it shoot a bullet and if i click many time quick on the G key it will shoot many bullets.

But now i want to add an option so if i press the G key none stop it will shoot many bullets none stop.
So i tried to change the line:

 if (Input.GetKeyDown(KeyCode.G))

To:

if (Input.GetKeyDown(KeyCode.G) || Input.GetKey(KeyCode.G))

But this make it shoot one bullet at a time or two and if i press the G key none stop it’s not shooting at all or at least not shooting none stop bullets.

I also tried only:

if (Input.GetKey(KeyCode.G))

But this wasn’t working fine also.

I would guess that you’re shooting bullets so fast that they are colliding with each other as soon as they’re created, and you have code to delete them as soon as they collide. You need to set physics layers to have the bullets ignore their own layer when checking for collision. Also, I think you’ll find that you will be spawning bullets way too fast if you do this anyway, since it will create a new bullet every frame; if you’re running at 60 fps that’s 60 individual bullets every second. A real life assault rifle only shoots about 10 bullets per second.

1 Like

If i’m changing the Update function to this then it’s working with the GetKey and also with the GetKeyDown but the question now if it’s count as solution a good solution ?

At the top i added: private int frames = 0;

void Update ()
    {
        frames++;
        if (frames % 10 == 0)
        {
            if (Input.GetKeyDown(KeyCode.G) || Input.GetKey(KeyCode.G))
            {
                GameObject shot = (GameObject)Instantiate(bullet, transform.position
                    + (transform.forward * 2), transform.rotation);

                Rigidbody _rigidbody = shot.AddComponent<Rigidbody>();
                _rigidbody.AddForce(transform.forward * bulletSpeed);
            }
        }
    }

right approach, wrong choice of implementation. Your version would make the rate of fire frame dependent. More bullets when the game is running quickly etc.

Usually rate of fire is setup to be governed by the desired delay between shots in actual time, not frame counts.

I tried this implementation but it does nothing when i click the G key or press the G key.
Could you show me maybe how to do it right ?

using UnityEngine;
using System.Collections;

public class Shooter : MonoBehaviour {

    public GameObject bullet = null;
    public float bulletSpeed = 500f;

    private bool toFire = true;

    void Update ()
    {
        if (Input.GetKeyDown(KeyCode.G) || Input.GetKey(KeyCode.G) && toFire)
        {
            FireBullets();
        }
    }

    IEnumerator FireBullets()
    {
        toFire = false;

        GameObject shot = (GameObject)Instantiate(bullet, transform.position
                    + (transform.forward * 2), transform.rotation);

        Rigidbody _rigidbody = shot.AddComponent<Rigidbody>();
        _rigidbody.AddForce(transform.forward * bulletSpeed);

        yield return new WaitForSeconds(10);

        toFire = true;
    }
}
public class Shooter : MonoBehaviour
{
    public GameObject bulletPrefab;
    public Transform spawnPoint;

    //throttle rate of fire upto 20 rounds per second. higher rate of fire should require a more specialized implementation
    [Range(0f,20f)] public float bulletsPerSecond = 10f;

    private float fireDelay =0;

    private void Update()
    {
        fireDelay = Mathf.MoveTowards(fireDelay,0, bulletsPerSecond * Time.deltaTime);

        if(!Mathf.Approximately(0,fireDelay)) return; //if delay not 0 then the gun is currently reloading the chamber
        if(!Input.GetKey(KeyCode.G)) return; //if the fire key is not pressed nothing else needs to be done


        fireDelay = 1f;
        Instantiate(bulletPrefab,spawnPoint.position, spawnPoint.rotation);

        //I usually have the bullet propel itself on spawn, incase the bullet isn't always physics-based
    }
}

Is that also a good way to do it ?

public GameObject bullet = null;
    public float bulletSpeed = 500f;
    public float fireRate = 0.2f;
    public float coolDownTime = 1f; // 0.2 --> 5 shots per second
    private float time = 0;

    void Update()
    {
        if (time > 0)
        {
            time -= Time.deltaTime;
        }
        else
        {
            if (Input.GetKey(KeyCode.G))
            {
                coolDownTime = 1f / fireRate;
                time += coolDownTime;

                GameObject shot = (GameObject)Instantiate(bullet, transform.position
                    + (transform.forward * 2), transform.rotation);

                Rigidbody _rigidbody = shot.AddComponent<Rigidbody>();
                _rigidbody.AddForce(transform.forward * bulletSpeed);
            }
        }
    }

If so then i have two questions:

  1. Why when i change the value of coolDownTime while the game is running it’s all the time get back 0.14 i tried to change it to 1 or to 7 but it’s back to 0.14

  2. What this do: transform.forward * 2 ? Make it to move twice faster ?

Update:

I see now that i’m not using the time variable and the collDownTime in my old lines with the shot variable and the _rigidbody. What should i do ?