简体   繁体   中英

What code do I need for my Unity character to shoot the bullet correctly?

I am not new to programming, but I am new to C#. I am experienced in Python, Java, and HTML. My game is 2D I have a game where my character currently has to touch the enemy to kill it. Now I added code for shooting a bullet to kill the enemy. I also want the bullet to be shot if the spacebar is pressed. The character is supposed to a shoot bullet in either direction. I have taken my code from an example my professor gave me which was originally Javascript and I converted it to C#. Unity no longer supports Javascript. The example code he gave me was basically a rocket shooting as many bullets as I clicked (clicking the mouse shoots bullets) to eliminate an enemy, however the rocket in that example does not move. In my game, the character moves, so the bullet has to get the position of the character. What is the correct code for getting the character position and shooting a bullet correctly?

I tested my game with my current code. The bullet is being spit out of nowhere (from the bottom of my background wallpaper [smack in the middle of the bottom] to a little below the wallpaper). Not even from the character... Also, I added the Hit class script to my Bullet category in Unity.

Complete Camera Controller (no issues here at all)

using UnityEngine;
using System.Collections;

public class CompleteCameraController : MonoBehaviour {

    public GameObject player;       //Public variable to store a reference to the player game object


    private Vector3 offset;         //Private variable to store the offset distance between the player and camera

    // Use this for initialization
    void Start () 
    {
        //Calculate and store the offset value by getting the distance between the player's position and camera's position.
        offset = transform.position - player.transform.position;
    }

    // LateUpdate is called after Update each frame
    void LateUpdate () 
    {
        // Set the position of the camera's transform to be the same as the player's, but offset by the calculated offset distance.
        transform.position = player.transform.position + offset;
    }
}

Complete Player Control Class (If you read the comments in the code that say the "BULLET CODE", that's new code I have placed in the game for the bullets.

using UnityEngine;
using System.Collections;

//Adding this allows us to access members of the UI namespace including Text.
using UnityEngine.UI;

public class CompletePlayerController : MonoBehaviour
{

    public float speed;             //Floating point variable to store the player's movement speed.
    public Text countText;          //Store a reference to the UI Text component which will display the number of pickups collected.
    public Text winText;            //Store a reference to the UI Text component which will display the 'You win' message.

    private Rigidbody2D rb2d;       //Store a reference to the Rigidbody2D component required to use 2D Physics.
    private int count;              //Integer to store the number of pickups collected so far.
    Rigidbody2D bullet;
    float speed2 = 30f; //BULLET CODE



    // Use this for initialization
    void Start()
    {
        //Get and store a reference to the Rigidbody2D component so that we can access it.
        rb2d = GetComponent<Rigidbody2D> ();

        //Initialize count to zero.
        count = 0;

        //Initialze winText to a blank string since we haven't won yet at beginning.
        winText.text = "";

        //Call our SetCountText function which will update the text with the current value for count.
        SetCountText ();
    }

    //FixedUpdate is called at a fixed interval and is independent of frame rate. Put physics code here.
    void FixedUpdate()
    {
        //Store the current horizontal input in the float moveHorizontal.
        float moveHorizontal = Input.GetAxis ("Horizontal");

        //Store the current vertical input in the float moveVertical.
        float moveVertical = Input.GetAxis ("Vertical");

        Rigidbody2D bulletInstance; //BULLET CODE

        //Use the two store floats to create a new Vector2 variable movement.
        Vector2 movement = new Vector2 (moveHorizontal, moveVertical);

        //Call the AddForce function of our Rigidbody2D rb2d supplying movement multiplied by speed to move our player.
         rb2d.AddForce (movement * speed);

         if(Input.GetKeyDown(KeyCode.Space)&& Hit.hit == false) //BULLET CODE IN HERE
        {
            // ... instantiate the bullet facing right and set it's velocity to the right. 
            bulletInstance = Instantiate(bullet, transform.position, Quaternion.Euler(new Vector3(0,0,0)));
            bulletInstance.velocity = new Vector2(speed2, 0);
            bulletInstance.name = "Bullet";
        }







    }




    //OnTriggerEnter2D is called whenever this object overlaps with a trigger collider.
    void OnTriggerEnter2D(Collider2D other) 
    {
        //Check the provided Collider2D parameter other to see if it is tagged "PickUp", if it is...
        if (other.gameObject.CompareTag ("PickUp")) 
        {
            //... then set the other object we just collided with to inactive.
            other.gameObject.SetActive(false);

            transform.localScale += new Vector3(0.1f, 0.1f, 0);

            //Add one to the current value of our count variable.
            count = count + 1;

            //Update the currently displayed count by calling the SetCountText function.
            SetCountText ();
        }


    }

    //This function updates the text displaying the number of objects we've collected and displays our victory message if we've collected all of them.
    void SetCountText()
    {
        //Set the text property of our our countText object to "Count: " followed by the number stored in our count variable.
        countText.text = "Count: " + count.ToString ();

        //Check if we've collected all 12 pickups. If we have...
        if (count >= 12)
            //... then set the text property of our winText object to "You win!"
            winText.text = "You win!";
    }
}

Hit code. All code in this class is made for the bullet.

using UnityEngine;
using System.Collections;

public class Hit : MonoBehaviour 
{


    GameObject[] gameObjects;
    public static bool hit = false;

    void  Removal ()
    {

    gameObjects =  GameObject.FindGameObjectsWithTag("Bullet");

    for(var i= 0 ; i < gameObjects.Length ; i ++)
        Destroy(gameObjects[i]);
    }

    void  OnCollisionEnter2D ( Collision2D other  )
    {
        if(other.gameObject.name=="Bullet")
        {
            Removal();
            Destroy(gameObject);
            hit = true;

        }
    }
}

I see several issues with the code you wrote. as @Kyle Delaney suggested, I'd also highly recommend you check out the Unity Learn website, and go through several tutorials before moving through. I've highlighted a few issues below that may help solve your problem, but you could really benefit from changing your approach in the first place to avoid many of these issues. See below.

In your camera controller class, why not make the offset public so you can set it yourself in the inspector>

In Player controller class:

changed:

if (Input.GetKeyDown(KeyCode.Space)) //Shoot bullet
{
    // ... instantiate the bullet facing right and set it's velocity to the right. 
    Rigidbody2D bulletRB = Instantiate(bullet, transform.position, transform.rotation);
    bulletRB.AddForce(new Vector2(speed2,0), ForceMode2D.Impulse);
}

On a click, this instantiates the bullet prefab and sets its transform to copy the position and rotation of the player. It then adds a force to it to the right. You should avoid setting the velocity manually with rigidbodies, this can cause unwanted behaviour. Use the Addforce/addTorque methods instead. The ForceMode says to ignore its mass and set its velocity.

Then delete your Hit class, and replace with this Bullet class, which you drag onto the bullet prefab. Your player shouldn't be in charge of checking for bullet hits. that's the bullet's job. The player just launches the bullets and then the bullets do what bullets do. this just checks to see if the bullet hit anything, if so it destroys it. You can make this more complicated if you want. I would recommend using layers to determine which layers the bullet checks collisions with. You probably don't want bullets destroying your terrain. and you definitely don't want bullets destroying the player itself!

public class Bullet : MonoBehaviour
{

    private void OnCollisionEnter2D(Collision2D collision)
    {
        Destroy(collision.gameObject);
        Destroy(this.gameObject);
    }

}

Also you shouldn't need to set the name of the bullet, since your prefab bullet should already be named "bullet".

I hope this gets you started in the right direction. But based on your code, I HIGHLY recommend you work through the tutorials before continuing with any projects. The unity staff that make them are super helpful and the tutorials start off really simple but get really complicated fast, so you actually come away learning a ton!

Perhaps the problem has to do with the player's parent transform. You could try something like this to make sure the bullet has the right parent:

bulletInstance = Instantiate(bullet);
bulletInstance.transform.parent = transform.parent;
bulletInstance.transform.position = transform.position;
bulletInstance.velocity = new Vector2(speed2, 0);
bulletInstance.name = "Bullet";

If that doesn't work it may be worthwhile to check the player's Rect Transform to see where the anchors and pivot are. Perhaps the player's actual "position" coordinates aren't where you think they are.

Have you done the Space Shooter tutorial? It has a segment about shooting bullets .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM