Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Space Shooter Tutorial Q&A [ARCHIVED]

Discussion in 'Community Learning & Teaching' started by Valdier, Jan 12, 2014.

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

    Ares121

    Joined:
    Jun 5, 2014
    Posts:
    8
    Thanks Adam! I managed to figure it out and get through the tutorial! Thanks to the help of the posts from the community members in this forum. Also thanks to your awesome video. Each problem I encountered was a learning experience. There were more issues beyond this ones I posted here but through careful investigation and reviewing of the videos I got passed them and completed a successful Space Shooter!

    I have a long journey ahead of me learning this software but completing the Roll-a-Ball and Space Shooter tutorials was a big step in the right direction. I hope to see more awesome tutorial videos like these ones in the future!
     
    RJ-MacReady likes this.
  2. Adam-Buckner

    Adam-Buckner

    Joined:
    Jun 27, 2007
    Posts:
    5,664
    We will try to deliver more material as soon as possible!

    Currently, I'm concentrating on Live Sessions (http://cms.hq.unity3d.com/learn/live-training) but have plans for more off-line persistent material.

    If you feel you were derailed by some omission or confusion in the videos, let me know, so I can either try to fix it, or make sure it doesn't happen on the next one.

    Glad you made it through!
     
  3. xJayce

    xJayce

    Joined:
    Jun 12, 2014
    Posts:
    2
    Hi Adam!

    Another fan of the tutorials so far! Thanks for your work on this.

    I had a quick question. For some reason, I generally (though not always) receive 20 pts each time I destroy an asteroid. The score value in the prefab inspector is set to 10. The script in the 'DestroyByContact' is set to 'OnTriggerEnter' From what I can tell, it appears that two collisions are being triggered (I have two instances of 'explosion_asteroid(Clone)' in my hierarchy, and I added some debug code that shows that a score of 10 is being added twice at exactly the same time).

    Any suggestions on where I can look to fix this? Let me know what info you need (code, screenshots of settings).
     
  4. RJ-MacReady

    RJ-MacReady

    Joined:
    Jun 14, 2013
    Posts:
    1,718
    Each object that collides will be evaluated and will register OnTriggerEnter, so say fifteen shots hit the same asteroid, each one of those OnTriggerEnter events will be called, the asteroid won't be destroyed until after that frame is completed.

    In your case you might have two instances of the same script attached to the shot OR you might have accidentally attached the DestroyByContact to the asteroid and forgotten about it.

    It definitely feels like you've got another instance of the script somewhere, or you're calling it twice and since it only happens per collision and its always two exactly, that has to be the case. Just a matter of finding the logic error.
     
  5. Adam-Buckner

    Adam-Buckner

    Joined:
    Jun 27, 2007
    Posts:
    5,664
    Misterselmo seems to have nailed it. That would be my best suggestion. Look at the two colliding objects (hazard and bolt) and see how you are getting two calls in the same frame.
     
  6. xJayce

    xJayce

    Joined:
    Jun 12, 2014
    Posts:
    2
    AHA!! I had a collider on the Asteroid (parent) and one on the Asteroid_Prop_01 (Child). Removed the collider in the child and I think that's got it working.

    Thanks guys!
     
  7. Adam-Buckner

    Adam-Buckner

    Joined:
    Jun 27, 2007
    Posts:
    5,664
    Fantastic! I'm glad you discovered the issue. Learning how to troubleshoot a project is important, and I'm sure this has given you a lot of insight into that!
     
  8. 5devilz

    5devilz

    Joined:
    Jun 21, 2014
    Posts:
    5
    Hey all. First of all...great tutorial so far. I watched it complete.
    Now I'm trying it for my self, but i'm running in some problems.

    1. if i hit the "play" button. the rotation of my player object is changed to x 270 instead of -90. I tryed the finished version and everything works fine.
    Ah. I have to say, I'm using my own model. I fixed the rotation problem (blender > unity) with the tool from this thread http://forum.unity3d.com/threads/blender-unity-rotation-fix.181870/ . everything worked.

    2. If i add the tilt funktion it flips my player object 90° on z. So it looks like the camera is positioned on the back instead of the top view.

    I hope you guys understand what I'm trying to say :)
     
  9. Adam-Buckner

    Adam-Buckner

    Joined:
    Jun 27, 2007
    Posts:
    5,664

    1: You can use either negative or positive values for the transform axes and get the same rotation. These axes numbers (the 3 float values as a Vector 3) are converted into quaternions internally, but displayed as 3 decimal numbers in the inspector. So -90 and 270 are the same rotational value along a single axis... as is 630 and -450!

    I see that your issues are different from the positive/negative values, and I have not read the linked thread, but do check the orientation of the model before applying the code in the tutorial. It assumes that the models are set up with the same orientation.

    2: Double check the final orientation of the model and make sure it matches that of the model in the project's assets. If the two models are in the scene with the same orientation and transform values, the code should work correctly. I can't speak to the blender-unity-rotation-fix solution. This may be introducing an error. Don't forget that you can model your ship in Blender along the correct axes and it will import correctly into Unity. Now - this may look different in Blender, as Blender is z-up whereas Unity is y-up... but if you model your ship with the nose along the z-axis and the wings along the x-axis and the cock pit on the positive side of the y-axis, it will drop into Unity just fine. I just may look like it's pointing up in Blender rather than forward as you'd expect in Unity.
     
  10. 5devilz

    5devilz

    Joined:
    Jun 21, 2014
    Posts:
    5
    OMG. It's working :D
    Thank you so much. NOw i can die in peace xD. Just kidding :)
    I think i did something wrong, when i used the tool or it simple sucks :)

    Another question. is there a chance that the rotation problem "blender>unity" will be fixed? I mean its no problem, if i have to rotate the finished model in blender, but it's kind of annoying keeping it in mind.
    Or i try the tool again....
     
  11. Adam-Buckner

    Adam-Buckner

    Joined:
    Jun 27, 2007
    Posts:
    5,664
    As far as my memory serves, there is no actual problem with importing blender models ... if they are modelled with the correct orientation. Blender uses the z-axis as up, and Unity uses the y-axis as up. A Blender model will be positioned along the correct axes on import - x along the x, y on the y and z on the z. What looks like up, however, will be different. This is a perceived difference, but the axes are correct.
     
    Last edited: Jun 22, 2014
  12. 5devilz

    5devilz

    Joined:
    Jun 21, 2014
    Posts:
    5
    Hey Adam,
    sorry to bother you again. But I have a new problem.
    If I press play, my player is always off rotation. i mean, the Player object is positioned at x = 0, y= 0 and z = 0. With a rotation of x, y, z = 0. But after I pressed start, the rotation axes become random values and change continuously.
    Movement works correct.
    After some time flying, the player object suddenly rotates on Y, and when I stopp pressing "left or right key", it slowly returns to 0.
     
  13. Adam-Buckner

    Adam-Buckner

    Joined:
    Jun 27, 2007
    Posts:
    5,664
    Hmm... I'm not sure what could be causing that off the top of my head.

    If this is happening when in play-mode, but not edit mode, then it's either due to a script... or interacting with another component.

    If it's a script, then look through your code for anything that's either adding forces or grabbing input. You can compare this with DONE folder in the project, just to make sure everything is correct.

    If it's a component, then look for something like an overlapping collider, or colliders that are not set as triggers but should be. Intersecting colliders will apply forces against each other as part of the physics engine...

    Le us know what you find out.
     
  14. 5devilz

    5devilz

    Joined:
    Jun 21, 2014
    Posts:
    5
    Well that's kind of awkward. I just tryed it again and the problem doesn't occur anymore.
    I don't know how and why....
    I let you know if it happened again.
     
  15. Adam-Buckner

    Adam-Buckner

    Joined:
    Jun 27, 2007
    Posts:
    5,664
    ^_^ It's always great when things just work out. The magic code-fairies come in the middle of the night and fix your project without you noticing!
     
  16. nf3

    nf3

    Joined:
    Jul 3, 2014
    Posts:
    1
    Hi Adam. Newb here, lots of thanks for these tuts. Completed the roll-a-balls, I'm into space shooter, everything goes fine but I've got a few glitches i cannot figure out:

    a) My asteroids come down with some angle instead of just falling down the screen. So they also destroy each other a lot, and if not, they die at about mid screen. I blamed gravity, but its unchecked. I suppose I've got something wrong in scripts or public variables, but I cannot find it, got any clue for me?

    b) Every time i start the game, the ship shoots a single shoot,

    Ty very much


    edit : after adding the spawning coroutine the asteroids fall just fine and the mid-screen destroy no longer happens. I don't know why this happened in the first time and why is now fixed. The first shoot on run game persists, though. Fyi i'm doing the tut on unity 4.5.1f3
     
    Last edited: Jul 3, 2014
  17. shimizu2

    shimizu2

    Joined:
    Nov 25, 2013
    Posts:
    1
    Sorry for interrupting
    but where is the optional tutorial?
    about controlling the enemy space craft movement etc?
     
  18. Adam-Buckner

    Adam-Buckner

    Joined:
    Jun 27, 2007
    Posts:
    5,664
    I'm glad the asteroids fall fine now. It's always interesting to track down the "why" when something like that happens, but if it's working, you may just want to move on.

    When it comes to the ship shooting a shot when the game is starting - double check to make sure you don't have a shot instantiated in the game during edit-time. You may have placed a bolt prefab on the ship to check or test something and forgotten to delete it. All of the shots should be instantiated at run-time and there should be no shots on the ship when you build your edit to play.
     
  19. Adam-Buckner

    Adam-Buckner

    Joined:
    Jun 27, 2007
    Posts:
    5,664
    You can see the finished version of the game in "Done_Main" in the "Done" folder.

    I do plan to record "Chapter 2" when I get the chance, but it's not available yet.
     
  20. teknophyl

    teknophyl

    Joined:
    Jun 22, 2014
    Posts:
    51
    An FYI for others doing the tutorial:

    In the Counting Points part of the tutorial Adam states that the variable named score is automatically converted to string when assigning it to scoreText.text:

    scoreText.text = "Score: " + score

    I created a separate GUIText object to hold just the word "Score" and then added an additional GUIText object to contain just the score. I added 2 GUIText objects instead of 1 because I wanted a different font for my score. In this case the code above fails because Unity doesn't implicitly convert it, so you have to use ToString().
     
  21. Adam-Buckner

    Adam-Buckner

    Joined:
    Jun 27, 2007
    Posts:
    5,664
    Yes. Absolutely.

    I believe I state in the lesson that when adding a numerical value to a string:
    Code (csharp):
    1. float numericalValue = 3.14159f;
    2. string myString = "Text " + numericalValue;
    ... the conversion is automatic. Unity sees that the number is being added to the string and converts it.

    If, however, the numerical value is being put into a string field directly on its own, it must be explicitly converted into a string:
    Code (csharp):
    1. float numericalValue = 3.14159f;
    2. string myString = numericalValue.ToString();
     
  22. Baer

    Baer

    Joined:
    Aug 10, 2013
    Posts:
    5
    Hey Adam,
    I just wanted to say thanks for your great tutorial.
    Your explanations are really helpful and it was very easy to follow your turorial through to the end with basic C# skills.
    Now I want to self-explain the following steps (your unfinished Chapter 2).

    Without looking at the code, the additional elements are:
    - Background Scroller / Starfield
    - Enemy / Evasive Maneauver
    - Weapon Controller
    - Other types of Asteroids

    Did I forget something?
    In which order did you insert/create them?

    Keep up the good work!
     
  23. Adam-Buckner

    Adam-Buckner

    Joined:
    Jun 27, 2007
    Posts:
    5,664
    The order is somewhat irrelevant. As far as I remember, no one item required the next.

    Until I can find the time to explain "Chapter 2" in detail, the best thing to do is go through the "Done" folder and see what's different.

    I would start with what you find the most interesting.

    Look at the scrolling Background Script and the way it's set up in the scene.

    For the scrolling BG, you may also want to loot at the "Live Training Archives" on the learn part of our website as I did a session on scrolling backgrounds, including the implementation in this Space Shooter project.

    The starfield is simply a particle system.

    Look at how it's set up and tweak the parameters and see what changes.

    The only other major change is the addition of 3 new types of hazards - 2 more asteroids and the enemy spaceship.

    The additional hazards are simply added by changing the single reference to the hazard into a list of hazards, and picking randomly from that list.

    The evasive manoeuvres and shooting are incorporated directly in the scripts attached to the enemy ship prefab, so they only need to be instantiated as hazards to work. Again, simply look at the scripts and see how they are done.

    As I said, all of this material is in the "Done" folder, for you to play with to your heart's content.

    If you have any specific questions about this "Done" material, just post them here.
     
  24. Baer

    Baer

    Joined:
    Aug 10, 2013
    Posts:
    5
    Thanks for your quick reply Adam.
    I think I understood all of your changes, though they are not self-explanatory for unity beginners like me. Especially the maneauver-part was quite confusing at first, I think your videos will help there a lot.

    Your Live Training video on scrolling backgrounds with pretty good as well, though the part with the "strip background" was a little bit confusing at first. Are there (performance wise) any differences for all 3 methods you described?

    Oh, and if you haven't fixed it already (I saw it in said live training video as well):
    By putting the collider on the child of the asteroids you only destroy these and not the parent when exiting the Boundary Collider. I doubt that this is intended.
     
  25. Adam-Buckner

    Adam-Buckner

    Joined:
    Jun 27, 2007
    Posts:
    5,664
    Yes. That's true. There is a version where the collider is on the child, not the parent. It's on my list to fix. Can you remind me if this is on the Video or the Done folder version?
     
  26. rumblemonkey

    rumblemonkey

    Joined:
    Mar 25, 2011
    Posts:
    280
    Hey, great tutorial!

    Just came back to Unity after a hiatus of almost a year working with another engine, zoomed through this without much of an issue, other than the obvious pressing need to have another IDE other than MonoDevelop pronto (seriously, going to have to complain about that, it's bloody awful using something that doesn't even do brackets, indents, etc.- I got spoiled by NetBeans- well, that, and the sheer latency of the awful thing).

    Anyhow, I ran into minor problems with the final bit of the project- presenting the end-game states. The problem is, essentially, an issue with IEnumerator's behavior; it doesn't like being sent variables from outside of the coroutine, so the code you've got just plain doesn't work as written there, in the current build of Unity. It never breaks. Tried various methods to get it to break, realized I was getting nowhere, did some homework, got it fixed, thought I'd share back, as a way to say thanks :)

    This code works:
    Code (csharp):
    1.  
    2. using UnityEngine;
    3. using System.Collections;
    4.  
    5. public class GameController : MonoBehaviour
    6. {
    7.     public GameObject hazard1;
    8.     public GameObject hazard2;
    9.     public GameObject hazard3;
    10.     public Vector3 spawnValues;
    11.     public int hazardCount;
    12.     public float spawnWait;
    13.     public float startWait;
    14.     public float waveWait;
    15.    
    16.     public GUIText scoreText;
    17.     public GUIText restartText;
    18.     public GUIText gameOverText;
    19.  
    20.     private bool gameGoing;
    21.     private bool gameOver;
    22.     private bool restart;
    23.     private int score;
    24.  
    25.     void Start ()
    26.     {
    27.         gameGoing = true;
    28.         gameOver = false;
    29.         restart = false;
    30.         restartText.text = "";
    31.         gameOverText.text = "";
    32.         score = 0;
    33.         UpdateScore ();
    34.         StartCoroutine ("SpawnWaves");
    35.     }
    36.  
    37.     void Update ()
    38.     {
    39.         if(!gameGoing){
    40.             StopCoroutine("SpawnWaves");
    41.         }
    42.         if (restart)
    43.         {
    44.             if (Input.GetKeyDown (KeyCode.R))
    45.             {
    46.                 Application.LoadLevel (Application.loadedLevel);
    47.             }
    48.         }
    49.     }
    50.    
    51.     IEnumerator SpawnWaves ()
    52.     {
    53.         yield return new WaitForSeconds (startWait);
    54.         while (true)
    55.         {
    56.             for (int i = 0; i < hazardCount; i++)
    57.             {
    58.                 Vector3 spawnPosition = new Vector3 (Random.Range (-spawnValues.x, spawnValues.x), spawnValues.y, spawnValues.z);
    59.                 Quaternion spawnRotation = Quaternion.identity;
    60.                 int rand = (int) (Random.value * 3f);
    61.                 if(rand == 0){
    62.                     Instantiate (hazard1, spawnPosition, spawnRotation);
    63.                 } else if(rand == 1){
    64.                     Instantiate (hazard2, spawnPosition, spawnRotation);
    65.                 } else {
    66.                     Instantiate (hazard3, spawnPosition, spawnRotation);
    67.                 }
    68.                 yield return new WaitForSeconds (spawnWait);
    69.             }
    70.             yield return new WaitForSeconds (waveWait);
    71.         }
    72.     }
    73.    
    74.     public void AddScore (int newScoreValue)
    75.     {
    76.         score += newScoreValue;
    77.         UpdateScore ();
    78.     }
    79.    
    80.     void UpdateScore ()
    81.     {
    82.         scoreText.text = "Score: " + score;
    83.         if(score > 100){
    84.             gameGoing = false;
    85.             restart = true;
    86.             gameOverText.text = "You Won!";
    87.             restartText.text = "Press 'R' for Restart";
    88.         }
    89.     }
    90.  
    91.     public void GameOver ()
    92.     {
    93.         gameOverText.text = "Game Over!";
    94.         gameOver = true;
    95.         restartText.text = "Press 'R' for Restart";
    96.         restart = true;
    97.         gameGoing = false;
    98.     }
    99. }
    100.  
    Note that hazard1, hazard2, hazard3 are explicit support for all three asteroids (did a bunch of extra homework along the way) but can be reverted without any impact.

    Probably needs a public int maxScore to support programming a stop-point for newbies.

    Otherwise works as written, should be OK with the stock code. Credits to the explanation about halting IEnumerator coroutines instantly here.

    Anyhow, this was so fun and easy, it's by far the best Unity tutorial I've gone through, definitely worth the time :)
     
  27. Baer

    Baer

    Joined:
    Aug 10, 2013
    Posts:
    5
    I will remind you again, if your new video tutorial comes out.
    The problem currently persists in the downloadable assets (done folder) your provided (I just start this week so it is likely still in there) and it happened as well in your Live Video about the scrolling backgrounds.

    For me the provided code in his video session worked.
    Code (csharp):
    1. IEnumerator SpawnWaves(){
    2.         yield return new WaitForSeconds (startWait);
    3.         while(true)
    4.         {
    5.             for (int i = 0;i<hazardCount;i++)
    6.             {
    7.                 Vector3 spawnPosition = new Vector3 (Random.Range (-spawnValues.x, spawnValues.x), spawnValues.y, spawnValues.z);
    8.                 Quaternion spawnRotation = Quaternion.identity;
    9.                 Instantiate (hazard, spawnPosition, spawnRotation);
    10.                 yield return new WaitForSeconds(spawnWait);
    11.             }
    12.             yield return new WaitForSeconds(waveWait);
    13.  
    14.             if (gameOver)
    15.             {
    16.                 restartText.text ="Press 'R' for Restart";
    17.                 restart = true;
    18.                 break;
    19.             }
    20.         }
    21.     }

    Since when you collide with an asteroide the gameOver flag will be set, the coroutine will enter the break once the current wave has finished.
    This is from the DestroyByContact script:
    Code (csharp):
    1. void OnTriggerEnter(Collider other) {
    2.         if (other.tag == "Boundary")
    3.                         return;
    4.         Instantiate (explosion, transform.position, transform.rotation);
    5.         if (other.tag == "Player") {
    6.                         Instantiate (playerExplosion, other.transform.position, other.transform.rotation);
    7.             gameController.GameOver ();
    8.             }
    9.         gameController.AddScore (scoreValue);
    10.         Destroy(other.gameObject);
    11.         Destroy (gameObject);
    12.     }

    I followed the tutorial 100% percent, so I am pretty sure that this solution works.

    Also regarding your asteroids, Adam provided a done version of this project and he used a container class for all kinds of hazards.
    With 4 different kind of hazards the code/if-sequences are just unnecessary.
     
    Last edited: Aug 10, 2014
  28. Adam-Buckner

    Adam-Buckner

    Joined:
    Jun 27, 2007
    Posts:
    5,664
    Good, that's my memory of it, that this was an error in the Done scene. I'll have to fix that after Unite 14, as I'm hip-deep in getting ready for our training day on the 19th.

    Thanks for the info.
     
  29. Adam-Buckner

    Adam-Buckner

    Joined:
    Jun 27, 2007
    Posts:
    5,664
    Glad to have you back!

    We understand your pain re: Monodevelop. The Feedback site is a good way to let people know what you're feeling about Monodevelop. Depending upon your platform, there could be any number of external solutions.

    Code (csharp):
    1. // (for the code, please see the original post)
    The code in the project should work out of the box. If you are interested in additional hazards, please see the "Done" folder in the project (noting the fact that as of the time of this posting, the colliders are on the wrong GameObject in the Asteroids prefab. This is a simple fix of moving them to the parent.

    If you look at the "Done" material, you'll see that the easiest way to hold the additional hazards is to make a collection, either an Array[] or a generic List<T>.

    The array would be:
    Code (csharp):
    1. public GameObject[] hazards;
    The generic List<T> would be:
    Code (csharp):
    1. using System.Collections.Generic;
    ... at the top of the script and the declaration of:
    Code (csharp):
    1. public List<GameObject> hazards;
    In the Inspector you would add in all of your hazards into the collection, and inside the co-routine, you would select a random hazard with:
    Code (csharp):
    1.  GameObject hazard = hazards [Random.Range(0, hazards.Length)]; // for the Array
    or:
    Code (csharp):
    1.  GameObject hazard = hazards [Random.Range(0, hazards.Count)]; // for the List<T>
    This works because you can identify the "slot" or item in the array by it's zero based index number (the first slot is slot 0). This is written with a variable:
    Code (csharp):
    1. myCollection[indexNumber];
    ... where indexNumber is an int. A specific index number would be something like:
    Code (csharp):
    1. myCollection[5];
    ... to indicate the sixth slot in the collection (as the first slot is 0).

    By using the "RandomRange", this index is a random range from 0 (the first slot) to the "Length" or "Count" (maximum number) of the collection... so this index is simply one random slot within the collection.


    Then you would do the instantiate as normal:
    Code (csharp):
    1. Instantiate (hazard, spawnPosition, spawnRotation);
    Note how changing the name of the initial public variable to "hazards" with an "s" keeps us from having to rewrite the instantiate code.

    When it comes stopping a coroutine, there are a number of ways to do it.

    Yes, StartCoroutine(string) and StopCoroutine(string) are good ways to explicitly stop a CoRoutine, but you must use the string version.

    Other ways are to simply use the keyword "break" as we do in the current code:
    Code (csharp):
    1. if (someValue) break;
    Another valid way is in the "While" loop.

    We could have written:
    Code (csharp):
    1. While (!gameOver) {
    2.    //Code Block
    3. }
    ... and when that gameOver bool is set to true, the while loop ends and the coroutine finishes naturally.

    With the "break;" however, we gain a little more control over cancelling the coroutine. In the current code, we have a Game Over state that is before the Restart State. By going straight to the Game Over state, there isn't that pause where the screen clear of the hazards...
     
  30. rumblemonkey

    rumblemonkey

    Joined:
    Mar 25, 2011
    Posts:
    280
    @Baer: That code from the final page of the project compiles fine, but when tested, it didn't ever break, regardless of the state of gameOver, at least over here. Nor did using stuff like: if(gameover) yield break; in the coroutine.

    After reading the article I posted about how to halt IEnumerators, I'm wondering why the code in the project is working for anybody; perhaps in a different OS, Unity's able to pass the boolean in properly. I'm apparently not the only person to have encountered problems with this though :)

    Anyhow, I'm still getting my head moving from Java-land to C#, so I'm not sure what else to look at; as you can see, there aren't any special conditions happening in my re-written code that significantly changes the behavior- but my code worked, whereas the example code compiled but did not work correctly re: break.

    @Adam Buckner: on the hazards using an array, yeah, that is definitely the right way, I agree. Sorry for the sloppy implementation example, I haven't looked at C# in a year so I did it in the most basic way I could to save myself time :)
     
  31. Adam-Buckner

    Adam-Buckner

    Joined:
    Jun 27, 2007
    Posts:
    5,664
    Could you post the code that you were using that didn't work? I'd like to look at it, and perhaps we could see why it wasn't working for you.

    This is the code from the "Done" scene:

    Code (CSharp):
    1.     IEnumerator SpawnWaves ()
    2.     {
    3.         yield return new WaitForSeconds (startWait);
    4.         while (true)
    5.         {
    6.             for (int i = 0; i < hazardCount; i++)
    7.             {
    8.                 GameObject hazard = hazards [Random.Range (0, hazards.Length)];
    9.                 Vector3 spawnPosition = new Vector3 (Random.Range (-spawnValues.x, spawnValues.x), spawnValues.y, spawnValues.z);
    10.                 Quaternion spawnRotation = Quaternion.identity;
    11.                 Instantiate (hazard, spawnPosition, spawnRotation);
    12.                 yield return new WaitForSeconds (spawnWait);
    13.             }
    14.             yield return new WaitForSeconds (waveWait);
    15.          
    16.             if (gameOver)
    17.             {
    18.                 restartText.text = "Press 'R' for Restart";
    19.                 restart = true;
    20.                 break;
    21.             }
    22.         }
    23.     }
    Now, the only thing I can think of that could be an issue is spelling?

    Could you have used "gameover" instead of "gameOver"? If so, this would cause the entire block to be ignored.
     
  32. rumblemonkey

    rumblemonkey

    Joined:
    Mar 25, 2011
    Posts:
    280
    Sure thing. This is one of the things I tried:

    Code (csharp):
    1.  
    2.   IEnumerator SpawnWaves ()
    3.    {
    4.      if (!gameGoing) yield break;
    5.      yield return new WaitForSeconds (startWait);
    6.      while (true)
    7.      {
    8.        for (int i = 0; i < hazardCount; i++)
    9.        {
    10.          Vector3 spawnPosition = new Vector3 (Random.Range (-spawnValues.x, spawnValues.x), spawnValues.y, spawnValues.z);
    11.          Quaternion spawnRotation = Quaternion.identity;
    12.          int rand = (int) (Random.value * 3f);
    13.          if(rand == 0){
    14.            Instantiate (hazard1, spawnPosition, spawnRotation);
    15.          } else if(rand == 1){
    16.            Instantiate (hazard2, spawnPosition, spawnRotation);
    17.          } else {
    18.            Instantiate (hazard3, spawnPosition, spawnRotation);
    19.          }
    20.          yield return new WaitForSeconds (spawnWait);
    21.        }
    22.        yield return new WaitForSeconds (waveWait);
    23.      }
    24.    }
    25.  
    Where gameGoing is a boolean, set to true in Start() before the coroutine is created, set to false in GameOver() (which worked just fine).
     
  33. rumblemonkey

    rumblemonkey

    Joined:
    Mar 25, 2011
    Posts:
    280
    And on the spelling stuff... shouldn't that have failed to compile at all? Because it compiled... it just never did stop the wave generation. It's like the boolean change to gameOver never happened. on UnityAnswers, it appears that others have seen some odd behaviors with passing data into IEnumerators as well.
     
  34. Baer

    Baer

    Joined:
    Aug 10, 2013
    Posts:
    5
    Hey @rumblemonkey, I think I know where your problem is.

    You ask for the gameGoing status at the beginning of the Coroutine, but we only start the coroutine ONCE!
    After you ask for the gameGoing status, you go into an infinite loop, never asking for gameGoing again. Just put the if-statement inside the while-loop.

    This should fix your issue:

    Code (csharp):
    1.  
    2. IEnumerator SpawnWaves (  {
    3. yield return new WaitForSeconds (startWait);
    4.      while (true)
    5.      {
    6.        for (int i = 0; i < hazardCount; i++)
    7.        {
    8.          Vector3 spawnPosition = new Vector3 (Random.Range (-spawnValues.x, spawnValues.x), spawnValues.y, spawnValues.z);
    9.          Quaternion spawnRotation = Quaternion.identity;
    10.          int rand = (int) (Random.value * 3f);
    11.          if(rand == 0){
    12.            Instantiate (hazard1, spawnPosition, spawnRotation);
    13.          } else if(rand == 1){
    14.            Instantiate (hazard2, spawnPosition, spawnRotation);
    15.          } else {
    16.            Instantiate (hazard3, spawnPosition, spawnRotation);
    17.          }
    18.          yield return new WaitForSeconds (spawnWait);
    19.        }
    20. if (!gameGoing) yield break; // !!!!!!!!!!CODE INSIDE THE WHILE LOOP !!!!!!!!!!
    21.        yield return new WaitForSeconds (waveWait);
    22.      }
    23.    }
    If you tried this as well and it still doesn't work for you, you should put the gameGoing statement inside the debug.log and see if it changes or not.
     
    Last edited: Aug 11, 2014
  35. rumblemonkey

    rumblemonkey

    Joined:
    Mar 25, 2011
    Posts:
    280
    @Adam Buckner:

    Kept messing with this tutorial as a base. This resulted :)

    Once again, thank you very much for providing such a clean-cut tutorial :)
     
  36. danimandiri

    danimandiri

    Joined:
    Mar 5, 2014
    Posts:
    19
    It doesnt work playing in Lenovo Tab3000, the game only using Taping to make fire, the controller like joystick is unavailable, wouldyou fix that? I try to fix that but i am stuck
     
  37. danimandiri

    danimandiri

    Joined:
    Mar 5, 2014
    Posts:
    19
    Hello any helper for me
     
  38. Baer

    Baer

    Joined:
    Aug 10, 2013
    Posts:
    5
    How about some more information like your code your current build and where you are stuck?
     
  39. Adam-Buckner

    Adam-Buckner

    Joined:
    Jun 27, 2007
    Posts:
    5,664
    Totally cool!

    Fantastic!

    I've been so busy catching up after getting ready for Unite and then digging out from under, I missed that.

    It's great!
     
  40. Adam-Buckner

    Adam-Buckner

    Joined:
    Jun 27, 2007
    Posts:
    5,664
    Can you be more explicit about that the problem is and what you've done to fix it?
     
  41. danimandiri

    danimandiri

    Joined:
    Mar 5, 2014
    Posts:
    19
    The game space shooter i build into android without nothing change the code, it's ok playing in PC but when in android it useless because can not using joystick
     
  42. Adam-Buckner

    Adam-Buckner

    Joined:
    Jun 27, 2007
    Posts:
    5,664
    Yes. This tutorial presumes you are deploying for a "keyboard and mouse" device.

    You will have to modify this project to work with a touch device.

    To learn more about touch input, check the documentation and check the learn section of our web site.

    Translating this project to mobile would be a good exercise and will help you get to know Unity better.
     
  43. danimandiri

    danimandiri

    Joined:
    Mar 5, 2014
    Posts:
    19

    Perhaps you can help us, like where the script files should change to modify in mobile android
     
  44. Adam-Buckner

    Adam-Buckner

    Joined:
    Jun 27, 2007
    Posts:
    5,664
    You need to replace your keyboard and mouse input with touch input.

    Look at your scripts and find where there are instances of Input.GetAxis (you can look these up in the documentation and tutorials if you are unclear how the work) and replace them with input from touches.

    To find out how to use touches, you should check the documentation and the learn site.

    Here is a video on Multi-touch input:
    http://unity3d.com/learn/tutorials/modules/beginner/platform-specific/multitouch-input

    Here is a video on Accelerometer Input:
    http://unity3d.com/learn/tutorials/modules/beginner/platform-specific/accelerometer-input

    Here is a video on Mobile Development:
    http://unity3d.com/learn/tutorials/modules/beginner/live-training-archive/mobile-development

    Here is documentation on Touches:
    http://docs.unity3d.com/Manual/MobileInput.html
    http://docs.unity3d.com/ScriptReference/Touch.html
     
  45. Adam-Buckner

    Adam-Buckner

    Joined:
    Jun 27, 2007
    Posts:
    5,664
  46. Nightgaunt

    Nightgaunt

    Joined:
    Jan 15, 2014
    Posts:
    7
    Hey,

    first of all, I want to thank you for the good introduction tutorial to Unity. I'm currently studying (web development) JavaScript at school so I thought I'd give Unity a whirl since I love gaming. Anyway, I did the Roll-A-Ball and completed the "first chapter" of the Space Shooter if you so will. Now I am in the process of doing the undocumented "chapter two", adding hazards and whatnot to spice up the gameplay a bit.

    I have a weird problem, though. I can't seem to get the boundary collider to work correctly. Some of my player ship bolts do get destroyed (well, most of them), but some are not and they float endlessly forward in z-axis. I tried to shoot many bolts during gameplay and then pausing, to inspect the bolts closer, and they had rightout crazy positions. I can in some way understand that the pos.x and pos.z varies, but some of them got rotation also, and always only on the z-axis.

    I have tried to look at your code and do everything alike, but it doesn't work. Also, enemy ships and asteroids floating by my ship are not being destroyed either, and neither are enemy bolts. Does it have something to do with placement, where they spawn? I suspect the boundary collider but it's very weird that it works sometimes in the other direction.

    If you need to see my codes or something, just tell me which one you want to look at and I'll show you.

    Edit: Okay, I found out what is causing the problem - something hits the boundary collider and destroys it, after which anything is free to continue it's ride forever. I have no idea how to fix this, though.

    The rotated shots I figured was because of the tilt on the player ship.

    Edit2: Okay, for some reason I had added my DestroyByBoundary script to the enemy ship, which kept destroying the boundary after which things went to hell. It's working now :)

    Is there a way to make the enemy ship fire two lasers at the same time?
     
    Last edited: Sep 22, 2014
  47. Adam-Buckner

    Adam-Buckner

    Joined:
    Jun 27, 2007
    Posts:
    5,664
    Yay! Glad you got it working. Debugging little issues is always the developer's nightmare, and learning ways to divide and conquer just takes time and patience.

    Yes, this is possible. I believe that the shots are spawned at "spawnPoint.position" and "spawnPoint.rotation", and probably should be aligned to the world for perfectly flat rotation, but this would require taking a new Vector3 with x, y, z values of (0.0f, spawnPoint.rotation.y, 0.0f); which was an extra layer of complication for what is otherwise relatively simple.

    Yes, you can make two spawn points in a list or array:
    Code (csharp):
    1. public Transform spawnPoints;
    ... and when you fire you can say (roughly):
    Code (csharp):
    1. foreach (var spawnPoint in spawnPoints) {
    2.      Instantiate (shot, spawnPoint.position, new Vector3 ((0.0f, spawnPoint.rotation.y, 0.0f));
    3. }
    ps: (iirc) the actual variable name was "shotSpawn", so you could use "shotSpawns", or "muzzles" or "guns" - whatever works for you and the project.
     
  48. Nightgaunt

    Nightgaunt

    Joined:
    Jan 15, 2014
    Posts:
    7
    So, this code is to be inserted in WeaponController? And the foreach-thing inside void Fire? This is the script right now but obviously it isn't working. I can't even get the array to work.

    Code (csharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class WeaponController : MonoBehaviour
    5. {
    6.    public GameObject shot;
    7.    public GameObject[] muzzles;
    8.    public Transform shotSpawn;
    9.    public float fireRate;
    10.    public float delay;
    11.  
    12.    void Start ()
    13.    {
    14.      InvokeRepeating ("Fire", delay, fireRate);
    15.    }
    16.  
    17.    void Fire ()
    18.    {
    19.      foreach(var shotSpawn in shotSpawns)
    20.      {
    21.        Instantiate(shot, shotSpawn.position, shotSpawn.rotation);
    22.        audio.Play();
    23.      }
    24.    }
    25. }
     
  49. Adam-Buckner

    Adam-Buckner

    Joined:
    Jun 27, 2007
    Posts:
    5,664
    Ah - There are a few mistakes in your code.

    Your first error is public GameObject[] muzzles. Not public Transform[] muzzles.

    You need: public Transform[] muzzles.

    You can get a list of GameObjects with GameObject[], it's not illegal at all, but you will then need to find the transform on those GameObjects with muzzle.Transform.position... so you might as well just grab the Transform in the first place.

    What you are doing with public Transform[] muzzles is defining the list of guns (and you could have as many as you wanted here! 2, 10, 20, 100!).

    The next error is you don't need publicTransform shotSpawn; as you will be using your public Transform[] muzzles instead. The line public Transform[] muzzles replaces publicTransform shotSpawn;

    Lastly, you need to call your muzzles collection, not shotSpawn in fire. You chose to use "muzzles" as your name when defining the collection, but didn't use "muzzles" within the foreach loop.

    You need foreach (var muzzle in muzzles)... and then you will need to propagate that name into the rest of your code, notably the instantiate line...

    Or you need to say foreach (var shotSpawn in muzzles)...

    Essentially, you've added some of the things I've mentioned a bit willy-nilly without following / propagating the logic thru the rest of the script.

    Good first go, but now it needs some untangling and polish! The logic needs to follow all the way thru the script. You should be able to trace and follow the logic like wires from start to finish.

    Does this make sense?
     
  50. Nightgaunt

    Nightgaunt

    Joined:
    Jan 15, 2014
    Posts:
    7
    Thank you, Adam.

    As you can probably see from my code, I'm very new to C# and how the arrays work in it, since my only experience would be from JavaScript and it differs quite a lot from that. Anyway, I don't quite understand why the muzzles weren't showing up in Inspector right from the beginning, but I did the polish, as you put it, and it works now.

    I also got the scrolling background to work, so now I only need the evasion for the enemy ships, and the nebulas.
     
Thread Status:
Not open for further replies.