Problems with the shooting on my game

I’m making a shmup game and obviously one of the most important things of this type of game is if the bullet system is working.

However, the bullets are not coming out in the position they should, which is at the player’s position. Furthermore, multiple bullets are firing at once, making it appear as a continuous line instead of a single one.

Unfortunately, I can’t attach a video showing the problem running, but I have the code.

Here are the lines of code for the player, the gun and the bullet.

using System;
using Unity.VisualScripting;
using UnityEngine;
using UnityEngine.InputSystem;

public class Player : MonoBehaviour
{
    // This array will hold references to all Gun components that are children of the player
    Gun[] guns;
    bool shoot;

    // This is the input action for moving the player, which can be set up in the Unity editor
    public InputAction MoveAction;
    public float moveSpeed = 5f;
    private Vector2 move;

    // Variables for health management
    public int maxHealth = 100;
    public int health { get { return currentHealth; } }
    public int currentHealth;

    // Start is called once before the first execution of Update after the MonoBehaviour is created
    void Start()
    {
        guns = transform.GetComponentsInChildren<Gun>();
        MoveAction.Enable();
        currentHealth = maxHealth;
    }

    // Update is called once per frame
    void Update()
    {
        move = MoveAction.ReadValue<Vector2>();

        // Check if the space key is pressed to shoot
        shoot = Keyboard.current.spaceKey.isPressed;
        if (shoot)
        {
            shoot = false;
            foreach (Gun gun in guns)
            {
                gun.Shoot();
            }
        }
     
    }
    
    void FixedUpdate()
    {
        Vector2 position = (Vector2)transform.position + (move * 0.1f);
        transform.position = position;
    }

    // This method is called when the player takes damage or heals
   public void ChangeHealth(int amount)
    {
        currentHealth = Mathf.Clamp(currentHealth + amount, 0, maxHealth);
        Debug.Log(currentHealth + "/" + maxHealth);
    }
}
using UnityEngine;

public class Gun : MonoBehaviour
{
    public Bullet bullet;
    // Start is called once before the first execution of Update after the MonoBehaviour is created
    void Start()
    {
        
    }

    // Update is called once per frame
    void Update()
    {
        
    }

    // This method is called when the player shoots 
    public void Shoot()
    {
        Bullet spawnedBullet = Instantiate(bullet, transform.position, Quaternion.identity);
        Rigidbody2D rb = spawnedBullet.GetComponent<Rigidbody2D>();
    }
}
using UnityEngine;

public class Bullet : MonoBehaviour
{
    public Vector2 direction = new Vector2(1,0);
    public Vector2 velocity;
    public float speed = 2f;

    Rigidbody2D rb;

    // Start is called once before the first execution of Update after the MonoBehaviour is created
    void Start()
    {
        rb = GetComponent<Rigidbody2D>();
        rb.linearVelocity = transform.right * speed;

        Destroy(gameObject, 5);
    }

    // Update is called once per frame
    void Update()
    {
       velocity = direction * speed;
    }

    private void FixedUpdate()
    {
       Vector2 position = transform.position;
        position += velocity * Time.fixedDeltaTime;
        transform.position = position;
    }
}

Sounds like a bug! Print the positions, press pause, see where it’s coming from. Make sure you’re not referring to the prefab when you intend to refer to what is in scene.

The docs say that the .isPressed property of a KeyControl will fire anytime that button is down. You probably want a different property that is only when it is pressed this frame… see the docs for KeyControl.

If that’s not it, then it’s some other kind of bug, which means… time to start debugging!

By debugging you can find out exactly what your program is doing so you can fix it.

Use the above techniques to get the information you need in order to reason about what the problem is.

You can also use Debug.Log(...); statements to find out if any of your code is even running. Don’t assume it is.

Once you understand what the problem is, you may begin to reason about a solution to the problem.

Remember with Unity the code is only a tiny fraction of the problem space. Everything asset- and scene- wise must also be set up correctly to match the associated code and its assumptions.

Where is the part on the Unity manual that talks about KeyControl??

KeyControl is the class type of the spaceKey… you can filter for it in the docs left panel and it will instantly come up… it’s part of the InputSystem, specifically the controls.

You mention in a comment that the Guns are children of the player. Therefore projectiles use the gun’s transform.position, not the player’s:

    public void Shoot()
    {
        Bullet spawnedBullet = Instantiate(bullet, transform.position, Quaternion.identity);
    }

Each gun, if they are children, can have an offset relative to the player’s position. Check that the gun objects have their position at 0,0,0 so it matches the player’s position. If it’s non-zero it should only be a small offset, ie the actual gun’s firing point (barrel) relative to the player’s position.

You could also pass the player’s transform.position to the Shoot method and use that.

That’s because you test, every frame (Update) whether the key is (still) pressed. Which it will continue to be for several frames, thus spawning multiple bullets, one per gun, every frame while the key is down. You should check the wasJustPressed property instead.

Note that resetting the shoot field doesn’t change this. It’s actually unnecessary and needn’t be a field either:

        var isShooting = Keyboard.current.spaceKey.wasJustPressed;
        if (isShooting)
        {
            foreach (Gun gun in guns)
                gun.Shoot();
        }

Your suggestion to modify the code of how the shooting works was successful, which I greatly appreciate!!
I just didn’t understand your explanation of how to adjust the gun’s position to be with the player’s sprite. Because, even though I modified the position to coordinates 0,0,0; the player doesn’t stay at those coordinates and the gun always shoot behind the player, and I genuinely didn’t understand your explanation of the changes for this code.