Search Unity

Space Shooter Enemy Spawn Bug

Discussion in 'Community Learning & Teaching' started by BlackPipe, May 15, 2015.

Thread Status:
Not open for further replies.
  1. BlackPipe

    BlackPipe

    Joined:
    May 15, 2015
    Posts:
    3
    Hello everyone,
    I've completed the Space Shooter Project(https://unity3d.com/learn/tutorials/projects/space-shooter) yesterday and decided to take it a bit further by adding the included Enemy Ships and different kinds of Asteroids to the game.
    My problem lies with the way my Enemy Ships spawn. I've taken a look at the "Evasive Maneuver" script that's included and replicated it, trying to figure out what does what.
    What happens is that when my ships spawn, they appear somewhere inside my playing area, not where they're supposed to off-screen. I tried disabling parts of the script to find out where the problem is, and it's got something to do with the Vector3 position of the object in FixedUpdate()
    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class EvasiveManeuver : MonoBehaviour {
    5.     public Boundary boundary;
    6.     public float tilt;
    7.     public float dodge;
    8.     public float smoothing;
    9.     public Vector2 startWait;
    10.     public Vector2 maneuverWait;
    11.     public Vector2 maneuverTime;
    12.  
    13.     private float currentSpeed;
    14.     private float targetManeuver;
    15.  
    16.  
    17.     void Start () {
    18.         currentSpeed = GetComponent<Rigidbody> ().velocity.z;
    19.         StartCoroutine (Evade ());
    20.     }
    21.  
    22.     IEnumerator Evade() {
    23.         yield return new WaitForSeconds (Random.Range (startWait.x, startWait.y));
    24.         while (true) {
    25.             targetManeuver = Random.Range(0, dodge) * -Mathf.Sign (transform.position.x);
    26.             yield return new WaitForSeconds(Random.Range (maneuverTime.x, maneuverTime.y));
    27.             targetManeuver = 0;
    28.             yield return new WaitForSeconds(Random.Range(maneuverWait.x, maneuverWait.y));
    29.         }
    30.     }
    31.  
    32.     void FixedUpdate () {
    33.         float newManeuver = Mathf.MoveTowards (GetComponent<Rigidbody>().velocity.x, targetManeuver, smoothing * Time.deltaTime);
    34.         GetComponent<Rigidbody>().velocity = new Vector3 (newManeuver, 0.0f, currentSpeed);
    35.         GetComponent<Rigidbody>().position = new Vector3 (
    36.             Mathf.Clamp (GetComponent<Rigidbody> ().position.x, boundary.xMin, boundary.xMax),
    37.             0.0f,
    38.             Mathf.Clamp (GetComponent<Rigidbody> ().position.x, boundary.zMin, boundary.zMax)
    39.         );
    40.         GetComponent<Rigidbody>().rotation = Quaternion.Euler (0.0f, 0.0f, GetComponent<Rigidbody>().velocity.x * -tilt);
    41.     }
    42. }
    43.  
    I'm guessing it's got something to do with the Boundary-Values (boundary.xMin, boundary.xMax etc), more specifically the z-Values. When i set the position-z-Value to something fixed like 20 the ship just stays fixed in that position (understandably of course)
    Here are the public values I've set in the editor:
    http://imgur.com/5VTmaj1

    Something else I've noticed when letting the game run a bit longer with ships on-screen is that they only dodge in a diagonal ~45° angle.

    I'm really not sure why this happens... I'd appreciate any help/hints towards a solution :)
     
    Last edited: May 15, 2015
  2. renaissanceCoder1

    renaissanceCoder1

    Joined:
    Apr 8, 2015
    Posts:
    127
    Have you tried increasing your boundary threshholds? They look a little limiting.
     
  3. BlackPipe

    BlackPipe

    Joined:
    May 15, 2015
    Posts:
    3
    Yeah, I have. It's a pretty small scene which is why they're so limiting.
    Something to mention: the enemy ships are spawned by a seperate script (along with asteroids) and are supposed to spawn off-screen and move along the z-Axis. The asteroids spawn fine, but the ships just appear out of nowhere.

    I've decided to lean pretty heavily on the finished scene that's included in the assets for the tutorial, and I've literally got the EXACT same Enemy Ship Component, when i use mine, they spawn offscreen but stay there and get destroyed by asteroirds, when i use the one from the finished scene they work fine...
     
  4. renaissanceCoder1

    renaissanceCoder1

    Joined:
    Apr 8, 2015
    Posts:
    127
    They spawn but stay there? So they aren't moving? The first thing I would do is Debug.Log the currentSpeed variable - since that is what is propelling your object on the z-axis. Make sure that isn't getting zeroed out anywhere.

    From the looks of it, you create a private currentSpeed variable and set it to velocity.z. When the ship first spawns, are you setting the velocity to anything? If not, that is likely your problem because currentSpeed is always 0.
     
  5. BlackPipe

    BlackPipe

    Joined:
    May 15, 2015
    Posts:
    3
    well there's a Mover-script attached to the ship that is supposed to set their velocity (same mover script is attached to the Asteroids that move fine).
    Code (csharp):
    1.  
    2. using UnityEngine;
    3. using System.Collections;
    4.  
    5. public class Mover : MonoBehaviour {
    6.     public float speed;
    7.     void Start() {
    8.         GetComponent<Rigidbody>().velocity = transform.forward * speed;
    9.     }
    10.  
    11. }
    12.  
    You were right about the currentSpeed-Issue, it was always at 0. I've fixed the issue by simply removing the currentSpeed variable all together and setting velocity.z to -5 in the velocity Vector3 set in FixedUpdate().
    Everything works fine now, but I still fail to realize why exactly the original EvasiveManeuver script doesnt work in my scene, but it does in the Done_Scene that's included in the project :|
    Heres the "new" EvasiveManeuver:
    Code (csharp):
    1.  
    2. using UnityEngine;
    3. using System.Collections;
    4.  
    5. public class EvasiveManeuver : MonoBehaviour
    6. {
    7.     public Boundary boundary;
    8.     public float tilt;
    9.     public float dodge;
    10.     public float smoothing;
    11.     public Vector2 startWait;
    12.     public Vector2 maneuverTime;
    13.     public Vector2 maneuverWait;
    14.  
    15.     //private float currentSpeed;
    16.     private float targetManeuver;
    17.  
    18.     void Start ()
    19.     {
    20.         //GetComponent<Rigidbody> ().velocity = transform.forward * -5;
    21.         StartCoroutine(Evade());
    22.     }
    23.  
    24.     IEnumerator Evade ()
    25.     {
    26.         yield return new WaitForSeconds (Random.Range (startWait.x, startWait.y));
    27.         while (true)
    28.         {
    29.             targetManeuver = Random.Range (1, dodge) * -Mathf.Sign (transform.position.x);
    30.             yield return new WaitForSeconds (Random.Range (maneuverTime.x, maneuverTime.y));
    31.             targetManeuver = 0;
    32.             yield return new WaitForSeconds (Random.Range (maneuverWait.x, maneuverWait.y));
    33.         }
    34.     }
    35.  
    36.     void FixedUpdate ()
    37.     {
    38.         float newManeuver = Mathf.MoveTowards (GetComponent<Rigidbody>().velocity.x, targetManeuver, smoothing * Time.deltaTime);
    39.         GetComponent<Rigidbody>().velocity = new Vector3 (newManeuver, 0.0f, -5);
    40.         GetComponent<Rigidbody>().position = new Vector3 (
    41.             Mathf.Clamp(GetComponent<Rigidbody>().position.x, boundary.xMin, boundary.xMax),
    42.             0.0f,
    43.             Mathf.Clamp(GetComponent<Rigidbody>().position.z, boundary.zMin, boundary.zMax)
    44.             );
    45.      
    46.         GetComponent<Rigidbody>().rotation = Quaternion.Euler (0, 0, GetComponent<Rigidbody>().velocity.x * -tilt);
    47.     }
    48. }
    49.  
    Is it because both the currentSpeed-variable and the velocity are set in the Start() function in EvasiveManeuver and Mover? Maybe the EvasiveManeuver Start() function was executed first which is why currentSpeed was set to 0?

    Edit: So it also worked when i simply moved
    Code (csharp):
    1. currentSpeed = GetComponent<Rigidbody>().velocity.z;
    to FixedUpdate(), so i guess the problem really was EvasiveManeuver being executed before the Mover?
    Is there any way to set execution orders for scripts to avoid stuff like this?
     
    Last edited: May 16, 2015
  6. renaissanceCoder1

    renaissanceCoder1

    Joined:
    Apr 8, 2015
    Posts:
    127
    You are correct about both those lines of code being in Start(). Remember if you want to be sure something is executed before anything else, you can use the Awake() event function. It is always executed before any Start() code.

    I have created a tutorial on Unity Event functions specifically. If you have any doubts about when to use Awake(), Start(), FixedUpdate(), Update(), or LateUpdate().

    If you are interested you can check it out here: Unity Event Functions
     
    theANMATOR2b likes this.
  7. Adam-Buckner

    Adam-Buckner

    Joined:
    Jun 27, 2007
    Posts:
    5,664
    Glad you seem to have this working. If you have any more questions, please use the official thread in the sticky section of this forum.
     
Thread Status:
Not open for further replies.