Search Unity

Space Shooter Tutorial Q&A

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

  1. McNoguff

    McNoguff

    Joined:
    Sep 20, 2015
    Posts:
    9
    Thanks! And thank you for your continued efforts to help folks like me. I look forward to the edited live session as well.

    What I really like about your work so far is the "feel" -- so many tutorials produce content that doesn't feel fun when it's finished(a bowling game with bland physics, for example, seems to be the most common tutorial in existence). What I'm loving about Unity is the considerations you guys take in even the smallest training material to focus on the "fun," whether it's the tilt of the ship adding that little bit of juiciness or the mix of the overall audio.

    And it is -this- to which I'm referring when I mention best practices; Not merely the much-debated technical bp of development, but the unity-specific considerations when making a player controller, enemy mover et al. I might not recreate the exact process, per se, but the things you consider important tend to align nicely with my own philosophy and how I'd like to use the program! So seeing the logic -behind- decisions made, the results of which I can already see in the "Done_" directories, would be crazy helpful.

    Anyway, sorry for the verbosity and again, thank you for your hard work!
     
  2. marcusrwatson

    marcusrwatson

    Joined:
    Sep 24, 2015
    Posts:
    10
    OK I've finished the whole tutorial except for the web build. Well, I built the web build, and it plays, but does not recognize any input at all (I was using arrows for movement, space for fire, and r for restart - none of them do anything). I tried building the Done_Scenes/Main scene, and I have the same problem. Both work fine in the Unity environment itself, or when I build them as a standalone application.

    I'm using a Macbook Pro with Yosemite 10.10.5. Any clever thoughts on this one?
     
  3. McNoguff

    McNoguff

    Joined:
    Sep 20, 2015
    Posts:
    9
    @marcusrwatson this might be a stupid question but did you try clicking inside the game area on the webpage? Unity won't recognize input until you do so, so if you just started by using the keyboard it wouldn't work. What browser are you using?

    Edit: This is why if you publish a game for web it's always a good idea to have a "click here to start" splash.
     
  4. SicraS

    SicraS

    Joined:
    Sep 22, 2015
    Posts:
    7
    First of all, great series and thanks for doing them. I've enjoyed a lot with this tutorials. The point is that I didn't realized of the live training called: "Extending Space Shooter: Enemies, More Hazards, Scrolling BG...". I'm wondering if this lesson will be opened.. I'm excited wating for it!
     
  5. Adam-Buckner

    Adam-Buckner

    Joined:
    Jun 27, 2007
    Posts:
    5,664
    I am preparing this lesson for the learn site. It was presented last week. It will be available soon.
     
  6. SicraS

    SicraS

    Joined:
    Sep 22, 2015
    Posts:
    7
    Thanks so much!
     
  7. Ironfi5h

    Ironfi5h

    Joined:
    Mar 10, 2015
    Posts:
    3
    I'm currently working through the "Space Shooter" "creating hazards" tutorial

    I'm having a problem getting the Asteroid to rotate with my 'RandomRotator' script. However I find it works fine when I attach the 'Done_RandomRotator' Script...

    Out of curiosity I want to know why my script doesn't work...

    My Script:
    Code (CSharp):
    1.  
    2. using UnityEngine;
    3. using System.Collections;
    4.  
    5. public class RandomRotator : MonoBehaviour
    6. {
    7.  
    8.     public float tumble;
    9.     private Rigidbody Aroid;
    10.  
    11.     void start()
    12.     {
    13.         Aroid = GetComponent<Rigidbody> ();
    14.         Aroid.angularVelocity = Random.insideUnitSphere * tumble;
    15.     }
    16.  
    17.  
    18. }
    19.  
    Tutorials "done" Script:
    Code (CSharp):
    1.  
    2. using UnityEngine;
    3. using System.Collections;
    4.  
    5. public class Done_RandomRotator : MonoBehaviour
    6. {
    7.     public float tumble;
    8.    
    9.     void Start ()
    10.     {
    11.         GetComponent<Rigidbody>().angularVelocity = Random.insideUnitSphere * tumble;
    12.     }
    13. }
     
  8. Markkus

    Markkus

    Joined:
    Jul 6, 2015
    Posts:
    1
    Hi Ironfi5h,
    I'm a newbie, but probably the mistake in your C# script is the start() must be in capital S.
     
    IanSmellis, SicraS and Ironfi5h like this.
  9. Ironfi5h

    Ironfi5h

    Joined:
    Mar 10, 2015
    Posts:
    3
    Doh! Spot on Markkus thanks. lol
     
    IanSmellis, SicraS and Markkus like this.
  10. W3lshm3n

    W3lshm3n

    Joined:
    Sep 28, 2015
    Posts:
    4


    thanks for the fix Adam Buckner, not long after I had posted that I saw my mistake and corrected it. I thought I had deleted my post after I fixed it. but thanks again for the reply.

    but now I have seem to have gotten another problem with Tags ?!?!
    when I change the build platform from pc to android all my tags disappear. Is there a setting to fix this?

    Note: This only happens with any "Enemy" GameObjects , GameObjects tagged "Player" stay at player when the platform is changed

    OK.... So I haven't been able to fix the tag problem, so I just re-tagged what needed to be.
    now it plays for a bit and than I get the same error...


    UnityException: GameObject has undefined tag!
    UnityEngine.Component.get_tag () (at C:/buildslave/unity/build/artifacts/generated/common/runtime/UnityEngineComponentBindings.gen.cs:160)
    Done_DestroyByContact.OnTriggerEnter (UnityEngine.Collider other) (at Assets/Done/Done_Scripts/Done_DestroyByContact.cs:26)

    Its still Tagged "Enemy" in the inspector and I'm now using the Done script (As well as the whole Done Project) for DestroyByContact and when I click on the error and VB comes up with the script this portion is highlighted...

    if (other.tag =="Boundary"|| other.tag =="Enemy")

    ??? I am new at this and have follow the tuts to the T and fixed any problems that coincide with unity 5 from the ver. the tut was made( like the Get.Component for the RigidBody changes)

    Update: This error is coming from Done_Bolt-Enemy(Clone) and seems to happen when the Enemy Bolt hits a Asteroid and/or another "Enemy".
     
    Last edited: Oct 1, 2015
  11. Adam-Buckner

    Adam-Buckner

    Joined:
    Jun 27, 2007
    Posts:
    5,664
    As a moderator I end up seeing all of the posts, whether they been deleted or not. In my haste, I may have accidentally replied to a deleted post, without noticing the "deleted" icon. This probably made visible again.

    Either way, this means that other people can see the problem and the solution!

    Sorry for the bother.
     
    IanSmellis likes this.
  12. Adam-Buckner

    Adam-Buckner

    Joined:
    Jun 27, 2007
    Posts:
    5,664
    I would suspect that even though they appear to be "tagged" as "enemy", if you go to the tags and layers panel you will discover that "enemy" is not defined, and your need to redefine enemy and then re-apply it to the game object.

    I've seen this happen a few times now from people in the community… But I've never been able to track down why or how it's happening. Perhaps it's due to changing the build target? I'll try to look into it…

    If you can reproduce this problem, then please let me know and also fill the bug report using the editor bug reporter.

    If changing the build target somehow removes the newly defined tags, then that would definitely be a bug. So please let us know if this is reproducible!

    What I have noticed with this issue, regardless of how it is created, is that the gameplay is perfectly fine in the editor – even though the tag is not defined (though it is assigned to the game object), when it is compiled to be built – whether that's standalone or mobile or whatever – the game will not play correctly. Also, for what it's worth, I've seen this so far only in the role – a – ball project, and never yet here in space shooter.
     
  13. Ironfi5h

    Ironfi5h

    Joined:
    Mar 10, 2015
    Posts:
    3
    I've just added code to restart the game in the Space Shooter(Unity 5) - Ending the Game tutorial, the problem is that the game auto restarts, when I comment out the line of code to reload the level I get a constant stream of Debug.Log reports telling from within the 'if' statement responsible for checking if Input.GetKeyDown(KeyCode.R) is true.

    Why am I getting a stream of false possitives from KeyDown?

    Code (CSharp):
    1. using UnityEngine;
    2. using UnityEngine.UI;
    3. using System.Collections;
    4.  
    5. public class GameController : MonoBehaviour
    6. {
    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.     public Text scoreText;
    14.     public Text restartText;
    15.     public Text gameOverText;
    16.  
    17.     private bool gameOver;
    18.     private bool restart;
    19.     private int score;
    20.  
    21.     void Start()
    22.     {
    23.         gameOver = false;
    24.         restart = false;
    25.         restartText.text = "";
    26.         gameOverText.text = "";
    27.  
    28.         Debug.Log ("hello from Start()");
    29.  
    30.         score = 0;
    31.         UpdateScore ();
    32.         StartCoroutine(SpawnWaves ());
    33.         Debug.Log ("Start Wave Begun");
    34.  
    35.     }
    36.  
    37.     void Update()
    38.     {
    39.         if (restart) {
    40.  
    41.             if(Input.GetKeyDown(KeyCode.R));
    42.             {
    43.                 Debug.Log ("'R' PRESSED!");
    44.                 Application.LoadLevel(Application.loadedLevel);
    45.             }
    46.         }
    47.     }
    48.  
    49.     IEnumerator SpawnWaves()
    50.     {
    51.         yield return new WaitForSeconds(startWait);
    52.  
    53.         while (true)
    54.         {
    55.             for (int i = 0; i < hazardCount; i++) {
    56.                 Vector3 spawnPosition = new Vector3 (Random.Range (-spawnValues.x, spawnValues.x), spawnValues.y, spawnValues.z);
    57.                 Quaternion spawnRotation = Quaternion.identity;
    58.                 Instantiate (hazard, spawnPosition, spawnRotation);
    59.                 yield return new WaitForSeconds (spawnWait);
    60.             }
    61.             yield return new WaitForSeconds(waveWait);
    62.  
    63.             if(gameOver)
    64.             {
    65.                 restartText.text ="Press 'R' for restart";
    66.                 restart = true;
    67.                 break;
    68.             }
    69.         }
    70.     }
    71.  
    72.     public void AddScore(int newScoreValue)
    73.     {
    74.         score += newScoreValue;
    75.         UpdateScore ();
    76.     }
    77.  
    78.     void UpdateScore()
    79.     {
    80.         scoreText.text = "Score: " + score;
    81.     }
    82.  
    83.     public void GameOver(){
    84.         gameOverText.text = "Game Over!";
    85.         gameOver = true;
    86.     }
    87. }
    88.  
    ====================================================================

    I've found out why it wasn't working... Yet another DOH! moment. I couldn't see the syntax error for the code. Semi colon in front of my if statement!
     
    Last edited: Oct 2, 2015
  14. GiordanoBruno

    GiordanoBruno

    Joined:
    Oct 1, 2015
    Posts:
    1
    Hi,

    I completed the tutorial at 99%, the only thing that is not working is the SimpleTouchPad. When I drag the finger in the touch screen nothing happens... I made a debug and I saw that inside the "public void OnDrag" the variable 'direction' changes according to my movements. However, 'direction' is not passed to "public Vector2 GetDirection ()" where it results always null. Both of them are inside the same class "SimpleTouchPad". I am really a beginner with Unity and C#, so I am sorry for any imprecisions. Please let me know if you can help. Thank you!!

    by the way, I get the following error: the variable 'direction' is assigned but is never used

    ==========================================

    Problem solved, I erroneously put Vector 2 in front of direction in "public void OnDrag"!
     
    Last edited: Oct 2, 2015
  15. AlphaCommie

    AlphaCommie

    Joined:
    Sep 30, 2015
    Posts:
    1
    can anyone tell me how to make the tilt more smoother? like when i press left arrow button and then the right arrow button quickly, i see that the player moves from left tilt to neutral with no animation in between and then it goes from neutral smoothly to the right tilt.
     
  16. austindake18

    austindake18

    Joined:
    Sep 16, 2015
    Posts:
    4
    So i am all the way towards the end of the section covering how to end the game and when i restart the level, the light is gone. I have searched through all of my work to see if i could figure it out but im clueless.
     
  17. DYV

    DYV

    Joined:
    Aug 10, 2015
    Posts:
    58
    first of all thank you very much for such good tutorial, I really enjoy it.
    I wonder how can one to stop spawning waves and start another spawning waves with another hazards? Or to stop spawning waves and spawn boss-hazard?
     
  18. Adam-Buckner

    Adam-Buckner

    Joined:
    Jun 27, 2007
    Posts:
    5,664
    Glad you got it working!
     
  19. Adam-Buckner

    Adam-Buckner

    Joined:
    Jun 27, 2007
    Posts:
    5,664
    Fantastic day! It's always a great feel to figure out why things are not working.
     
  20. Adam-Buckner

    Adam-Buckner

    Joined:
    Jun 27, 2007
    Posts:
    5,664
    If you are using input.axis() then there is smoothing built in. If you use input.axisraw, there is no smoothing. This could be a perceived issue, or a frame rate issue. Do you have an issue when you build and deploy the game?
     
  21. Adam-Buckner

    Adam-Buckner

    Joined:
    Jun 27, 2007
    Posts:
    5,664
    Can you give us screenshots or more detailed information? Are the lights in your hierarchy? What are the settings in your lighting window? Use screenshots of you need to...
     
  22. Adam-Buckner

    Adam-Buckner

    Joined:
    Jun 27, 2007
    Posts:
    5,664
    You can stop spawning waved with break, just as you do when ending the game. Then you'd need more logic to start a new set of disowned waves or bosses

    The other thing you can do is add conditionals into the while loop. With certain conditions are present you choose what to spawn.
     
  23. austindake18

    austindake18

    Joined:
    Sep 16, 2015
    Posts:
    4
    This is my screenshot for my main lifting as that is the light that goes away every time I restart the level. Just a not the settings themselves do not change so i was thinking it was maybe something in the code but just to be safe I went back and copy and pasted the scripts and I still get the same result
     

    Attached Files:

  24. Adam-Buckner

    Adam-Buckner

    Joined:
    Jun 27, 2007
    Posts:
    5,664
    You can try some free screen shot applications like https://gyazo.com/tabs/history or you can use "print screen" from the Windows OS: http://windows.microsoft.com/en-gb/...en#take-screen-capture-print-screen=windows-8

    With one of these can you show your game when it starts and when it restarts to see the difference.

    Can you also take a shot of your "lighting" panel:

    https://gyazo.com/8c5e94003c1a80e27abdf2f0e4fc3943

    This can be found at
    WIndows/Lighting:

    https://gyazo.com/26932bb2c9b17eaa1938d7de1a45c377
     
  25. austindake18

    austindake18

    Joined:
    Sep 16, 2015
    Posts:
    4
    i actually figured out the problem, in unity 5 for some reason the editor messes with the lighting when you restart once i built and launched the game it worked flawlessly.
     
  26. Adam-Buckner

    Adam-Buckner

    Joined:
    Jun 27, 2007
    Posts:
    5,664
    Oh! Fantastic! Well, the sorting it out thing.

    If you need any more help, don't hesitate to post.
     
  27. shintaru22

    shintaru22

    Joined:
    Oct 4, 2015
    Posts:
    10
    Can anyone teach me how to limit the number of waves of enemies and it will go to the next level..
     
  28. Adam-Buckner

    Adam-Buckner

    Joined:
    Jun 27, 2007
    Posts:
    5,664
    In your while loop, have a count (or you could exchange the while loop with a for loop...) and when the count reaches a certain number of waves (or [in the while loop] a certain number of points or whatever condition you want) - you could even test this right around where the code tests "Game Over"... and then load a new level.

    You may want to add some new things to the rest of the co-routine "spawn waves" before loading the new level, like displaying a "Congratulations! You've been promoted to Cadet First Class!" and the take control of the ship and zoom it off screen, then "Prepare for the next wave!"

    Then load the level.
     
  29. DYV

    DYV

    Joined:
    Aug 10, 2015
    Posts:
    58
    Adam, thank you. Your answer to shintaru22 solved my problem. I have just tested while loop and it works, so now I can stop those waves, that was I needed :) Thanks!
     
  30. Mr.Mille

    Mr.Mille

    Joined:
    Sep 17, 2015
    Posts:
    21
    Hello Adam.I have some problems with multiple colliders on Asteroid3 prefab.By rewatching the
    twitch video of the last live training i noticed you didn't set the second collider to IsTrigger and
    the asteroid3 is rotating like a mad around it's non-trigger collider. Is it supposed to be like this?By setting the second collider to IsTrigger i get another issue...sometimes i get double score for shooting the Asteroid3.
    It means that somehow the bolt collides with both of the trigger colliders of the asteroid. Is there any practice to avoid hitting multiple colliders?
     
  31. Adam-Buckner

    Adam-Buckner

    Joined:
    Jun 27, 2007
    Posts:
    5,664
    Sorry, I'm not quite sure I follow... Could be it's late and I'm tired.

    Can you try explaining this again in a different way?
     
  32. Mr.Mille

    Mr.Mille

    Joined:
    Sep 17, 2015
    Posts:
    21
    Sure. Sry, english is not my native language. I'll try to explain this step by step.
    So, you added two capsule colliders to Asteroid3 object. One of these colliders was not a trigger collider according to the video of your last live training. If you hit play the Asteroid3 object behaves different than other two asteroids. It rotates not the same way.Because of the rigidbody is not being Kinematic the Asteroid3 instance rotates not around the own local axis but rather around it's non-triggered capusle collider right? Anyway it seems to be like this by testing a game.
     
    Last edited: Oct 4, 2015
  33. dcolzani

    dcolzani

    Joined:
    Sep 22, 2014
    Posts:
    19
    How would I go about spawning multiple enemies at the same time? They don't need any special behavior. I tried messing around with Lists but couldn't quite grasp the concept. I'm using my GameController script for all this. Currently I'm repeating code to get my desired results but I know that's a no no.
     
  34. Adam-Buckner

    Adam-Buckner

    Joined:
    Jun 27, 2007
    Posts:
    5,664
    If one of the colliders was not a trigger collider, this was an error.
     
  35. Adam-Buckner

    Adam-Buckner

    Joined:
    Jun 27, 2007
    Posts:
    5,664
    In this case, you'd either need another loop around Instantiate(hazard, spawpPos, spawnRot), or you'd need to duplicate your code.
     
  36. DYV

    DYV

    Joined:
    Aug 10, 2015
    Posts:
    58
    Adam, could you show me the way how to add health to the player and some enemies.
    I tried to use some scripts but they came into conflict with DistroyByContact script and trigger collider.
    Is there any gentle way to add a health of player (and some enemies) in the game and don't destroy your elegant script?
     
  37. Mr.Mille

    Mr.Mille

    Joined:
    Sep 17, 2015
    Posts:
    21
    The problem is if there are 2 capsule colliders on one hazard, sometimes there will be
    created two instances of the Asteroid and the Bolt at the same time when collision occures.
    Therefore the score will be increased by 20 instead of 10. I don't really understand why it
    sometimes happens. Any ideas? Here is the screenshot of the console:
     
  38. Adam-Buckner

    Adam-Buckner

    Joined:
    Jun 27, 2007
    Posts:
    5,664
    Are you asking: I'd like to have a health value for the Player Ship and the Enemy Ships, so they won't be destroyed in one hit?

    Are you discovering that: If you add a health variable, they are destroyed in one hit anyway with DestroyByContact?
     
  39. Adam-Buckner

    Adam-Buckner

    Joined:
    Jun 27, 2007
    Posts:
    5,664
    Did you set both of these to trigger colliders?

    If so, yes, it's possible to have a double contact as the bolt could pass thru them on the same frame.

    I didn't think of this when doing the live session.

    Stick to one collider for now, or you will need to "trap" the score so it is not doubled.
     
  40. DYV

    DYV

    Joined:
    Aug 10, 2015
    Posts:
    58
    exactly:)
     
  41. shintaru22

    shintaru22

    Joined:
    Oct 4, 2015
    Posts:
    10
    sir Adam Bucker this is the code i use. How can i put the end loop into this code..

    IEnumerator SpawnWaves ()
    {
    yield return new WaitForSeconds (startWait);
    while (true)
    {
    for (int i = 0; i < hazardCount; i++)
    {
    Vector3 spawnPosition = new Vector3 (Random.Range (-spawnValues.x, spawnValues.x), spawnValues.y, spawnValues.z);
    Quaternion spawnRotation = Quaternion.identity;
    Instantiate (hazard, spawnPosition, spawnRotation);
    yield return new WaitForSeconds (spawnWait);
    }
    yield return new WaitForSeconds (waveWait);
    }
    }
     
  42. shintaru22

    shintaru22

    Joined:
    Oct 4, 2015
    Posts:
    10
    sorry for many questions im just newbie student.. thank you
     
  43. 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/
     
  44. Adam-Buckner

    Adam-Buckner

    Joined:
    Jun 27, 2007
    Posts:
    5,664
    I am not sure I understand the question?

    "End Loop"?

    Do you mean "How to I break out of the while loop and end the game?" This is covered in the second to last episode.

    If now, can you try again to explain what you need?
     
  45. zonder

    zonder

    Joined:
    Oct 15, 2013
    Posts:
    2
    Hi,
    I have a problem with DestroyOnContact script I get error Object reference not set to an instance of an object pointing to this line
    Code (CSharp):
    1. gameController.AddScore (scoreValue);
    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.  
    11.     void Start ()
    12.     {
    13.         GameObject gameControllerObject = GameObject.FindWithTag ("GameController");
    14.         if (gameController != null)
    15.         {
    16.             gameController = gameControllerObject.GetComponent <GameController>();
    17.         }
    18.         if (gameController == null)
    19.         {
    20.             Debug.Log ("Cannot find 'GameController' script");
    21.         }
    22.     }
    23.  
    24.     void OnTriggerEnter(Collider other)
    25.     {
    26.         if (other.tag == "Boundary")
    27.         {
    28.             return;
    29.         }
    30.         Instantiate (explosion, transform.position, transform.rotation);
    31.         if (other.tag == "Player")
    32.         {
    33.             Instantiate (playerExplosion, other.transform.position, other.transform.rotation);
    34.         }
    35.         gameController.AddScore (scoreValue);
    36.         Destroy(other.gameObject);
    37.         Destroy (gameObject);
    38.     }
    39. }
    40.  
    I also get log in debug "Cannot find Game Controller script "

    What is happening, when I run game I cant destroy asteroids, neither I can kill player, on contact nothing happens appart sound and VFX
     
    Last edited: Oct 6, 2015
  46. SicraS

    SicraS

    Joined:
    Sep 22, 2015
    Posts:
    7
    @zonder
    Maybe it's obvious but, have you created and written the GameController script? If you have, check the name you gave to the script, as it has to be the same as GameController. Also check the Tag. Your code, at least in this class seems to be correct. Just a miss-spell letter can break it all! :)

    If these all are correct, can you post the AddScore method code? Or better, the GameController class? Are you setting a value to scoreValue in the editor (just for guessing what happens)?

    Edit add: Have you attached the scripting to the Game Objects correctly?
     
    Last edited: Oct 7, 2015
  47. shintaru22

    shintaru22

    Joined:
    Oct 4, 2015
    Posts:
    10
    what i mean is how
    yes sir "How do I break out the while loop?". Ex. is i want that the number of enemies spawn in my stage level 1 is only 50 and if the enemies get the limit of spawn the player will go to next level..
     
  48. SicraS

    SicraS

    Joined:
    Sep 22, 2015
    Posts:
    7
    Don't know if this is what you want @shintaru22 , but let's see...

    You can check this http://www.dotnetperls.com/while to see how while loop works.

    In your case I'll try to do this (don't know if this is the best way to accomplish it, btw it ends the loop):
    Code (CSharp):
    1. IEnumerator SpawnWaves ()
    2. {
    3.      yield return new WaitForSeconds (startWait);
    4.      // Number of waves to Spawn
    5.      int wavesNumber = 50; // This surely needs to be a public attribute of the class so you can set its value in the editor
    6.      // counter which counts the waves
    7.      int wavesCount = 0; // We initialize it to zero
    8.      // now we will loop until the wavesCount = 50
    9.      while (wavesCount < wavesNumber)  // this will evaluate to false when wavesCount = 50
    10.     {
    11.         for (int i = 0; i < hazardCount; i++)
    12.         {
    13.             Vector3 spawnPosition = new Vector3 (Random.Range (-spawnValues.x, spawnValues.x), spawnValues.y, spawnValues.z);
    14.             Quaternion spawnRotation = Quaternion.identity;
    15.             Instantiate (hazard, spawnPosition, spawnRotation);
    16.             yield return new WaitForSeconds (spawnWait);
    17.         }
    18.         yield return new WaitForSeconds (waveWait);
    19.  
    20.        // now we add 1 to our counter so the condition could be false
    21.        wavesCount++;
    22.     }
    23. }
    This is a simple way to end the loop.... but I REPEAT, just for ENDING the loop.. nothing related to the game main loop or to go to gameover.

    another way to to this can be like:
    Code (CSharp):
    1. ...
    2. int wavesNumber = 50;
    3.  
    4. int waveCount = 0;
    5.  
    6. while (true)
    7. {
    8.     ...
    9.     /* do the stuff for spawning waves*/
    10.     ...
    11.  
    12.     waveCount++; // increase in 1 the counter
    13.  
    14.     // now we can check the condition
    15.     if (waveCount == wavesNumber )
    16.         break;                                                 // this will stop the loop
    17. }
    18. ...
    tell us if this is what are you looking for. :)

    PD: If your problem is that you don't have a good knowledge of programming, i suggest you to dive into more C# programming tutorials or lessons before go on with Unity Scripting. :) If this is your case I recommend you to visit https://www.microsoftvirtualacademy...es/c-fundamentals-for-absolute-beginners-8295
     
    Last edited: Oct 7, 2015
  49. Adam-Buckner

    Adam-Buckner

    Joined:
    Jun 27, 2007
    Posts:
    5,664
    Just to be clear. In the past, the underlying Physics engine (PhysX) allowed multiple Colliders associated with one single Rigidbody component. If there were multiple contacts with Colliders in the same frame, only one combined message would ever reach the Rigidbody component. Now, with PhysX3 in Unity 5, the Physics system has been optimized for speed. Each collider will send it's own message to the Rigidbody. If multiple Colliders are used, we will have to "trap" or "group" these messages ourselves.

    One suggestion would be to add:
    Code (csharp):
    1. private bool destroyed = false;
    2.  
    3. OnTriggerEnter() {
    4.    if (!destroyed) {
    5.      destroyed = true;
    6.      gameController.AddScore (scoreValue);
    7.    }
    8. }
    This way, only one score is sent to the gameController.

    -

    I will remove this part where we add the second Collider from the session before I upload it to avoid confusion.
     
    OboShape likes this.
  50. Adam-Buckner

    Adam-Buckner

    Joined:
    Jun 27, 2007
    Posts:
    5,664
    Are you asking: I'd like to have a health value for the Player Ship and the Enemy Ships, so they won't be destroyed in one hit?

    Are you discovering that: If you add a health variable, they are destroyed in one hit anyway with DestroyByContact?
    Ok - with the Caveat that I'm writing this here without testing it... so FWIW, YMMV, Caveat Emptor, etc...

    This is the original "DestroyByContact" Script:
    Code (csharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class Done_DestroyByContact : MonoBehaviour
    5. {
    6.     public GameObject explosion;
    7.     public GameObject playerExplosion;
    8.     public int scoreValue;
    9.  
    10.     private Done_GameController gameController;
    11.  
    12.     void Start ()
    13.     {
    14.         GameObject gameControllerObject = GameObject.FindWithTag ("GameController");
    15.         if (gameControllerObject != null)
    16.         {
    17.             gameController = gameControllerObject.GetComponent <Done_GameController>();
    18.         }
    19.         if (gameController == null)
    20.         {
    21.             Debug.Log ("Cannot find 'GameController' script");
    22.         }
    23.     }
    24.  
    25.     void OnTriggerEnter (Collider other)
    26.     {
    27.         if (other.tag == "Boundary" || other.tag == "Enemy")
    28.         {
    29.             return;
    30.         }
    31.  
    32.         if (explosion != null)
    33.         {
    34.             Instantiate (explosion, transform.position, transform.rotation);
    35.         }
    36.  
    37.         if (other.tag == "Player")
    38.         {
    39.             Instantiate(playerExplosion, other.transform.position, other.transform.rotation);
    40.             gameController.GameOver();
    41.         }
    42.    
    43.         gameController.AddScore (scoreValue);
    44.         Destroy (other.gameObject);
    45.         Destroy (gameObject);
    46.     }
    47. }
    I feel that the first thing you'd need is a "health" variable. Let's be able to set this in the inspector and save it to prefabs, so add:
    Code (csharp):
    1. public int health;
    ... as an int, as we will be counting the number of shots it takes to kill the item. (This could be made a default of 1, but using public int health = 1;)

    Then, in the OnTriggerEnter, we need to do a few things:
    • Decrement the health of the object
    • Test the health to see if it's <= 0;
    • Somehow accommodate the logic that we need to destroy the bolts no matter what.
    Now, we have to remember that the driving logic to this simple game is that the hazards destroy every thing they touch with Destroy(other.gameObject); So, let's make one simplification... "If the hazard hits the player, the player is dead..." This means we can't have a health value for the player at this stage - just for the hazards.

    With this, the code if fairly simple. Changing only OnTriggerEnter():
    Code (csharp):
    1.     void OnTriggerEnter (Collider other)
    2.     {
    3.         if (other.tag == "Boundary" || other.tag == "Enemy")
    4.         {
    5.             return;
    6.         }
    7.  
    8.        // Add DECREMENT here:
    9.        health -= 1;
    10.  
    11.         if (explosion != null)
    12.         {
    13.             Instantiate (explosion, transform.position, transform.rotation);
    14.         }
    15.  
    16.         if (other.tag == "Player")
    17.         {
    18.             Instantiate(playerExplosion, other.transform.position, other.transform.rotation);
    19.             gameController.GameOver();
    20.         }
    21.    
    22.         gameController.AddScore (scoreValue);
    23.         Destroy (other.gameObject);
    24.  
    25.        // Add TEST here:
    26.        if (health <= 0)
    27.        {
    28.               Destroy (gameObject);
    29.        }
    30.     }
    31. }
    There are some things that you may want to add to this, like a test to see if the hit destroys the hazard or not, and if not, have a smaller explosion, to indicate a "hit" but not a destroy. That could be coded with:
    Code (csharp):
    1. public gameObject smallExplosion;
    ... and then in OnTriggerEnter() add:
    Code (csharp):
    1.  
    2.         if (explosion != null)
    3.         {
    4.               if (health <=0)
    5.               {
    6.                      Instantiate (explosion, transform.position, transform.rotation);
    7.               }
    8.               else
    9.               {
    10.                      Instantiate (smallExplosion), transform.position, transform.rotation);
    11.               }
    12.         }
    Now, if you want the player to have health, it gets a lot more complicated.
    • The player would need to have a health value.
    • The player would need a TakeDamage (int damageValue) {} function that would do something like health -= damageValue; in it.
    • To destroy the player, in this context, perhaps it would be best to return the value of the player's health to the hazard? (You might find a more clever way to do this...), so make TakeDamage into public int TakeDamage (int damageValue) {}.

    Then in the DestroyByContact's OnTriggerEnter() you'd need change:
    Code (csharp):
    1.  
    2.         if (other.tag == "Player")
    3.         {
    4.             Instantiate(playerExplosion, other.transform.position, other.transform.rotation);
    5.             gameController.GameOver();
    6.         }
    ... into something like:
    Code (csharp):
    1.  
    2.         if (other.tag == "Player")
    3.         {
    4.             int playerHealth = other.GetComponent<PlayerController>().TakeDamage (damageValue);
    5.             if (playerHealth <= 0)
    6.             {
    7.                 Instantiate(playerExplosion, other.transform.position, other.transform.rotation);
    8.                 gameController.GameOver();
    9.             }
    10.             else
    11.             {
    12.                 Instantiate(smallExplosion, other.transform.position, other.transform.rotation);
    13.             }
    14.         }
    Now - where this code FAILS is on "Who wins?"

    How much damage does the Player Ship do to a hazard? Does it destroy it outright? If so, what's the best logic to show this? How much damage does the hazard do to the Player Ship? Well, they could both have a damageValue that they could pass to the other object... but, ultimately: if one does not destroy the other, then what happens? Do they just pass through each other? (This is what will happen under the current logic as they are trigger colliders...)

    I'll leave that up to you as a "stretch goal"... but I trust this will give you a starting place to work from.