Skip to main content

On Sale: GamesAssetsToolsTabletopComics
Indie game storeFree gamesFun gamesHorror games
Game developmentAssetsComics
SalesBundles
Jobs
TagsGame Engines

Trying to do directional shooting

A topic by osrick97 created May 23, 2022 Views: 238 Replies: 6
Viewing posts 1 to 5
Submitted (7 edits) (+1)

Is anyone able to help me with this? I’m trying to make a game using the new Input System used in these videos and trying to implement 4 way directional shooting with arrow keys and movement with WASD. My Input System Actions are Move that have been set to WASD, and Shoot that are set to the arrow keys I can move fine, but when I shoot, sometimes the bullet stops moving and then if I hold an arrow key, then the bullet that had stopped moving will move in the direction of the new arrow key being pressed. I would like for the bullet to just go in the direction it was shot in and continue until it hits something. Here is the code for the bullet. (There's definitely some better way to write this code, and I would love to learn how).

using UnityEngine;
using UnityEngine.InputSystem;
public class Bullet : MonoBehaviour
{
    Rigidbody2D myRigidBody;
    [SerializeField] float bulletSpeed = 10f;
    [SerializeField] float fireDelay;
    private float lastFire;
    public InputAction bulletControls;
    Vector2 shootDirection = Vector2.zero;
    private void OnEnable() 
    {         bulletControls.Enable();     }     private void OnDisable()
    {         bulletControls.Disable();     }    
    void Start()     {         myRigidBody = GetComponent<Rigidbody2D>();     }     void Update()     {         if(Time.deltaTime > lastFire + fireDelay)         {             Shoot(shootDirection);             lastFire = Time.deltaTime;         }     }     void Shoot(Vector2 direction)     {         shootDirection = bulletControls.ReadValue<Vector2>();         myRigidBody.velocity = new Vector2(shootDirection.x * bulletSpeed, shootDirection.y * bulletSpeed);     }     private void OnTriggerEnter2D(Collider2D other)
    {         if(other.tag == "Enemy")         {             Destroy(other.gameObject);         }         Destroy(gameObject);     }     private void OnCollisionEnter2D(Collision2D other)
    {         Destroy(gameObject);
    } }
(1 edit)

You can put code in ```

Submitted(+1)

I think the problem is that you put the firing controls in the bullet object itself so it's continuing to take input even though you don't want it to. Instead try moving the controls to whatever object is firing the bullet and then you can pass the vector to the bullet when its instantiated or pulled from the object pool.

Hope that helps.

Submitted (1 edit)

I understand what you said a little bit, but I'm having trouble trying to implement it. I moved the shooting stuff and now the bullets just spawn and sit. From the tips you gave it sounds like I'm supposed to call something in the Bullet script, but I don't know what. I decided to use the old input system for getting keys pressed because the new one is just giving me trouble. My player is the one shooting the bullets, here is the code that I have for the Player script

using UnityEngine;
using UnityEngine.InputSystem;
public class PlayerController : MonoBehaviour
{
    [SerializeField] float runspeed = 10f;
    [SerializeField] GameObject bullet;
    [SerializeField] Transform gun;
    [SerializeField] float bulletSpeed = 10f;
    [SerializeField] float fireDelay;
    private float lastFire;
    
    Vector2 moveInput;
    Rigidbody2D myRigidbody;
    Rigidbody2D bulletRigidBody;
    bool isAlive = true;
    void Start()
    {
        myRigidbody = GetComponent<Rigidbody2D>();
    }
    void Update()
    {
        if(!isAlive) { return; }
        Run();
        if(Time.time > lastFire + fireDelay) { return; }
        Fire();
    }
    void OnMove(InputValue value)
    {
        moveInput = value.Get<Vector2>();
    }
    void Run()
    {
        Vector2 playerVelocity = new Vector2 (moveInput.x * runspeed, moveInput.y * runspeed);
        myRigidbody.velocity = playerVelocity;
    }
    void OnShoot(InputValue value)
    {
        if(!isAlive) { return; }
        Instantiate(bullet, gun.position, transform.rotation);
    }
    void Fire()
    {
        if (Input.GetKey(KeyCode.UpArrow)) 
        {
            Shoot(Vector2.up);
            lastFire = Time.time;
        }
        else if (Input.GetKey(KeyCode.RightArrow)) 
        {
            Shoot(Vector2.right);
            lastFire = Time.time;
        } 
        else if (Input.GetKey(KeyCode.DownArrow)) 
        {
            Shoot(Vector2.down);
            lastFire = Time.time;
        }
        else if (Input.GetKey(KeyCode.LeftArrow)) 
        {
            Shoot(Vector2.left);
            lastFire = Time.time;
        }
    }
    void Shoot(Vector2 direction)
    {
        bulletRigidBody.velocity = new Vector2(direction.x * bulletSpeed, direction.y * bulletSpeed);
    }
}
// the text after this comment is the code in my Bullet script
using UnityEngine;
public class Bullet : MonoBehaviour 
{     
    private void OnTriggerEnter2D(Collider2D other)      
    {         
        if(other.tag == "Enemy")         
        {             
            Destroy(other.gameObject);         
        }         
        Destroy(gameObject);     
    }      
    private void OnCollisionEnter2D(Collision2D other)      
    {         
        Destroy(gameObject);      
    }
}
Submitted(+1)

Unless I'm overlooking something you haven't assigned a value to bulletRigidbody so that's why it isn't doing anything. Without testing it myself you need something like:

GameObject bullet = Instantiate(//instantiate code)

Rigidbody2D bulletRigidbody = bullet.GetComponent<Rigidbody2D>()

And then set its velocity.

Submitted (2 edits) (+1)

Here's what I'm suspecting is happening...

Depending on the order scripts are running, you're instantiating a bullet after the shoot command has already been dealt with. Then, when the time for the next shot is available, the stagnant bullet is still ready to accept the next Shoot() method. So, then the next bullet.

You may want to debug those processes.

I'm still not totally secure on the OnEnable/OnDisable parts of the new system, but I believe bulletControls.Disable() will turn off the receiver for the button presses.

...Now that I'm reading it again. I think this is the long winded explanation to. "Yeah,  what Max Frymark said."

(+1)

I see another issue in your code.   You  are dealing with the wrong Time.  command. You have to change  the following lines:
if(Time.deltaTime >   lastFire + fireDelay) to   if(Time.time >   lastFire + fireDelay)
and   lastFire = Time.deltaTime; to  lastFire = Time.time;