UNIT SPACE SHOOTER....The shot spawn stays at fixed location and doesn't move with ship.

Hey guys, 

I'm at the "Shooting Shots" part of the Unity Space shooter. 

https://www.youtube.com/watch?v=kX0hnOS1QQQ&list=PLX2vGYjWbI0RibPF7vixmr4x8ONJX-mNd

After following the prompts... I can now successfully move my player and shoot.

The only problem is that the shot spawn does not travel WITH the ship, even though it is a child of the ship and located right in front of it. 

Basically the shot emirates from the centre of the screen, regardless of where the ship is. 


 Any advice? 




The player controller script is 


using UnityEngine;
using System.Collections;

[System.Serializable]
public class Boundary
{
    public float xMin, xMax, zMin, zMax;
}

public class PlayerController : MonoBehaviour {

    public float speed;
    public float tilt;
    public Boundary boundary;

    public GameObject shot;
    public GameObject shotSpawn;
    public float fireRate;
    private float nextFire;
    private GameObject shotFired;
    void Update ()
    {
        if (Input.GetButton("Fire1") && Time.time > nextFire)
        {
            shotFired = Instantiate(shot) as GameObject;

            nextFire = Time.time + fireRate;

            shotFired.transform.position = shotSpawn.transform.position;

        }
    }
    void FixedUpdate()
    {
        float moveHorizontal = Input.GetAxis("Horizontal");
        float moveVertical = Input.GetAxis ("Vertical");

        Vector3 movement= new Vector3(moveHorizontal,0.0f,moveVertical);
        GetComponent<Rigidbody>().velocity = movement * speed;

        GetComponent<Rigidbody>().position = new Vector3 (
            Mathf.Clamp (GetComponent<Rigidbody>().position.x, boundary.xMin, boundary.xMax),
            0.0f,
            Mathf.Clamp (GetComponent<Rigidbody>().position.z, boundary.zMin, boundary.zMax)
        );

        GetComponent<Rigidbody> ().rotation = Quaternion.Euler (0.0f, 0.0f, GetComponent<Rigidbody> ().velocity.x * -tilt);

    }

}

  • Jonathan Gonzalez(jgonzalez) replied

    According to your script that's exactly what it should be doing. In your script you're instantiating the shot game object at the location of where the spawn shot is at. If you want the shot to originate from the ship, make the spawn shot a child of the ship. I can see from your screenshot that it's a separate object and not part of the ship hierarchy. I assume that's the only issue. 

    A few things I would change in your script for ease of use and to cut down a few lines/words. First, since the shot spawn is just used for positioning use it as a Transform. 

    Transform shotSpawn;

    That way you can just say shotSpawn.position instead of shotSpawn.transform.position. If you are using it as a GameObject somewhere else then disregard this. 

    You can also simplify the Instantiation lines to one line:

    Instantiate(shot, shotSpawn.position, Quaternion.identity) as GameObject;

    With that line you're instantiating your shot and positioning it at the shotSpawn position. The Quaternion.identity part just means you're not rotating the shot from it's original rotation. If you wanted to rotate it to the same rotation as the shotSpawn you'd write instead shotSpawn.rotation in that spot. 

    If you have any other questions let me know. 


  • gauntlit replied

    Hi John!

    Yeah, I guess I missed that part. I thought it was a child but it wasn't. Thanks for pointing it out!

    One thing I find very confusing about coding is that there's casual phrases about doing stuff... However I'm at the point where I'm pretty much just writing the exact lines into the exact spaces.  Most of what I do is just copy and paste, because the general concepts here mostly fly right over my head. 

    I'm not sure how to "use" the shot spawn as a transform, for instance... what code do I write to "use" it as a transform. 

    I assume that AFTER I use shot spawn as transform then I erase shotSpawn.tranform.position; and replace it with shotSpawn.position. 

    However... This confuses me because it seems your next suggestion is to replace the "Instantiation lines" entirely with Instantiate(shot, shotSpawn.position, Quaternion.identity) as GameObject;

    But what exactly ARE the Instantiation lines?  Are they all the lines in the blue circle?  including the line that I replaced? 


    Basically, I have a hard time understanding the basic phrases here...Is there perhaps a resource for learning how to code that provides a general overview on basic phrases and how to do stuff?  

  • Jonathan Gonzalez(jgonzalez) replied

    I'll explain this a bit further. The "shotSpawn" is used as a position of where the "shot" should originate. Currently in your script you are using it as a GameObject which is fine, but not entirely necessary. In your script you have "shotSpawn.transform.position", which is essentially saying "Use the transform of this game object, then use the position of that transform". At the top of your script you have:

    public GameObject shotSpawn;

    I would change it to 

    public Transform shotSpawn;

    Since you're just using this to get position information, you can use it as a transform directly and just write out "shotSpawn.position" instead. You don't need to do this, it just simplifies things a bit. 


    The Instantiation lines are those where you instantiate the object and then move that instantiated object to a new location. Technically in your script it's just one line, but the moving of the object can also be added into one line. This is what I'm, referring to:

    shotFired = Instantiate(shot) as GameObject;
     shotFired.transform.position = shotSpawn.transform.position;


    Here you are creating the object in the game (instantiating), then you are setting it's position to the position of shotSpawn. This can all be done at once when it is created as such:

    Instantiate(shot, shotSpawn.position, Quaternion.identity) as GameObject;

    Instantiate is a method that can contain multiple parameters. In your script you're just using the very basic version it by saying you want to instantiate an object, but typically when you use instantiate you're creating something and placing it somewhere specific in the game world. So this is what you'd use:

    Instantiate(YourPrefab, Position, Rotation);

    First you instantiate something, usually a prefab, then the other two allow you to determine at what position, and what rotation that instantiated object should be. There are more parts to that method, but that's mostly what you'll use. 

    I know it can be tough to understand this stuff at times, I always like to know the what and why of these mechanics. If you'd like me to explain further let me know. 

    Also if you haven't already I'd recommend this course: https://cgcookie.com/course/c-bootcamp-for-unity I'll be remaking it in the near future but it's a good starting point for learning C#.