Search Unity

Space Shooter Tutorial Q&A

Discussion in 'Community Learning & Teaching' started by Adam-Buckner, Mar 26, 2015.

  1. Yeoli_Livunts

    Yeoli_Livunts

    Joined:
    Jul 20, 2015
    Posts:
    7
    *Edit*
    Ok sir, I have studied Switch Statements, added my Switch and cleaned up all those if else statements. I also added an update function to check for the int shipDestroyed to reach 4, & then end the game. But I'm still doing something wrong because the game is not ending.:confused:

    Obviously I'm still wrong, Thank you for your help and getting me to this current point. Can you look at my script and tell me if I'm at least using the switch the correct way. I am not getting any more error messages BTW.

    Thank you again Adam. You are awesome!


    Code (CSharp):
    1. public class DestroyByContact : MonoBehaviour
    2. {
    3.     public GameObject explosion;
    4.     public GameObject playerExplosion;
    5.     public int scoreValue;
    6.  
    7.     private enum PlayerDestroyed
    8.     {
    9.         p1Destroyed,
    10.         p2Destroyed,
    11.         p3Destroyed,
    12.         p4Destroyed      
    13.     }
    14.  
    15.     private GameController gameController;
    16.     private PlayerDestroyed playerDestroyed = 0;
    17.     private int shipDestroyed = 0;
    18.  
    19.     void Start ()
    20.     {
    21.         GameObject gameControllerObject = GameObject.FindGameObjectWithTag ("GameController");
    22.         if (gameControllerObject != null)
    23.         {
    24.             gameController = gameControllerObject.GetComponent <GameController>();
    25.         }
    26.         if (gameController == null)
    27.         {
    28.             Debug.Log ("Cannot find 'GameController' script");
    29.         }
    30.     }
    31.  
    32.     void OnTriggerEnter (Collider other)
    33.     {
    34.         if (other.tag == "Boundary" || other.tag == "Enemy")
    35.         {
    36.             return;
    37.         }
    38.  
    39.         if (explosion != null)
    40.         {
    41.             Instantiate(explosion, transform.position, transform.rotation);
    42.         }
    43.  
    44.         if (other.tag == "Player1" || other.tag == "Player2" || other.tag == "Player3" || other.tag == "Player4")
    45.         {
    46.             Instantiate(playerExplosion, other.transform.position, other.transform.rotation);
    47.             playerDestroyed++;
    48.         }  
    49.  
    50.         switch (playerDestroyed)
    51.         {
    52.             case PlayerDestroyed.p1Destroyed:
    53.                 shipDestroyed++;
    54.                 break;
    55.             case PlayerDestroyed.p2Destroyed:
    56.                 shipDestroyed++;
    57.                 break;
    58.             case PlayerDestroyed.p3Destroyed:
    59.                 shipDestroyed++;
    60.                 break;
    61.             case PlayerDestroyed.p4Destroyed:
    62.                 shipDestroyed++;
    63.                 break;
    64.         }
    65.  
    66.         gameController.AddScore(scoreValue);
    67.         Destroy (other.gameObject);
    68.         Destroy (gameObject);
    69.     }
    70.  
    71.     void Update ()
    72.     {
    73.         if (shipDestroyed >= 4)
    74.         {
    75.             gameController.GameOver();
    76.         }
    77.     }
    78. }
     
    Last edited: Nov 17, 2015
  2. jlopezfdez

    jlopezfdez

    Joined:
    Nov 15, 2015
    Posts:
    2
    Hi, and regards from Spain,

    There is a little correction to do in the source code:

    at 'DestroyByContact' class, the function 'OnTriggerEnter' must be corrected to not give '10' points for free just when the player crashs with an asteroid:

    Original source code:

    Code (CSharp):
    1.         if (other.tag == "Player")
    2.         {
    3.             Instantiate(playerExplosion, other.transform.position, other.transform.rotation);
    4.             gameController.GameOver();
    5.         }
    6.      
    7.         gameController.AddScore(scoreValue);
    8.  

    Possible correction:


    Code (CSharp):
    1.       if (other.tag == "Player")
    2.         {
    3.             Instantiate(playerExplosion, other.transform.position, other.transform.rotation);
    4.             gameController.GameOver();
    5.         }
    6.         else
    7.         {
    8.             gameController.AddScore(scoreValue);
    9.         }
    10.  
     
    Last edited: Nov 15, 2015
  3. Fulacine

    Fulacine

    Joined:
    Nov 16, 2015
    Posts:
    2
    Thanks for the tutorial.
    Your tutorial's are the best I have ever seen.
    I added a second laser to my ship but when they both strike an asteroid at the same time the score goes up by
    double the increment.
    I haven't figured out a solution to this issue yet any idea's?
    I added a new public laser gameobject and separated the two from each other.
    so they are not the same object.
    in fact when one of the laser misses the astroid it continues on and will destroy another asteroid if it come into
    contact with it.
     
  4. GameBlaster

    GameBlaster

    Joined:
    Nov 14, 2015
    Posts:
    11
    Hey thank you so much for responding to our questions so quickly .. Unity and the Unity community are the best!
     
  5. Mancu37

    Mancu37

    Joined:
    Nov 17, 2015
    Posts:
    7
    Hi, I'm writting a space shooter tutorial in spanish based on official unity space shooter tutorial. Here is the link


    Thanks! :)
     
  6. fabking

    fabking

    Joined:
    Aug 4, 2015
    Posts:
    1
    Hi great tutorial.
    I noticed that if the rigidbody must be first on the list in the Start function otherwise the code doesn't work properly .
    I was working on the extended space shooter tutorial and couldn't get the enemy ship do dodge and after checking codes from the finished versions and mine I realised that rb = GetComponent<Rigidbody>(); must be on the first line as I had any of the other 2 lines before this code it wouldnt work.
    Does the order of the Start function really matter?
    Code (CSharp):
    1.  
    2. void Start ()
    3. {
    4.   rb = GetComponent<Rigidbody>();
    5.   currentSpeed = rb.velocity.z;
    6.   StartCoroutine (Evade());
    7.     }
     
  7. Adam-Buckner

    Adam-Buckner

    Joined:
    Jun 27, 2007
    Posts:
    5,664
    For simplicity, you may want to just add the items to the list of hazards in the ratio you want them in your game. You could add 5 simple asteroids, 3 medium asteroids, 1 difficult asteroid, 2 easy enemies and 1 hard enemy and you'll get them picked randomly in that ratio - as each slot has an equal chance of spawning.

    If you create a second spawner, second controller or use spawn waits, you'll have to change some of the (admittedly overly simple) base game mechanics. Currently all items are spawned regularly and move at the same speed. This means that hazards can never bump into each other. If you by-pass this simple mechanic, you will have to work through your game to make sure it works correctly.
     
  8. Adam-Buckner

    Adam-Buckner

    Joined:
    Jun 27, 2007
    Posts:
    5,664
    As you move orward in your coding, be aware that public variables are not recommended unless absolutely necessary. TBH, we over use public variables in our lessons to keep them simple to understand. Having a script talking directly to a an other script is something called a dependency. The two scripts depend on each other or are coupled together.

    At this stage in your development: Do not worry about it! But be aware that as you move into more and more complicated and complex games, you will be looking for tools to remove or reduce the number of dependencies in your games.
     
  9. Adam-Buckner

    Adam-Buckner

    Joined:
    Jun 27, 2007
    Posts:
    5,664
    That's ok. I undeleted it. Not to show you in a bad light, as it's an easy mistake, but so other people can read this and understand - first that it's and easy mistake, and two that it might help them find their error.
     
  10. Adam-Buckner

    Adam-Buckner

    Joined:
    Jun 27, 2007
    Posts:
    5,664
    Please see the relevant comment on the video (turn comments on) and please use the upgrade guide, which will lead you through changes in this project for Unity 5.
     
  11. Adam-Buckner

    Adam-Buckner

    Joined:
    Jun 27, 2007
    Posts:
    5,664
    So, this is a local (4 players, 1 keyboard, 1 game or 4 players, 4 controllers, 1 game) multiplayer game? You'll have to remind me as I've not followed this very closely.

    shipDestroyed++ is just advancing the enum?

    I'm confused by shipDestroyerd++ and playerDestroyed++

    What are you trying to do with these?

    I don't see code that is keeping track of each individual player, yet I see a complicated set of code keeping track of the number of players killed.

    If you just need to know the number of players killed, have an int.

    If you need to track each player, you'll need something that tracks each player.
     
    Yeoli_Livunts likes this.
  12. Adam-Buckner

    Adam-Buckner

    Joined:
    Jun 27, 2007
    Posts:
    5,664
    Ah - this was both simple and by design!

    Why not get 10 points for that last asteroid? You did destroy it.

    It destroyed you! But you destroyed it!

    10 pts.!
     
  13. Adam-Buckner

    Adam-Buckner

    Joined:
    Jun 27, 2007
    Posts:
    5,664
    Yes, multiple shots are beyond the scope of the original code.

    You will have to trap the collisions in the OnTriggerEnter function.

    Code (csharp):
    1. private bool destroyed = false;
    2.  
    3. void OnTriggerEnter()
    4. {
    5.      if (!destroyed)
    6.           {
    7.                destroyed = true;
    8.                // the rest of the code goes here
    9.                // this means you can only be destroyed once
    10.           }
    11. }
     
  14. Adam-Buckner

    Adam-Buckner

    Joined:
    Jun 27, 2007
    Posts:
    5,664
    Thank @OboShape who keeps things running when I'm busy (or ill - I'm ill today, but this time it's oddly taking me away from the main work I have to do, and allowing me (while I rest) to answer the forum).
     
  15. Adam-Buckner

    Adam-Buckner

    Joined:
    Jun 27, 2007
    Posts:
    5,664
    Yes, the order of code within a script can be very important.

    Within functions, code is read from the top to the bottom.

    In the case of the code you've posted, the logic is:
    • find a component on this GameObject called "Rigidbody" and assign it to the variable "rb".
    • take the object referenced in the variable "rb" and look for a value on "rb" that can be found in the "velocity" called "z" and assign it to the variable "current speed".
    • start a corouting called "Evade()".
    As the code is being read and executed from top to bottom, if you put the rb = GetComponent<Rigidbody>() last, then we will have a null reference exception on the first line, as the reference to rb will be null until the last line.

    It is worth noting that as functions are called by name, the order of the functions in the script is irrelevant. You could have:
    • Awake()
    • Start()
    • Update()
    • Evade()
    • GameOver()

    ... which I'd suggest as this order is vaguely in some form of execution order...

    But you could have:
    • GameOver()
    • Update()
    • Evade()
    • Awake()
    • Start()

    ... and as these are all called by name, will work just as well as the above order.

    This holds true for member declaring variables. There is no order required to the order of declaring member variable. For your working habits, it's probably best to have a system and keep to it, so thing are organized and don't get lost.

    Variables, however, that are declared within the scope of a function will follow the same top down order. You cannot use a local variable that has not yet been declared.
     
  16. Yeoli_Livunts

    Yeoli_Livunts

    Joined:
    Jul 20, 2015
    Posts:
    7
    Sorry about the limited details before.

    The game is a 1 player game that controls 4 different ships. The 4 ships are in a fixed position, and the player uses 1 keyboard to control all 4 ships at the same time. (I only "tagged" each ship "Player1", "2" and so on. Its actually only 1 player) When 1 ship is destroyed, play continues with the remaining ships, until each of the 4 ships are destroyed. At this point, I want to end the game. Ending the game is my issue.

    Initially I used bools to say when each tagged player was destroyed, because I had 4 different IF Statements. Once I posted that code, you told me to use a switch statement. At which point led me to learn a ton of great info about switch statements, but I just couldn't figure out how to make the switch statement work for this instance.

    Basically this is what I need. I need to end the game, after all 4 of the player's ships have been destroyed.

    This is what I've come up with, but it still isn't working for me.

    I have an int (shipDestroyed), starting at zero, and supposedly, one is being added (shipDestroyed++) when each ship (other.tag == "Player1", etc) is destroyed, or in the case that the code is written, the playerExplosion is Instantiated.

    At this point I have an Update function, with an IF statement inside checking for the int (shipDestroyed >= 4) to reach 4. At which point its calling for the game to end. I tested different numbers to have the IF statement checking for. For example: (shipDestroyed >= 0) ended the game immediately, and (shipDestroyed >= 1) ended the game when 1 of the ships were destroyed. But, (shipDestroyed >= 4) does nothing.

    Thank you again for your help

    Code (CSharp):
    1. public class DestroyByContact : MonoBehaviour
    2. {
    3.     public GameObject explosion;
    4.     public GameObject playerExplosion;
    5.     public int scoreValue;
    6.  
    7.     private GameController gameController;
    8.     private int shipDestroyed = 0;
    9.  
    10.     void Start ()
    11.     {
    12.         GameObject gameControllerObject = GameObject.FindGameObjectWithTag ("GameController");
    13.         if (gameControllerObject != null)
    14.         {
    15.             gameController = gameControllerObject.GetComponent <GameController>();
    16.         }
    17.         if (gameController == null)
    18.         {
    19.             Debug.Log ("Cannot find 'GameController' script");
    20.         }
    21.     }
    22.  
    23.     void OnTriggerEnter (Collider other)
    24.     {
    25.         if (other.tag == "Boundary" || other.tag == "Enemy")
    26.         {
    27.             return;
    28.         }
    29.  
    30.         if (explosion != null)
    31.         {
    32.             Instantiate(explosion, transform.position, transform.rotation);
    33.         }
    34.  
    35.         if (other.tag == "Player1" || other.tag == "Player2" || other.tag == "Player3" || other.tag == "Player4")
    36.         {
    37.             Instantiate(playerExplosion, other.transform.position, other.transform.rotation);
    38.             shipDestroyed++;
    39.         }
    40.  
    41.         gameController.AddScore(scoreValue);
    42.         Destroy (other.gameObject);
    43.         Destroy (gameObject);
    44.     }
    45.  
    46.     void Update ()
    47.     {
    48.         if (shipDestroyed >= 4)
    49.         {
    50.             gameController.GameOver();
    51.         }
    52.     }
    53. }
     
    Last edited: Nov 18, 2015
  17. Adam-Buckner

    Adam-Buckner

    Joined:
    Jun 27, 2007
    Posts:
    5,664
    When dealing with code, we are dealing with logic.

    What I tell people who say "I don't know how to program", I say when you're hungry and in a convenience store you can say "If I have enough money, I will buy that sandwich, if not, I will leave the store", you can program.

    You've progressed far beyond that with your code.

    Don't forget that there are many ways to skin your digital cat.

    If you don't care which ships are destroyed, you only care if all of the ships are destroyed, all you need to know is the number of ships destroyed. All you'd need is an int shipDestroyed = 0; and later a check that asks if (shipDestroyed >= 4)... and there you go.

    Now, there are ways you can make this a little more elegant.

    You can replace the hard coded number to check against with a public int shipCount; and then test if (shipDestroyed >= shipCount). This way you can expand or contract your ship count and adjust your game as you need.

    You should replace the code in Update () with a discreet check. Update will check this code every frame. You only need to check when there has been a collision. If this is in DestroyByContact then this Update is running on every hazard every frame! Not great for performance.

    Try creating a new function called something like CheckShips() (bad name, but hey, I'm tired), and then you can call this when there has been a collision. We don't care the rest of the time, as there is no possible way we could end the game without a collision. Moreover, you only need to know when there has been a collision with a player.
    Code (csharp):
    1.    int shipDestroyed = 0;
    2.    // public int shipCount; // (optional)
    3.  
    4.     void OnTriggerEnter (Collider other)
    5.     {
    6.         // code removed to simplify example
    7.         if (other.tag == "Player") // this could be if (other.CompareTag ("Player");
    8.         {
    9.             Instantiate(playerExplosion, other.transform.position, other.transform.rotation);
    10.             shipDestroyed++;
    11.             CheckShips ();
    12.         }
    13.         // code removed to simplify example
    14.     }
    15.  
    16.    void CheckShips ()
    17.    {
    18.       if (shipDestroyed >= 4)   // Or this could be: if (shipDestroyed >= shipCount)...
    19.          GameOver ();
    20.    }
    Now, you can note that I've removed all the tags except Player, as we don't care if the ships are numbered or not (or so it seems). We just care if they are a player controlled object - thus we only need one "Player" tag.

    Lastly, there are some more "clever" ways you can do this. If you were to put all of your ships into an array: public GameObject[] playerShips;, then you could just check details about the ship. This works better in you are deactivating the ships rather than destroying them. You could check the array to see if there are any active ships, and if there are, do nothing, but if all the ships are inactive, then end the game. If you were destroying the ships, you could use a List<T> (a generic list), and you could remove the ship from the list when it was destroyed, and when the list had a count of 0, you could end the game... there are a number of ways to do this sort of thing.

    I hope this helps a little.
     
    Yeoli_Livunts likes this.
  18. stanley_angelino

    stanley_angelino

    Joined:
    Nov 14, 2015
    Posts:
    11
    I'm having problem with the scripts. The script was "PlayerController". They say that there was an error. The error is "Assets/Scripts/PlayerController.cs(22,25): error CS1525: Unexpected symbol 'rigidbody'

    Here's my script:

    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;

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

    Vector3 movement = new Vector3 (moveHorizontal, 0.0f, moveVertical)
    rigidbody.velocity = movement * speed;

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

    rigidbody.rotation = Quaternion.Euler (0.0f, 0.0f, rigidbody.velocity.x * -tilt);
    }
    }
     
  19. stanley_angelino

    stanley_angelino

    Joined:
    Nov 14, 2015
    Posts:
    11
    The error is in the text "rigidbody.velocity = movement * speed"
     
  20. Adam-Buckner

    Adam-Buckner

    Joined:
    Jun 27, 2007
    Posts:
    5,664
    A few things...

    When posting code, please use code tags so we can read it.

    Please turn on annotations when viewing the videos, as all upgrade points are noted on the video using annotations.

    Please use the upgrade guide when running the stage shooter video tutorials in Unity 5.

    This is a well documented issue arising from the video bring made in version 4, and changes in version 5.
     
  21. johnleonard

    johnleonard

    Joined:
    Nov 15, 2015
    Posts:
    10
    I'm really new with Unity and i was hoping you could help me with some new code. i need to add an extra life to the player ship in Space shooter in the sense that the first and second collision with the asteroid wont destroy it. its more like having a life bar. first collision takes up 50 percent of the player life and so on.
     
  22. Adam-Buckner

    Adam-Buckner

    Joined:
    Jun 27, 2007
    Posts:
    5,664
    Well, I'm not in the habit of just giving out code. I'd rather help someone through finding the solution themselves. If you were to give it one stab, what would you try? Look at the code. Look at where the collision does its work. The try to add lives and a way to deduct them. This will require scripts to talk to each other.
     
  23. johnleonard

    johnleonard

    Joined:
    Nov 15, 2015
    Posts:
    10
    Here is the code so far and in this code, the player ship wont destroy even after 3 collisions with the asteroid. i was expecting it to destroy after the 3rd collision.

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class DestroyByContact : MonoBehaviour
    5. {
    6.     public GameObject explosion;
    7.     public GameObject playerExplosion;
    8.     public int scoreValue;
    9.     private GameController gameController;
    10.     int Health =6;
    11.     int Damage = 2;
    12.    
    13.  
    14.     void Start ()
    15.     {
    16.         GameObject gameControllerObject = GameObject.FindWithTag ("GameController");
    17.         if (gameControllerObject != null)
    18.         {
    19.             gameController = gameControllerObject.GetComponent <GameController>();
    20.         }
    21.         if (gameController == null)
    22.         {
    23.             Debug.Log ("Cannot find 'GameController' script");
    24.         }
    25.     }
    26.  
    27.     void OnTriggerEnter(Collider other)
    28.     {
    29.  
    30.         if (other.tag == "Boundary")
    31.         {
    32.             return;
    33.         }
    34.         Instantiate(explosion, transform.position, transform.rotation);
    35.  
    36.         if (other.tag == "Player")
    37.         {
    38.             TakeDamage();
    39.         }
    40.  
    41.         if (Health == 0) {
    42.  
    43.             Instantiate (playerExplosion, other.transform.position, other.transform.rotation);
    44.             Destroy (other.gameObject);
    45.             gameController.GameOver ();
    46.         }
    47.        
    48.  
    49.         Destroy (gameObject);
    50.         gameController.AddScore (scoreValue);
    51.     }
    52.  
    53.      public void TakeDamage()
    54.     {
    55.         Health -= Damage;
    56.     }
    57.  
    58.  
    59. }
    60.  
     
  24. Adam-Buckner

    Adam-Buckner

    Joined:
    Jun 27, 2007
    Posts:
    5,664
    This is the destroy by contact script and probably sits on every hazard in the game.

    The hazards don't need to have any control over the player's health. Some single thing needs to know the player's health, and this needs a way to lose health, probably sent from the hazard. This gets awkward because in the original game, the hazards drove all the interaction. Now either the gamecontroller or the playercontroller needs to control the health value, and end the game. The hazards need to send details to that object with the damage they do.

    Does this help?
     
  25. johnleonard

    johnleonard

    Joined:
    Nov 15, 2015
    Posts:
    10
    Uhmm not really, i mean there are a lot of code in the GameController and PlayerController which make things even more complicated and hazards sending details of the damage, waaw. Okay give me some time and i will see what i can do
     
  26. Adam-Buckner

    Adam-Buckner

    Joined:
    Jun 27, 2007
    Posts:
    5,664
    Basically, you'll need either the GameController or the PlayerController with the health variable and damage functions.

    I'd use the GameController, as this has the GameOver script on it, and the hazards already have a reference to it.

    Make the function that damages the player public, and have the hazards (DestroyByContact script) call the Damage function.

    Hazards will also need a variable to hold the amount of damage the hazard does, and pass that to the damage function - so the damage function will need a parameter to send damage. This means you could have asteroids that do a little damage, and enemy bolts that do a lot.
     
  27. johnleonard

    johnleonard

    Joined:
    Nov 15, 2015
    Posts:
    10

    here is my code so far like you suggested but its not working. The player ship is still destroyed one time on collision with the Asteroid.
    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class GameController : MonoBehaviour
    5. {
    6.     public GameObject player;
    7.     public GameObject hazard;
    8.     public Vector3 spawnValues;
    9.     public int hazardCount;
    10.     public float spawnWait;
    11.     public float startWait;
    12.     public float waveWait;
    13.  
    14.     public int Playerhealth = 6;
    15.     //public float resethealth = 5f;
    16.  
    17.  
    18.  
    19.     public GUIText scoreText;
    20.     private int score;
    21.  
    22.     public GUIText restartText;
    23.     public GUIText gameOverText;
    24.    
    25.     private bool gameOver;
    26.     private bool restart;
    27.     private bool playerdead;
    28.    
    29.     void Start ()
    30.     {
    31.         playerdead = false;
    32.         gameOver = false;
    33.         restart = false;
    34.         restartText.text = "";
    35.         gameOverText.text = "";
    36.  
    37.         score = 0;
    38.         UpdateScore ();
    39.         StartCoroutine (SpawnWaves ());
    40.     }
    41.  
    42.     void Update ()
    43.     {
    44.         if (restart)
    45.         {
    46.             if (Input.GetKeyDown (KeyCode.R))
    47.             {
    48.                 Application.LoadLevel (Application.loadedLevel);
    49.             }
    50.         }
    51.  
    52.         if (Playerhealth <= 0)
    53.         {
    54.             if (!playerdead)
    55.             {
    56.                 PlayerDying();
    57.             }
    58.             else
    59.  
    60.             {
    61.                 Playerdead();
    62.                 GameOver();
    63.             }
    64.         }
    65.     }
    66.  
    67.  
    68.    
    69.     IEnumerator SpawnWaves ()
    70.     {
    71.         yield return new WaitForSeconds (startWait);
    72.         while (true)
    73.         {
    74.             for (int i = 0; i < hazardCount; i++)
    75.             {
    76.                 Vector3 spawnPosition = new Vector3 (Random.Range (-spawnValues.x, spawnValues.x), spawnValues.y, spawnValues.z);
    77.                 Quaternion spawnRotation = Quaternion.identity;
    78.                 Instantiate (hazard, spawnPosition, spawnRotation);
    79.                 yield return new WaitForSeconds (spawnWait);
    80.             }
    81.             yield return new WaitForSeconds (waveWait);
    82.  
    83.             if (gameOver)
    84.             {
    85.                 restartText.text = "Press 'R' for Restart";
    86.                 restart = true;
    87.                 break;
    88.             }
    89.         }
    90.     }
    91.  
    92.     public void AddScore (int newScoreValue)
    93.     {
    94.         score += newScoreValue;
    95.         UpdateScore ();
    96.     }
    97.    
    98.     void UpdateScore ()
    99.     {
    100.         scoreText.text = "Score: " + score;
    101.     }
    102.  
    103.     public void GameOver ()
    104.     {
    105.         gameOverText.text = "Game Over!";
    106.         gameOver = true;
    107.     }
    108.  
    109.     public void PlayerDying()
    110.     {
    111.         playerdead = true;
    112.     }
    113.  
    114.     void Playerdead()
    115.     {
    116.         Destroy(gameObject);
    117.     }
    118.  
    119.     public void TakeDamage(int amount)
    120.     {
    121.         Playerhealth -= amount;
    122.     }
    123. }
    124.  
    125.  


    DestroyByContact;
    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class DestroyByContact : MonoBehaviour
    5. {
    6.     int damage = 0;
    7.     int minidamage = 2;
    8.     public GameObject explosion;
    9.     public GameObject playerExplosion;
    10.     public int scoreValue;
    11.     private GameController gameController;
    12.    
    13.  
    14.     void Start ()
    15.     {
    16.         GameObject gameControllerObject = GameObject.FindWithTag ("GameController");
    17.         if (gameControllerObject != null)
    18.         {
    19.             gameController = gameControllerObject.GetComponent <GameController>();
    20.         }
    21.         if (gameController == null)
    22.         {
    23.             Debug.Log ("Cannot find 'GameController' script");
    24.         }
    25.  
    26.    
    27.  
    28.     }
    29.  
    30.  
    31.  
    32.     void OnTriggerEnter(Collider other)
    33.     {
    34.  
    35.         if (other.tag == "Boundary")
    36.         {
    37.             return;
    38.         }
    39.         Instantiate(explosion, transform.position, transform.rotation);
    40.  
    41.         if (other.tag == "Player")
    42.         {
    43.             Instantiate (playerExplosion, other.transform.position, other.transform.rotation);
    44.             //gameController.GameOver();
    45.         }
    46.  
    47.        // Destroy(other.gameObject);
    48.         Destroy (gameObject);
    49.         gameController.AddScore (scoreValue);
    50.     }
    51.  
    52.     void DamageDone()
    53.     {
    54.        
    55.         int Damage = damage + minidamage;
    56.         gameController.TakeDamage(Damage);
    57.  
    58.     }
    59.  
    60. }
    61.  
    62.  
    63.  
     
  28. UAR777

    UAR777

    Joined:
    Jul 2, 2013
    Posts:
    35
    Hi everyone. I'm working my way through the space shooter tutorial but have run into an unexpected problem.
    When shooting bolts they don't get destroyed from exit of the bounding box, but instead are destroyed when about 8 units in front of the ship no matter where it moves. I have have thoroughly checked the code and bounding box yet can't seem to find any fault. Any ideas? thanks.
     
  29. Adam-Buckner

    Adam-Buckner

    Joined:
    Jun 27, 2007
    Posts:
    5,664
    Is it possible you have "use gravity" active on the bolt's rigidbody?
     
  30. UAR777

    UAR777

    Joined:
    Jul 2, 2013
    Posts:
    35
    That's it! Thanks for that.
     
  31. Adam-Buckner

    Adam-Buckner

    Joined:
    Jun 27, 2007
    Posts:
    5,664
    A few things:

    First, I would definitely move this code out of Update and into it's own function, like I mentioned above:
    Code (csharp):
    1.         if (Playerhealth <= 0)
    2.         {
    3.             if (!playerdead)
    4.             {
    5.                 PlayerDying();
    6.             }
    7.             else
    8.  
    9.             {
    10.                 Playerdead();
    11.                 GameOver();
    12.             }
    13.         }
    Now, as this is running on only one GameObject, it's much more performant than running it on every instantiated hazard. However, it is still running every frame, and there is no need to do that. In this game, there will be no impact having the code in Update, but keeping unnecessary code out of Update is a good habit to get into. Just to be clear, this code will work here in Update, it's just not efficient.

    Your variables Playerhealth, (resethealth) and playerdead don't follow the normal conventions of making variables camelCase with the first letter lowercase, and then Capitalizing each "new word" after that. Normally, by convention, these variables should be: playerHealth, resetHealth and playerDead.

    Now, to the meat of the code...

    Coding is a lot like wiring:
    588_cable-HDMI-colores-hilos.jpg wire_harness_with_color_coded_pvc_insulation.jpg wiring_diagram_simple.gif wiring1.jpg

    Logic flows through code a lot like electricity through wires, and depending upon what functions that are being called and the content within these functions, logic can be affected a lot like the switches and transistors in wiring.

    • We can trace the path of electricity in a circuit (especially if we have a good circuit diagram).
    • We should be able to trace the path of our logic in our code.

    Our logic will flow through our scripts in a determined order.

    Here is the order that Unity uses events:
    http://docs.unity3d.com/Manual/ExecutionOrder.html

    Our logic will enter our scripts in only a few possible places (this is not an exhaustive list, but will give the idea):
    • Startup Events called by Unity: Awake, OnEnable, Start, ...
    • Regular Loop Events: Update, FixedUpdate, LateUpdate, ...
    • In-game events: OnTriggerEnter, OnCollisionEnter, OnBecameVisible, ...
    • Custom Public Functions: GameOver, TakeDamage, etc...

    When trying to solve a problem in our script we need to follow the logic step by step and see what it should be doing and then find where it falls off the rails.

    Model trains are also another good analogy!

    19thomas-600.jpg

    Our logic is on a track, and we have to find where we've opened a switch for the train, sending it onto track that is damaged or non-existent.

    In your GameController:

    • the variables are defined at the top and this is done during compilation (before the game even starts).
    • Start sets the values for a number of the variables
    • every frame in Update, the code checks for restart = true and Playerheath <= 0
    • every loop of the co-routine, SpawnWaves spawns a new hazard and checks for gameOver
    • AddScore is a new entry point and is called by another script
    • UpdateScore is called by AddScore
    • GameOver is called from the check in the Update() loop.
    • PlayerDying sets the boolean variable playerdead to true. Hmm... What is this function actually doing?
    • Playerdead destroys the current GameController GameObject. Is this really what we want to do? Remember the shorthand reference gameObject points to the GameObject that the current script is attached to. Destroy(gameObject) will destroy this GameObject. (Look up Destroy in the scripting reference for more details). Destroy will destroy exactly whatever object you put into the parentheses! If we want to destroy the Player's GameObject, then we need to point Destroy to that GameObject with Destroy(player). This is pointing to the reference variable player, which should have a reference to the player - which is also a GameObject reference. If the player was a Transform, you would need Destroy(player.gameObject). In this example case, we would have a valid reference to the player as a Transform, and we use the automatic reference to find the player's GameObject with .gameObject.
    • TakeDamage reduced the Playerhealth by the amount, and is called from outside the class (presumably by the hazards with DestroyByContact)
    Follow the flow of logic and see if everything is working the way you expect it to. You have to look carefully at each detail and not make assumptions. It's easy to think in your mind "Now I destroy the player with Destroy(gameObject) as the Player is a GameObject", but when looking for errors you need to thing down to the last possible detail, and not skip over anything with a high level assumption. When you read in your code Destroy(gameObject), you must think exactly what is that gameObject representing?

    Following the flow of logic, I'm a bit concerned by this chunk when I look at it in detail:
    Code (csharp):
    1.  
    2.         if (Playerhealth <= 0)
    3.         {
    4.             if (!playerdead)
    5.             {
    6.                 PlayerDying();
    7.             }
    8.             else
    9.  
    10.             {
    11.                 Playerdead();
    12.                 GameOver();
    13.             }
    14.         }
    "If we have no health, but are not dead, set dead to be true, if we have no health and are dead, player is dead and game is over."

    What is this actually doing? Or should I be asking what are you trying to do here. If I follow the loop of logic, this only delays GameOver by one frame. Are you trying to put in a dying delay here? Or are you trying to do something different? Currently when Playerhealth reaches 0, we set PlayerDying to true and then the next frame, as this is true, we end the game... This seems odd.
     
    Yeoli_Livunts and OboShape like this.
  32. johnleonard

    johnleonard

    Joined:
    Nov 15, 2015
    Posts:
    10


    Thank you soo much for your response, actually that code was my first try And i wasn't trying to do something else. All i wanted to do is whenever Playerhealth reaches 0, it calls the playerdead func and ends the game. I removed that code which sets playerDying to true with the normal calling of playerdead func and game over still it wont work.
    PlayerDead this is meant to destroy our playership
     
  33. Adam-Buckner

    Adam-Buckner

    Joined:
    Jun 27, 2007
    Posts:
    5,664
    To simplify this (and looking back at my earlier comment) - In DestroyByContact, have something like this:
    Code (csharp):
    1. public int hazardImpactValue;
    ... and in OnTriggerEnter:
    Code (csharp):
    1.     if (other.CompareTag("Player")) {
    2.           gameController.HazardContact(hazardImpactValue);
    3.      }
    This way you can push all of the relevant code to the GameController.

    You will have to migrate things like the playerExplosion reference to the GameController script.

    In GameController.HazardContact, you can make all your decisions about what happens to your player if there is a hazard contact. Here you can deduct health points, check to see if the health is <=0, instantiate the player explosion, end the game... whatever...
     
  34. johnleonard

    johnleonard

    Joined:
    Nov 15, 2015
    Posts:
    10

    Thanks again Sir, here is my new code, it doesn't destroy the player and doesn't instantiate explosion. i think am missing something but still cant figure out what exctly

    GameCont script;
    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class GameController : MonoBehaviour
    5. {
    6.     public GameObject Player;
    7.     public GameObject hazard;
    8.     public Vector3 spawnValues;
    9.     public int hazardCount;
    10.     public float spawnWait;
    11.     public float startWait;
    12.     public float waveWait;
    13.  
    14.     public int Playerhealth = 6;
    15.     public GameObject playerExplosion;
    16.  
    17.     public GUIText scoreText;
    18.     private int score;
    19.  
    20.     public GUIText restartText;
    21.     public GUIText gameOverText;
    22.  
    23.     private bool gameOver;
    24.     private bool restart;
    25.    
    26.  
    27.     void Start()
    28.     {
    29.         gameOver = false;
    30.         restart = false;
    31.         restartText.text = "";
    32.         gameOverText.text = "";
    33.  
    34.         score = 0;
    35.         UpdateScore();
    36.         StartCoroutine(SpawnWaves());
    37.     }
    38.  
    39.     void Update()
    40.     {
    41.         if (restart)
    42.         {
    43.             if (Input.GetKeyDown(KeyCode.R))
    44.             {
    45.                 Application.LoadLevel(Application.loadedLevel);
    46.             }
    47.         }
    48.     }
    49.  
    50.  
    51.  
    52.     IEnumerator SpawnWaves()
    53.     {
    54.         yield return new WaitForSeconds(startWait);
    55.         while (true)
    56.         {
    57.             for (int i = 0; i < hazardCount; i++)
    58.             {
    59.                 Vector3 spawnPosition = new Vector3(Random.Range(-spawnValues.x, spawnValues.x), spawnValues.y, spawnValues.z);
    60.                 Quaternion spawnRotation = Quaternion.identity;
    61.                 Instantiate(hazard, spawnPosition, spawnRotation);
    62.                 yield return new WaitForSeconds(spawnWait);
    63.             }
    64.             yield return new WaitForSeconds(waveWait);
    65.  
    66.             if (gameOver)
    67.             {
    68.                 restartText.text = "Press 'R' for Restart";
    69.                 restart = true;
    70.                 break;
    71.             }
    72.         }
    73.     }
    74.  
    75.  
    76.     public void AddScore(int newScoreValue)
    77.     {
    78.         score += newScoreValue;
    79.         UpdateScore();
    80.     }
    81.  
    82.     void UpdateScore()
    83.     {
    84.         scoreText.text = "Score: " + score;
    85.     }
    86.  
    87.     public void GameOver()
    88.     {
    89.         gameOverText.text = "Game Over!";
    90.         gameOver = true;
    91.     }
    92.  
    93.     void playerDead()
    94.     {
    95.         Destroy(Player.gameObject);
    96.     }
    97.  
    98.      public void HazardContact(int amount)
    99.     {
    100.         int Currenthealth;
    101.         Currenthealth = Playerhealth - amount;
    102.    
    103.         if (Currenthealth <= 0)
    104.         {
    105.             Instantiate(playerExplosion, Player.transform.position, Player.transform.rotation);
    106.             playerDead();
    107.             GameOver();
    108.         }
    109.     }
    110. }

    DestroyByCont script;

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class DestroyByContact : MonoBehaviour
    5. {
    6.     public GameObject explosion;
    7.     public int scoreValue;
    8.     private GameController gameController;
    9.     public int hazardImpactValue = 2;
    10.  
    11.  
    12.     void Start()
    13.     {
    14.         GameObject gameControllerObject = GameObject.FindWithTag("GameController");
    15.         if (gameControllerObject != null)
    16.         {
    17.             gameController = gameControllerObject.GetComponent<GameController>();
    18.         }
    19.         if (gameController == null)
    20.         {
    21.             Debug.Log("Cannot find 'GameController' script");
    22.         }
    23.     }
    24.  
    25.  
    26.  
    27.     void OnTriggerEnter(Collider other)
    28.     {
    29.  
    30.         if (other.tag == "Boundary")
    31.         {
    32.             return;
    33.         }
    34.         Instantiate(explosion, transform.position, transform.rotation);
    35.  
    36.         if (other.CompareTag("Player"))
    37.         {
    38.             gameController.HazardContact(hazardImpactValue);
    39.  
    40.             //Instantiate(playerExplosion, other.transform.position, other.transform.rotation);
    41.             //gameController.GameOver();
    42.         }
    43.  
    44.         // Destroy(other.gameObject);
    45.         Destroy(gameObject);
    46.         gameController.AddScore(scoreValue);
    47.     }
    48.  
    49. }
     
  35. OboShape

    OboShape

    Joined:
    Feb 17, 2014
    Posts:
    836
    Morning @johnleonard,
    looking at your HazardContact function. you have Currenthealth here.
    every time this function is run/called it is recreating the Currenthealth variable and setting it to the value of player health minus the amount you passed in. so effectively only checking to see what the health would be like if you got hit. not doing actual damage to the players health directly.

    Code (CSharp):
    1.  public void HazardContact(int amount)
    2.    {
    3.        int Currenthealth;
    4.         Currenthealth = Playerhealth - amount;
    5.  
    6.        if (Currenthealth <= 0)
    7.        {
    8.            Instantiate(playerExplosion, Player.transform.position, Player.transform.rotation);
    9.             playerDead();
    10.             GameOver();
    11.        }
    12.    }
    I cant test at the mo as im still offshore on nighshift, but give this a go (fingers crossed)
    Code (CSharp):
    1.  public void HazardContact(int amount)
    2.    {
    3.       Playerhealth = Playerhealth - amount; // apply damage to players health
    4.  
    5.        if (Playerhealth <= 0)
    6.        {
    7.            Instantiate(playerExplosion, Player.transform.position, Player.transform.rotation);
    8.             playerDead();
    9.             GameOver();
    10.        }
    11.    }
     
  36. johnleonard

    johnleonard

    Joined:
    Nov 15, 2015
    Posts:
    10




    Perfect :D :D it worked it. thanks everyone and special thanks to Adams Buckner and Obo shape
     
  37. johnleonard

    johnleonard

    Joined:
    Nov 15, 2015
    Posts:
    10
    Also i will be adding more stuff to the spaceshooter game example the player health GUI slider bar to keep track of the health
     
  38. Adam-Buckner

    Adam-Buckner

    Joined:
    Jun 27, 2007
    Posts:
    5,664
    Yes, definitely... This is called scope.

    A variable created in a function will live and die within the scope of that function. Remember code is read from the top down, so each time the function is called, int Currenthealth; will create a new int variable and set it to a default value.

    If you want to use a "Current Health" value (not a bad idea) then you should create:
    Code (csharp):
    1. public int maxHealth; // (or starting health, or whatever - this is public so set it in the inspector
    2. private int currentHealth;
    3.  
    4. void Start ()
    5. {
    6.    currentHealth = maxHealth;
    7. }
    8.  
    9. public void HazardContact (int amount)
    10. {
    11.    currentHealth = currentHealth - amount;
    12.    if (currentHealth <=0)
    13.    {
    14.       // Code removed
    15.    }
    16. }
    The main reason for doing something like this, is if you later want to do something like add health with, say, a powerup. If this is the case then you could so something like:
    Code (csharp):
    1. currentHealth = currentHealth + amount;
    2. currentHealth = Mathf.Clamp(currentHealth, 0.0f, maxHealth);
    Arguably, you could make a powerup using a contact script and
     
    johnleonard likes this.
  39. KrypnodaStudios

    KrypnodaStudios

    Joined:
    Nov 23, 2015
    Posts:
    6
    I need some help, I am stuck at restricting the Ship from moving off the screen, I am new, and I have done all I can at fixing it.
    using UnityEngine;
    using System.Collections;

    public class PlayerController : MonoBehaviour
    {
    private Rigidbody rig;
    public float speed;
    public float xMin, xMax, zMin, zMax;

    void Start()
    {
    rig = GetComponent<Rigidbody> ();
    }
    void FixedUpdate()
    {
    float moveHorzontal = Input.GetAxis ("Horizontal");
    float moveVertical = Input.GetAxis ("Vertical");

    Vector3 movement = new Vector3 (moveHorzontal, 0.0f, moveVertical);
    rig.velocity = movement * speed;

    rig.position = new Vector3 (x, y, z)
    {
    Mathf.Clamp(rig.position.x, xMin, xMax),
    (0.0f);
    Mathf.Clamp(rig.position.z, zMin, zMax);
    }
    }
    }
    ;
     
  40. Adam-Buckner

    Adam-Buckner

    Joined:
    Jun 27, 2007
    Posts:
    5,664
    Can you please learn to use code tag properly?

    http://forum.unity3d.com/threads/using-code-tags-properly.143875/
     
  41. Adam-Buckner

    Adam-Buckner

    Joined:
    Jun 27, 2007
    Posts:
    5,664
    Do you have any errors in the console? I see that the last character in your paste is a semicolon (;) and if this is in the script, it could cause compile errors.

    This line is not correct:
    Code (csharp):
    1. rig.position = new Vector3 (x, y, z)
    You may want to go back and review the lesson and see what the code should be here. If the video doesn't help, you can compare your code with the code example on the lesson page. I would suggest, however, that you do review the lesson to find where you went off-lesson and see what should be done at this point.
     
  42. UAR777

    UAR777

    Joined:
    Jul 2, 2013
    Posts:
    35
    Hi. Could you clarify what's happening in the following DestroyByContact script. How does the script manage to check for the ship hitting the asteroid if the boundary is encompassing the asteroid?

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class DestroyByContact : MonoBehaviour
    5. {
    6.     public GameObject explosion;
    7.     public GameObject playerExplosion;
    8.  
    9.     void OnTriggerEnter(Collider other)
    10.     {
    11.         if (other.tag == "Boundary")
    12.         {
    13.             return;
    14.         }
    15.         Instantiate(explosion, transform.position, transform.rotation);
    16.         if (other.tag == "Player")
    17.         {
    18.             Instantiate(playerExplosion, other.transform.position, other.transform.rotation);
    19.             gameController.GameOver ();
    20.         }
    21.         Destroy(other.gameObject);
    22.         Destroy(gameObject);
    23.     }
    24. }
     
  43. Mancu37

    Mancu37

    Joined:
    Nov 17, 2015
    Posts:
    7
    Hi folks!, I've written the second space shooter tutorial in spanish! :)

     
    Yeoli_Livunts likes this.
  44. Adam-Buckner

    Adam-Buckner

    Joined:
    Jun 27, 2007
    Posts:
    5,664
    First, see my note about wiring and train tracks above. Then, following the wires in this code:

    An "OnTriggerEnter" message will be sent every time the Collider on the same GameObject as the DestroyByContact script touches another Trigger Collider for the first time - eg: when it "enters" the trigger.

    This code processes every OnTriggerEnter message.

    When the GameObject carrying a DestroyByContact script - let's just call this GameObject "The Hazard", even tho' it could be any object with this script attached - So when The Hazard comes in contact with the Boundary, the OnTriggerEnter function is called by the physics system and the physics system passes in the collider that has been touched as an argument. This collider will be the one attached to the Boundary, which is has the tag "Boundary". The code says if (other.tag == "Boundary") {return;}. Return will "return" the control of the code back to Unity and it's game loop, leave the function and won't execute any more code. So - when the Hazard touches the Boundary, nothing happens.

    Later in the game, the Hazard touches a bolt from the player's ship. The physics system calls OnTriggerEnter and passes in the collider attached to the bolt. The other.tag is not "Boundary" so the rest of the code is executed. An explosion is instantiated. Then the code tests if (other.tag == "Player"), which it is not, so the code block controlled by the if statement is not executed, and Unity continues executing the rest of the code. The other GameObject (the bolt) is destroyed, and then finally this GameObject (the Hazard) is destroyed. The code leaves the function and returns to where ever it was in the game loop before the OnTriggerEnter was called.

    In a third possible situation, the Hazard hit's the player, and all of the above paragraph happens, but this time the other.tag IS the player, so the code instantiates the player's explosion and invokes the method GameOver on the GameController.

    Does this makes sense?
     
  45. Adam-Buckner

    Adam-Buckner

    Joined:
    Jun 27, 2007
    Posts:
    5,664
    Fantastic!
     
  46. johnleonard

    johnleonard

    Joined:
    Nov 15, 2015
    Posts:
    10
    i made this health player convas and slider and it works perfectly. just i have to find a good position to put the health slider bar :D

    And here is the code;
    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3. using UnityEngine.UI;
    4.  
    5. public class GameController : MonoBehaviour
    6. {
    7.     public Slider healthSlider;
    8.     public GameObject Player;
    9.     public GameObject hazard;
    10.     public Vector3 spawnValues;
    11.     public int hazardCount;
    12.     public float spawnWait;
    13.     public float startWait;
    14.     public float waveWait;
    15.  
    16.     public int currenthealth;
    17.     public int Playerhealth = 6;
    18.     public GameObject playerExplosion;
    19.  
    20.     public GUIText scoreText;
    21.     private int score;
    22.  
    23.     public GUIText restartText;
    24.     public GUIText gameOverText;
    25.  
    26.     private bool gameOver;
    27.     private bool restart;
    28.    
    29.  
    30.     void Start()
    31.     {
    32.         gameOver = false;
    33.         restart = false;
    34.         restartText.text = "";
    35.         gameOverText.text = "";
    36.  
    37.         score = 0;
    38.         UpdateScore();
    39.         StartCoroutine(SpawnWaves());
    40.         currenthealth = Playerhealth;
    41.     }
    42.  
    43.     void Update()
    44.     {
    45.         if (restart)
    46.         {
    47.             if (Input.GetKeyDown(KeyCode.R))
    48.             {
    49.                 Application.LoadLevel(Application.loadedLevel);
    50.             }
    51.         }
    52.     }
    53.  
    54.  
    55.  
    56.     IEnumerator SpawnWaves()
    57.     {
    58.         yield return new WaitForSeconds(startWait);
    59.         while (true)
    60.         {
    61.             for (int i = 0; i < hazardCount; i++)
    62.             {
    63.                 Vector3 spawnPosition = new Vector3(Random.Range(-spawnValues.x, spawnValues.x), spawnValues.y, spawnValues.z);
    64.                 Quaternion spawnRotation = Quaternion.identity;
    65.                 Instantiate(hazard, spawnPosition, spawnRotation);
    66.                 yield return new WaitForSeconds(spawnWait);
    67.             }
    68.             yield return new WaitForSeconds(waveWait);
    69.  
    70.             if (gameOver)
    71.             {
    72.                 restartText.text = "Press 'R' for Restart";
    73.                 restart = true;
    74.                 break;
    75.             }
    76.         }
    77.     }
    78.  
    79.  
    80.     public void AddScore(int newScoreValue)
    81.     {
    82.         score += newScoreValue;
    83.         UpdateScore();
    84.     }
    85.  
    86.     void UpdateScore()
    87.     {
    88.         scoreText.text = "Score: " + score;
    89.     }
    90.  
    91.     public void GameOver()
    92.     {
    93.         gameOverText.text = "Game Over!";
    94.         gameOver = true;
    95.     }
    96.  
    97.     void playerDead()
    98.     {
    99.         Destroy(Player.gameObject);
    100.     }
    101.  
    102.      public void HazardContact(int amount)
    103.     {
    104.         currenthealth = currenthealth - amount;
    105.         healthSlider.value = currenthealth;
    106.    
    107.         if (currenthealth <= 0)
    108.         {
    109.             Instantiate(playerExplosion, Player.transform.position, Player.transform.rotation);
    110.             playerDead();
    111.             GameOver();
    112.         }
    113.     }
    114. }
     

    Attached Files:

  47. Adam-Buckner

    Adam-Buckner

    Joined:
    Jun 27, 2007
    Posts:
    5,664
    Great work!

    There are some tiny things...

    • In Start, I would keep SpawnWaves until last, as you want all your variables set before you kick off the coroutine. So, move currentHealth = playerHealth up one line.
    • Unless you want to call if from somewhere else, I don't think you need PlayerDead(). It's only one line. Might as well just replace the PlayerDead(); call with the Destroy(player.gameObject); and keep it to one line.
    • I would fix my camelCase and PascalCase usage. Variables are camelCase. Functions are PascalCase. The variable currenthealth should be currentHealth (camelCase). The function playerDead should be PlayerDead (PascalCase), but only if you keep it. The variable Player should be player (camelCase, but it's only one word).
    Again: Great work!
     
  48. johnleonard

    johnleonard

    Joined:
    Nov 15, 2015
    Posts:
    10

    Thank you :)
     
  49. PizzaPie

    PizzaPie

    Joined:
    Oct 11, 2015
    Posts:
    107
    Any suggestions why changing resolution in player->settings won't have any effect on my Sceene? o_O
    I ve skipped the part about Layers in tutorial(1) but i doupt that has anything to do with it...
    also compared Setting from Done Sceene and it seems they are the same.

    Unity v.5.2.1f1
     
    Last edited: Nov 24, 2015
  50. Adam-Buckner

    Adam-Buckner

    Joined:
    Jun 27, 2007
    Posts:
    5,664
    The scene or game view? To set the resolution of the scene view, use the resolution and aspect ratio pull down menu.
     
    PizzaPie likes this.