Need help with instantiating a Bullet

I am current working on a kinda brawler-like game where 2 players shoot each other using one keyboard as controls. About 30 minutes ago I had the 2 players shooting bullets properly but for some reason, Player 2 no longer shoots bullets.Instead of shooting bullets, Player 2 kinda just creates a small invisible forward force when near him.I’ve been trying to find the source of the problem but I’ve failed for about 30 minutes now so I’m looking to see if someone may know how to fix this.

This is the script for player 2

using UnityEngine;

public class Player2Controller : MonoBehaviour {

    public float P2speed;
    public float P2JumpHeight;
    public GameObject P2Bullet;
    public GameObject P2Emitter;
    public float P2Bullet_speed;
   

    private Rigidbody P2rb;
    private bool P2grounded;
    private bool FacingLeft;
    public int P2health;

    void Start () {
        P2rb = GetComponent<Rigidbody>();
        P2grounded = true;
        FacingLeft = true;
       
    }
   
   
    void Fire(){
        
            GameObject P2Temporary_Bullet_Handler;
            P2Temporary_Bullet_Handler = Instantiate(P2Bullet,P2Emitter.transform.position,P2Emitter.transform.rotation) as GameObject;
            Rigidbody Temporary_RigidBody;
            Temporary_RigidBody = P2Temporary_Bullet_Handler.GetComponent<Rigidbody>();
            if(FacingLeft == false){
            Temporary_RigidBody.AddForce(new Vector3(1, 0, 0) * P2Bullet_speed);
            }

            if(FacingLeft == true){
            Temporary_RigidBody.AddForce(new Vector3(-1, 0, 0) * P2Bullet_speed);
            }


            Destroy(P2Temporary_Bullet_Handler, 3f);

    }


    void FixedUpdate () {

        if(Input.GetKey(KeyCode.RightArrow)){
            P2rb.AddForce(new Vector3(10, 0, 0) * P2speed * Time.deltaTime);
            transform.rotation = Quaternion.Euler(0, 180, 0);
            FacingLeft = false;
        }
        if(Input.GetKey(KeyCode.LeftArrow)){
            P2rb.AddForce(new Vector3(-10, 0, 0) * P2speed * Time.deltaTime);
            transform.rotation = Quaternion.Euler(0, 0, 0);
            FacingLeft=true;
        }
        if(Input.GetKey(KeyCode.UpArrow) && P2grounded == true){
            Debug.Log("Jump");
            P2rb.AddForce(new Vector3(0, 10, 0) * P2JumpHeight * Time.deltaTime);
            P2grounded = false;
        }

        if(Input.GetKeyDown(KeyCode.RightControl)){
            Debug.Log("Shoot2");
            Fire();
        }

        if(P2health<= 0){
            Destroy(gameObject);
        }

    }

    void OnTriggerEnter(Collider other){
        if(other.CompareTag("Ground")){
            P2grounded = true;
            Debug.Log("Grounded");
        }
    }
   
}

The 2 Scripts are basically the same [i think] with the only difference is that the script for the 2nd player has a “P2” prefixed to the variables to prevent complications.

This is the script for player1

using UnityEngine;

public class Player1Controller : MonoBehaviour {

    public float speed;
    public float JumpHeight;
    public GameObject Bullet;
    public GameObject Emitter;
    public float Bullet_speed;
   

    private Rigidbody rb;
    private bool grounded;
    private bool FacingLeft;
    public int health;

    void Start () {
        rb = GetComponent<Rigidbody>();
        grounded = true;
        FacingLeft = false;
       
    }
   
   
    void Fire(){
          //The Bullet instantiation happens here.
            GameObject Temporary_Bullet_Handler;
            Temporary_Bullet_Handler = Instantiate(Bullet,Emitter.transform.position,Emitter.transform.rotation) as GameObject;
            Rigidbody Temporary_RigidBody;
            Temporary_RigidBody = Temporary_Bullet_Handler.GetComponent<Rigidbody>();
            if(FacingLeft == false){
            Temporary_RigidBody.AddForce(new Vector3(1, 0, 0) * Bullet_speed);
            }

            if(FacingLeft == true){
            Temporary_RigidBody.AddForce(new Vector3(-1, 0, 0) * Bullet_speed);
            }


            Destroy(Temporary_Bullet_Handler, 3f);
    }


    void FixedUpdate () {

        if(Input.GetKey(KeyCode.D)){
            rb.AddForce(new Vector3(10, 0, 0) * speed * Time.deltaTime);
            transform.rotation = Quaternion.Euler(0, 0, 0);
            FacingLeft = false;
        }
        if(Input.GetKey(KeyCode.A)){
            rb.AddForce(new Vector3(-10, 0, 0) * speed * Time.deltaTime);
            transform.rotation = Quaternion.Euler(0, 180, 0);
            FacingLeft=true;
        }
        if(Input.GetKey(KeyCode.W) && grounded == true){
            Debug.Log("Jump");
            rb.AddForce(new Vector3(0, 10, 0) * JumpHeight * Time.deltaTime);
            grounded = false;
        }

        if(Input.GetKeyDown(KeyCode.Space)){
            Fire();
        }

        if(health<= 0){
            Destroy(gameObject);
        }

       

    }

    void OnTriggerEnter(Collider other){
        if(other.CompareTag("Ground")){
            grounded = true;
            Debug.Log("Grounded");
        }
       
    }

}

Hopefully someone can help me

Great work describing the problem well, sharing code and even a video demonstrating the issue!

First, let me get this out of the way: I challenge you to rethink these scripts and merge them into one “PlayerController” script that gets attached to both player objects. This will have several important benefits:

  • Less code to write / debug
  • Less tightly coupled design
  • More easily scaleable design (just add new controllers to have 4 players, for example)

Even with them as separate components, you don’t have to have the names of your variables be different. Scripts are compartmentalized enough that a shared variable name can’t be accidentally accessed from another object. And with a combined script, you really just need to define new input sources for each player when they’re instantiated, and that would mean you can handle everything else the same no matter which player you’re controlling. But that can be part of your optimization session later. For now, let’s figure out the issue.

If you’re using the built-in physics system, there’s a good chance your bullet objects are colliding with the player on instantiation. One easy way to test this is to create a new script that you attach to your Bullet prefab:

public class BulletHit: MonoBehavior {
    void OnCollisionEnter (Collision col) {
        Debug.Log("Bullet hitting " + col.gameObject.name);
    }
}

This will have the effect of spamming your console with messages as a player is shooting – or rather, as a player’s bullets are hitting something. If you see that, when Player2 is shooting, the messages are “Bullet hitting Player2”, you know that Player2’s bullets are getting jammed up inside the player’s object before they can continue on their way towards Player1.

If this is the case, you can fix it by having a player’s bullets ignore itself. I just did a quick Google search and found this old thread that describes one way of doing it. Try that and see how it works for you.

2 Likes

Thank you very much for the advice. I was able to condense the 2 scripts into one script which made some tasks easier. I was able to fix the bullet instantiation problem by using a ready made script from a tutorial and made some tweaks to suit my game better.

Also, thanks for noticing the extra bit of effort I put into asking the question. Having a more detailed description of the problem increases the chance of people replying.

1 Like

Awesome! Except I would be remiss if I didn’t strongly suggest that you go through the code you found line by line and try to understand exactly what it’s doing. That way, when you run into a problem in the future, you’ll be able to figure out why it’s happening!

Absolutely! Not only that, but sharing the solution you arrived at, thanking people, and even Liking posts is a great way to build a bond with the community and encourage people to continue to help you! Well done!