Search Unity

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. Adam-Buckner

    Adam-Buckner

    Joined:
    Jun 27, 2007
    Posts:
    5,664
    There is no know problem with Space Shooter and any particular device.

    I would try standard trouble shooting (making sure the build is correct, etc), and if no problems are found, you can reports problem as me big report.

    The only thing to keep in mind is that tablets often have large amounts of screen space to fill and can be slower compared to a phone with a smaller screen size. Fill rate comes to mind.

    If you can get data, check to see if a similar project runs well on the phone but slowly on the tablet, then it could be the tablet. I have heard of tablets still under performing even with "stronger chipsets" because the graphics requirements on the tablets exceed the strength of the chips.
     
  2. Beta4

    Beta4

    Joined:
    Nov 6, 2014
    Posts:
    34
    Thank you for the help... I am sorry for the late reply- work has kept me super busy. Thank you again :)
     
  3. Beta4

    Beta4

    Joined:
    Nov 6, 2014
    Posts:
    34
    So I am still learning a lot with Unity so first of all, thank you for your patience. I was doing the tutorial to the Space Shooter game and I was trying to clone the shot to make it shoot 3 shots. The effect I want is 3 simultaneous shots shooting from the player ship- the middle one is a bit more forward than the side shots.

    The code right now is shooting all 3 shots however, the clones I want on either side of the middle shot are appearing over it, making the player ship look like it's shooting 1 shot. I would like to know what I'm doing wrong to make the code Instantiate all 3 shots at once properly when the space bar is pressed.

    Code (CSharp):
    1.      void Update ()
    2.      {
    3.          if (Input.GetKeyDown("space") && Time.time > nextFire)
    4.          {
    5.              nextFire = Time.time + fireRate;
    6.              Instantiate(shot, shotSpawn.position, shotSpawn.rotation);
    7.              GameObject clone1 = (GameObject)Instantiate(shot, shotSpawn.position, shotSpawn.rotation);
    8.              clone1.transform.eulerAngles = new Vector3(transform.position.x - 0.35f, transform.position.y, (transform.localScale.y / 2));
    9.              GameObject clone2 = (GameObject)Instantiate(shot, shotSpawn.position, shotSpawn.rotation);
    10.              clone2.transform.eulerAngles = new Vector3(transform.position.x + 0.35f, transform.position.y, (transform.localScale.y / 2));
    11.              audio.Play ();
    12.          }
    13.      }
    14.  
    Here is the C# code, any help would be appreciated. Thanks again.
     
  4. Adam-Buckner

    Adam-Buckner

    Joined:
    Jun 27, 2007
    Posts:
    5,664
    Well, with that code, you are not changing the position of the shot, but the rotation of the shot with transform.eulerAngles. Then the Vector3 value (which is a float, float, float value) you are setting the rotation to is based on the position... AND this is affecting the transform.eulerAngles.x which would send it down or up from the plane.

    What you need to do is set the trasform.position.x!

    You could also make a spawn point for each "muzzle" or "gun".

    Then you could place or point the spawn points in any position or direction you want them.

    Then loop through the muzzles like:

    Code (csharp):
    1. public Transform[] spawnPoints;
    2.  
    3. void Update () {
    4.    if (Input.GetKeyDown ("space") && Time.time > nextFire) {
    5.        nextFire = Time.time + fireRate;
    6.        foreach (var spawnPoint in spawnPoints) {
    7.           Instantiate (shot, spawnPoint.position, spawnPoint.rotation);
    8.        }
    9.        audio.Play();
    10.    }
    11. }
    Note: I've just whipped this out without testing... but it should work and you should be able to get the idea from that.
     
  5. Beta4

    Beta4

    Joined:
    Nov 6, 2014
    Posts:
    34
    Ok I guess I'm still learning lol how about help with the way I wrote it...
    While i get the shots working the way i want them...only the middle shot follows the player ship. The other 2 start don't go any higher than where the ship first spawn. They do follow the ship side by side on the x axis but when the ship travels on the z axis to go foward, they do not travel with the player ship - just like it would if the ship could only travel from left to right on the x axis like "Space Invaders". I just cant get it figured out... again thanks for putting up with this rookies question and problems :p

    Code (CSharp):
    1.     void Update ()
    2.     {
    3.         if (Input.GetKeyDown("space") && Time.time > nextFire)
    4.         {
    5.             nextFire = Time.time + fireRate;
    6.             Instantiate(shot, shotSpawn.position, shotSpawn.rotation);
    7.  
    8.             Vector3 position0 = new Vector3(transform.position.x - 0.35f, transform.position.y);
    9.             Instantiate(shot, position0, shotSpawn.rotation);
    10.  
    11.             Vector3 position1 = new Vector3(transform.position.x + 0.35f, transform.position.y);
    12.             Instantiate(shot, position1, shotSpawn.rotation);
    13.  
    14.             audio.Play ();
    15.         }
    16.     }
    Thanks again Adam.
     
  6. Adam-Buckner

    Adam-Buckner

    Joined:
    Jun 27, 2007
    Posts:
    5,664
    Without looking very hard, I see that you are assigning your Vector3 with only 2 values, afaict. You should have 3 float values in a Vector3. Do you have no errors with this code? You should have:
    Code (csharp):
    1. new Vector3 (x, y, z);
    ... but I only see:
    Code (csharp):
    1. x = transform.position.x - 0.35f
    2. y = transform.position.y
    3. z = ??
    I don't see a z value.

    Also, be aware that the first shot is spawned at the "spawn point" transform, and the second two are spawned based on the transform holding the script, which is presumably the player ship. Just be aware that these are inconsistent... yet all 3 use the spawn point's rotation, which could be different from transform rotation. In this case, you're probably safe, as the spawn point is a child of the player ship and should be aligned the same.

    Just think about what you are doing: The Vector3 holds 3 float values and is convenient to use. These float values must have meaning related to the transform of the shot. The transform of the shot has 3 important values: Position, Rotation and Scale. We need to set this transform's Position and Rotation when we spawn it (Scale is assumed to be 1, 1, 1). You need to feed relevant Vector3 values to both the transform's Position and Rotation. The spawn point has this information as part of it's own transform. In the first instance, you are setting the shot's transform position and rotation to match that of the shot spawns transform position and rotation:
    Code (csharp):
    1. Instantiate(shot, shotSpawn.position, shotSpawn.rotation);
    Make sure you are being just as relevant in the other two instantiate calls.

    You are setting the shot's transform position and rotation to <something>, what is it supposed to be?

    -

    When it comes to that code, it's generally "best practice" that if you ever write the same thing multiple times, you're doing something wrong. Usually this means putting the code in a loop of some sort.
     
  7. Beta4

    Beta4

    Joined:
    Nov 6, 2014
    Posts:
    34
    LOL Yes you are correct... I really need to pay better attention. It works now- thank you so much for your help.
    You Da' Man Adam.

    Hopefully one day I become a Unity Expert as yourself.
    Thank you so much again. Have a great Thanksgiving!
     
  8. Adam-Buckner

    Adam-Buckner

    Joined:
    Jun 27, 2007
    Posts:
    5,664
    Here is a quick example video where I create a script using a foreach loop to instantiate shots at each spawn point in a collection of spawn points:



    This is a quick example of putting spawn points into a collection (in this case a standard array) and looping thru them to instantiate a prefab.

    In the second part, the example applies this to the situation of instantiating lazer bolts from the Space Shooter Tutorial.

    This will show that it's not only easy to use, but flexible and versatile when it comes to changing or adding new spawn points...

    ... and no coding is necessary after the script is first saved.
     
  9. lxkosxl

    lxkosxl

    Joined:
    Nov 28, 2014
    Posts:
    5
    Hey guys, General noob here but fast learner, Sailed through rollaball and nightmare and now the spaceshooter.. and now.. I am trying to do some of the things ive seen others posting about in this thread, IE. "make asteroids burst into smaller asteroids" and add some scrolling background???(tht will definatly have to wait). Anyways. after reading through the thread and finding someone say: "edit destroyByContact on the main asteroid, when the asteroid is destroyed you can use a loop to instantiate 5 smal asteroids. just make a new small asteroid prefab much like the larger one, but instead of giving it just a velocity in the -Z make it a random Z and X velocity. and instantiate from the transform position of the large asteroid that u destroyed." Issue is i am having a hell of a time racking my head against the wall trying to come up with the code to instantiate from a destroyed object. I guess i dont know if i should use an "IF/ELSE" or a Switch statement??..a complete new code to instantiate the smallers on destroy??? lol idk I'm not asking for you to write the code I just need a pointer in the right direction to research what I'm trying to do..

    Edit: after going back through the scripting videos this is what i have come up with inside the OnTriggerEnter...Instantiate(smallAsteroid, transform.position, Quaternion.identity);

    Ive got it to destroy the big asteroid into the small asteroid prefab ive made and when i destroy the small asteroid it does the asteroid explosion.. Now how to make that one big one into several little ones flying off in random directions..??
    Also sry idk how to post code snippets like a baller yet. xD Ty all!!
     
    Last edited: Nov 28, 2014
  10. Adam-Buckner

    Adam-Buckner

    Joined:
    Jun 27, 2007
    Posts:
    5,664
    In brief: Look for where you are instantiating the explosion and add code to instantiate a number of small asteroids.

    You don't need a new prefab if you don't want one.

    You could have:
    Code (csharp):
    1. int numberOfAsteroids = Random.Range (minNumber, maxNumber);
    2. for (int i = 0; i < numberOfAsteroids; i++) {
    3.    GameObject newAsteroid = <Insert Instantiate Code Here Cast "as GameObject">;
    4.    newAsteroid.transform.localScale = new Vector3 (<insert some value - set or random - here>);
    5.    Rigidbody asteroidsRB = newAsteroid.GetComponent<Rigidbody>();
    6.    asteroidRB.velocity = new Vector3 (<insert: Random x, 0, random z; value here>);
    7. }
    This is untested "back pocket" code, but you should get the idea.

    For the random Vector3 velocity, look at the same "inside unit sphere" for the tumble, but reset the y value to 0... or sift thru the Random class to see if there is anything else you prefer.
     
  11. anohinoyume

    anohinoyume

    Joined:
    Nov 28, 2014
    Posts:
    1
    Hi,
    I have been messing with the code for the enemies and was wondering how to program them to evade asteroids. I made my asteroids to spawn with a random trajectory, so they dont move strainght along the z-Axis. My code to do this currently looks like this:
    Code (CSharp):
    1. rigidbody.velocity = new Vector3 (Random.Range (-0.6f, 0.6f), 0.0f, 1.0f) * -speed;
    Currently i get all GameObjects with certain tags and return the nearest of them. Then i look if an intersection will happen. I currently use the following function to return the nearest GameObject to the enemy ship:
    Code (CSharp):
    1. GameObject ClosestHazard(string[] ObjectTags)
    2.     {
    3.         GameObject[][] aHazard = new GameObject[ObjectTags.Length][];
    4.        
    5.         for (int i = 0; i < ObjectTags.Length; i++) {
    6.             aHazard[i] = GameObject.FindGameObjectsWithTag (ObjectTags[i]);
    7.         }
    8.  
    9.         GameObject closestHazard = null;
    10.         Vector3 mePosition = transform.position;
    11.  
    12.         float distance = Mathf.Infinity;      
    13.  
    14.         for (int tHazard = 0; tHazard < ObjectTags.Length; tHazard++) {
    15.             for (int nHazard = 0; nHazard < aHazard[tHazard].Length; nHazard++) {
    16.  
    17.                 if (aHazard[tHazard][nHazard].GetHashCode () == gameObject.GetHashCode ()) {
    18.                     continue;
    19.                 }
    20.                
    21.                 Vector3 diff = aHazard[tHazard][nHazard].transform.position - mePosition;
    22.                 float curDistance = diff.sqrMagnitude;
    23.  
    24.                 if (curDistance < distance) {
    25.                     closestHazard = aHazard[tHazard][nHazard];
    26.                     distance = curDistance;
    27.                 }
    28.             }
    29.         }
    30.  
    31.         return closestHazard;
    32.     }
    Afterwards I currently use this code to do the normal manouvers and also steer the enemies away from probable intersections (and only do something if they occur in the game boundaries):
    Code (CSharp):
    1. public static bool NearlyEqual(float f1, float f2, float fLimit)
    2.   {
    3.   return Mathf.Abs (f1 - f2) < fLimit;
    4.   }
    5.  
    6. void FixedUpdate ()
    7.     {
    8.         Vector2 hazardVelocity;
    9.         Vector2 hazardPosition;
    10.         Vector2 mePosition;
    11.         Vector2 meVelocity;
    12.  
    13.         string[] HazardTags = new string[] { "Asteroid", "Enemy" };
    14.        
    15.         GameObject Hazard = ClosestHazard (HazardTags);
    16.  
    17.         float newManeuver = Mathf.MoveTowards (rigidbody.velocity.x, targetManeuver, smoothing * Time.deltaTime);
    18.         rigidbody.velocity = new Vector3 (newManeuver, 0.0f, currentSpeed);
    19.         rigidbody.rotation = Quaternion.Euler (0, 0, rigidbody.velocity.x * -tilt);
    20.  
    21.         hazardPosition.x = Hazard.rigidbody.position.x;
    22.         hazardPosition.y = Hazard.rigidbody.position.z;
    23.         hazardVelocity.x = Hazard.rigidbody.velocity.x;
    24.         hazardVelocity.y = Hazard.rigidbody.velocity.z;
    25.  
    26.         mePosition.x = rigidbody.position.x;
    27.         mePosition.y = rigidbody.position.z;
    28.         meVelocity.x = rigidbody.velocity.x;
    29.         meVelocity.y = rigidbody.velocity.z;
    30.  
    31.         float tx, ty;
    32.  
    33.         ty = (mePosition.y - hazardPosition.y) / hazardVelocity.y;
    34.         tx = (mePosition.x - hazardPosition.x) / hazardVelocity.x;
    35.  
    36.         if ( NearlyEqual (tx, ty, 0.75f) ) {
    37.             Vector2 Intersection;
    38.  
    39.             Intersection = hazardPosition + tx * hazardVelocity;
    40.  
    41.             if ((Intersection.x >= CollisionBoundary.x_min && Intersection.x <= CollisionBoundary.x_max) &&
    42.                 (Intersection.y >= CollisionBoundary.z_min && Intersection.y <= CollisionBoundary.z_max)) {
    43.  
    44.                
    45.                 rigidbody.velocity = new Vector3 (mePosition.x - Intersection.x, 0.0f, mePosition.y - Intersection.y);
    46.             }
    47.         }
    48.     }
    Somehow this does only work partly, as only some enemies steer away from asteroid. Ohers steer into them, if they appear from above the enemy ship.
    Thanks
     
  12. lxkosxl

    lxkosxl

    Joined:
    Nov 28, 2014
    Posts:
    5
    barely grasping the concept, I tried the code. adding my own into it . nothing but failure.. lol idk man maybe my confidence in myself is greater than my ability and knowledge i had already made a prefab, i was under the impression i had to have a prefab of the smaller asteroid.. okay well still idk what im doing wrong its probably something basic and freaking stupid that i havent caught cause im a noob but this is what it looks like now...
    Code (CSharp):
    1. public int numberOfAsteroids = 5;
    2. Instantiate(explosion, transform.position, transform.rotation);
    3.  
    4.         for (int i = 0; i < numberOfAsteroids; i++)
    5.         {
    6.             GameObject smallAsteroid = Instantiate(smallAsteroid, explosion.transform.postion, explosion.transform.rotation);
    7.             smallAsteroid.transform.localScale = new Vector3 (Random, 0.0f, Random);
    8.             Rigidbody asteroidsRB = smallAsteroid.GetComponent<Rigidbody>();
    9.             asteroidsRB.velocity = new Vector3 (Random.insideUnitSphere, 0.0f Random.insideUnitSphere);
    10.         }
     
    Last edited by a moderator: Nov 29, 2014
  13. Adam-Buckner

    Adam-Buckner

    Joined:
    Jun 27, 2007
    Posts:
    5,664
    Ok - A couple of things:

    You're probably getting some errors... In which case you should try to fix each one, one at a time, starting with the first one at the top.

    If you have trouble, you can copy and past the error from the lower box in the console:


    You can ask for help one error at a time until you understand it.

    Now, I can *guess* you're having some issues with a few things I see (off the top of my head...):

    • When instantiating an object, this is a generic Unity Object, but Unity needs to know what type of object if you are trying to use it, so you need to "cast" the UnityObject into a specific Type - in this case a "GameObject". You can see this if you read the documentation on "Instantiate". (You can click on the word "Instantiate" in the code pasted here for a link... or use cmd/xctrl + ' in Monodevelop)

    • Random is a class - but you need to use one of the functions or variables in the Random class to make this work. (Again, you can click on the work "Random" in the code pasted here for a link... or use cmd/xctrl + ' in Monodevelop) Take a look at Random.Range() for a float value, or look at Random.insideUnitSphere or Random.onUnitySphere to get a random Vector3. Be aware that when using something that gives you a random Vector3, you will then need to set the "y value" of the Vector3 back to 0 when dealing with the Rigidbody's velocity, but not when dealing with the Transform's local scale.

    • A float is a single decimal number. Any of these are float values: 1.1, -0.0025, 3.14159, 10000.1

    • A Vector3 is made up of 3 floats Vector3 (1.1, -0.0025, 3.14159) or shown generically as Vector3 (x, y, z)

    • When setting the localScale, you're using the Random class but not specifying *what* you want from the Random class. You either need to use 1 Random.insideUnitSphere for the entire Vector3, or get a Random.Range for each float value.

    • Currently you are getting random values of x and z but not y, which is 0. This means you are setting the new small asteroid to a scale that is random on the width and depth, but has a height of 0, so this new asteroid has no volume and doesn't exist in 3D space - it's now a 2D object on the XZ plane.

    • When setting the Velocity, you're using Random.insideUnitSphere, which returns a Vector3 value, but you are trying to set the x value to a new (x, y, z) value, which just doesn't work - and you're doing the same thing to the z, as well. You either need to use 1 Random.insideUnitSphere (or onUnitSphere) for the entire Vector3 - and then set the y value to 0, or get a Random.Range for x and z and set y to zero. You need y = 0, so the asteroid stays on the game plane, and doesn't shoot off - up or down - and leave the game area. E.G.: You want NO y velocity, and keep all the movement on the game plane (x and z).

    • I just noticed that you are trying to use the "explosion.transform.position"... I can kind of see the intent here... but the explosion is a prefab in the assets folder, and won't be instantiated in the scene... so the transform position of the prefab could be anything, tho' it's probably (0, 0, 0)... and this won't change as it's set in the prefab asset. You want to instantiate these new asteroids near each other in the same place as the explosion = e.g.: where the object was destroyed... or simply "transform.position", just like the explosions.

    -

    I do have a question, however: Did you want these asteroid to be "interactable"? Did you want them to blow up the ship if they hit the player? Did you want the player to be able to shoot these small asteroids?

    If so, you'll need to set the physics collision layers so these small asteroids don't collide with each other, or that first frame you create them, they will all be physical objects with collision volumes - all in the same space... and it could cause problems.
     
  14. sporadicallyjoe

    sporadicallyjoe

    Joined:
    Nov 30, 2014
    Posts:
    4
    I have just completed the "Boundary" portion of the Space Shooter tutorial. I've redone this portion multiple time, because when my boundary is active, my shots only travel half the length of the screen.

    Does anyone know why this might be?
    Screenshot (51).png
    Screenshot (52).png
     
  15. sporadicallyjoe

    sporadicallyjoe

    Joined:
    Nov 30, 2014
    Posts:
    4
    The solution to the above problem is to increase the scale of the Y axis on the boundary. The value of "8" worked best for me.
     
  16. sarahell

    sarahell

    Joined:
    Nov 30, 2014
    Posts:
    1
    Hi, this is my first time using unity and I am having trouble with shooting shots. I followed the code, and I used this fix and I still can't shoot. I am wondering if I need to declare a button as the fire button, but the code doesn't say anything about that. Any suggestions?

     
    Last edited by a moderator: Dec 1, 2014
  17. Adam-Buckner

    Adam-Buckner

    Joined:
    Jun 27, 2007
    Posts:
    5,664
    Just a thought... could it be that your spawn points are not aligned with the XZ plane? Could they have a slight tilt to them, so the shots are travelling slightly up or down in the scene volume?
     
  18. Adam-Buckner

    Adam-Buckner

    Joined:
    Jun 27, 2007
    Posts:
    5,664
    The "fire1" should be a default definition in the Input Manager. If you have not changed any settings in the input manager, then this should work "out of the box".

    Can you paste your code here, so we can look at it?

    Don't forget to use code tags properly:
    http://forum.unity3d.com/threads/using-code-tags-properly.143875/
     
  19. rkmax

    rkmax

    Joined:
    Nov 25, 2014
    Posts:
    2
    Thanks for the advice Adam.
     
  20. Beta4

    Beta4

    Joined:
    Nov 6, 2014
    Posts:
    34
    Hello guys, I was wondering if I could get some advice or help.
    I am wanting to spawn my enemy units with a random speed - while i set my currentspeed float as public to see that it is in fact moving at random speed in the inspector, it is not however showing up on my projectile as a random speed. I have included the code with some commented out stuff that I have also tried:

    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.                 currentSpeed = Random.Range(MaxSpeed, MinSpeed);
    9.                 float amountToMove = currentSpeed * Time.deltaTime;
    10.  
    11.                 Vector3 spawnPosition = new Vector3(Random.Range(-spawnValues.x, spawnValues.x), spawnValues.y, spawnValues.z);
    12.                 Quaternion spawnRotation = Quaternion.identity;
    13.                 var enemyObject = Instantiate(hazard, spawnPosition, spawnRotation) as GameObject;
    14.                 //enemyObject.rigidbody.AddForce(Vector3.down * amountToMove);
    15.                 enemyObject.rigidbody.velocity = transform.forward * amountToMove;
    16.                 //rigidbody.velocity.z = Random.Range(MaxSpeed, MinSpeed);
    17.                 yield return new WaitForSeconds (spawnWait);
    18.             }
    19.             yield return new WaitForSeconds (waveWait);
    20.         }
    21.     }
    Thanks again :)
     
  21. OboShape

    OboShape

    Joined:
    Feb 17, 2014
    Posts:
    836
    Morning Beta,

    just reading, thought i would see what i can see while im on a break at work.

    couple of things i would check,
    currentSpeed, is the maxSpeed and minSpeed floats or integers? as Random.Range can take int or float as parameters. ie return a random int, or a random float.

    amountToMove variable. dont think this is required here, as by applying an initial velocity to the asteroid and sending it on its merry way, the physics rigidbody will take care of it as long as it lives.
    you would use something like that if you were creating movement to be smooth over time, but in your case, let physics handle it.

    as a note, have a look at
    http://unity3d.com/learn/tutorials/modules/beginner/scripting/delta-time
    give you a better idea on what it is, basically its the time taken to load one frame to the next, usually quite small like 0.03f or something, so you can see from that how multiplying that by your currentSpeed would be really small.

    this SpawnWaves() is purely for managing instantiation of asteroids, the mover.cs script attached to each enemy and shot prefab does the moving within its Start() function. much like you have done after your instantiate, you have set the velocity of the rigidbody once and away it goes.

    have a try at commenting out line 9 on your script.
    and ammend line 15 to the following.
    Code (CSharp):
    1.  
    2. enemyObject.rigidbody.velocity= transform.forward * currentSpeed;
    3.  

    let us know if that works or not please.
    Cheers
     
  22. Beta4

    Beta4

    Joined:
    Nov 6, 2014
    Posts:
    34
    Thanks for helping me Obo Shape.
    The currentSpeed, MaxSpeed and Min Speeds are floats.
    I substituted the code with your recommendations (thanks for the shorter way to write it BTW), however its doing the same thing. When I run the code- I can see that it is still changing random speed values although my objects are still falling at the same velocity. I'm still trying to figure out what's going on. I will continue to work and find out why its still not working and look at the recommended documentation link you have provided for me.
    Thanks Obo Shape.
     
  23. Beta4

    Beta4

    Joined:
    Nov 6, 2014
    Posts:
    34
    I just though of something... The asteroid has that moverScript attached to it- which was set at -5 on the speed, I noticed that when I tweeked it higher or slower the asteroids moved faster or slower. How could I incorporate that speed value on that moverScript with the GameController script so it can affect the asteroid speed to indeed show the random value. I hope I'm on the right track. Any help would be great.
    Thanks again.
     
  24. Beta4

    Beta4

    Joined:
    Nov 6, 2014
    Posts:
    34
    Thanks agian to all your help. I figured out somethings. ( I got it - it did have to do with the other script) thanks
     
  25. 95_richi

    95_richi

    Joined:
    Dec 4, 2014
    Posts:
    2
    Hi. Im new in unity and i'm trying to make the space shooter proyect following the video tutorials but i had a problem with the first script, the PlayerController script. I wrote in ths script everything you put in the fifth video (6:37) but the ship doesn't move pressing any key (I tryed whith every key in my keyboard)

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class PlayerController : MonoBehaviour
    5. {
    6.  
    7.     void fixupdate ()
    8.     {
    9.         float moveHorizontal = Input.GetAxis ("horizontal");
    10.         float moveVertical = Input.GetAxis ("vertical");
    11.  
    12.         Vector3 movement = new Vector3 (moveHorizontal, 0.0f, moveVertical);
    13.         rigidbody.velocity = movement;
    14.     }
    15. }
    16.  
    Any idea about why this isn't working?
     
  26. OboShape

    OboShape

    Joined:
    Feb 17, 2014
    Posts:
    836
    evening 95_richi,

    on lines 10 and 11, the Horizontal and Vertical in quotes should be upper case.

    Code (CSharp):
    1. float moveHorizontal = Input.GetAxis ("Horizontal");
    2. float moveVertical = Input.GetAxis ("Vertical");
    should work now

    with things like that it can be hard when monos' intellisense isnt available, but the scripting guide is handy.
    http://docs.unity3d.com/ScriptReference/Input.GetAxis.html
     
    Last edited: Dec 4, 2014
  27. OboShape

    OboShape

    Joined:
    Feb 17, 2014
    Posts:
    836
    Beta4,
    good stuff you got it working.
    just been playing with the Mover script after work.
    you could have it so it can run at a fixed speed, or a random depending on what tag you give the object.
    this way the movement can be self contained.

    in the example ive done, ive added a tag named 'Enemy' and applied it to the object that i want to have a random speed.
    see more about tags here.
    http://unity3d.com/learn/tutorials/modules/beginner/editor/tags

    its just for fun but have a read see if you can see where ive gone with it :) (its heavily commented for info)
    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class Mover : MonoBehaviour
    5. {
    6.     // use these for your random number parameters
    7.     public float minRandomSpeed;
    8.     public float maxRandomSpeed;
    9.  
    10.     // if your not wanting a random we will use this
    11.     public float fixedSpeed;
    12.     // we can set the speed float to be a fixed or a random and then use it
    13.     private float speed;
    14.  
    15.     void Start ()
    16.     {
    17.  
    18.         if(this.gameObject.tag == "Enemy")
    19.         {
    20.             // set the speed to a random float number
    21.             speed = Random.Range(minRandomSpeed, maxRandomSpeed);
    22.         }
    23.         else
    24.         {
    25.             speed = fixedSpeed;
    26.         }
    27.  
    28.         // now set the velocity of the object
    29.         // transform.forward is a normal vector(0f, 0f, 1f)
    30.         // so for example
    31.         rigidbody.velocity = transform.forward * speed;
    32.     }
    33. }
     
    Last edited: Dec 4, 2014
  28. Adam-Buckner

    Adam-Buckner

    Joined:
    Jun 27, 2007
    Posts:
    5,664
    Thanks for all the replies OboShape!
     
  29. 95_richi

    95_richi

    Joined:
    Dec 4, 2014
    Posts:
    2
    Thanks for answering but still not working :(
     
  30. Adam-Buckner

    Adam-Buckner

    Joined:
    Jun 27, 2007
    Posts:
    5,664
    All the languages compatible with Unity are CaseSensitivE!

    And spelling is imperitive!

    Code (csharp):
    1. void fixupdate ()
    ... needs to be:


    Code (csharp):
    1. void FixedUpdate ()
    Capital "F", Capital "U" and "Fixed" not "Fix"
     
    OboShape likes this.
  31. OboShape

    OboShape

    Joined:
    Feb 17, 2014
    Posts:
    836
    didn't spot that, sorry :(
     
  32. Adam-Buckner

    Adam-Buckner

    Joined:
    Jun 27, 2007
    Posts:
    5,664
    I didn't notice the spelling until I was making the example of the the case!

    Code is picky! We must be careful!
     
  33. lxkosxl

    lxkosxl

    Joined:
    Nov 28, 2014
    Posts:
    5
    Hey adam, Sorry for the delay in my response i had to take a break i still couldnt get it working the way i wanted

    I am getting errors, youre right. you already knew that though =)
    When i was setting local scale, I was under the impression i was only editing the size of the asteroid.
    When i was getting random X & Z i thought that i was setting the vectors at which the asteroids would fly out of explosion to random locations along the X & Z planes, I was under the impression we were only using the X & z plane, i didnt know that i was randomizing the mass? / volume? thats why i had y set to 0.0f

    When it comes to the velocity i didnt understand how exactly to write the code im guessing thats why i was trying to set the x value to a new (x, y, z) value, the same thing to the z. I thought that if i was just randomizing the x and z again. im still learning and im doing all of this by myself, this is the first time ive tried to write my own code off the top of my head and im still not really understanding how to go about knowing "how" to write it exactly.

    I was trying to instantiate my new small asteroids out of the explosion animation from the big asteroids.. i want to keep the original explosion animation but add the small asteroids coming out of the explosion.

    I do want the small asteroids to be interactable, i want them to be destroyable, worth 5 points instead of 10, and able to destroy the player if he collides.
    Again. after doing the tutorials i was lead to believe we had to have a prefab of what ever object we were trying to insantiate. so i made a prefab of a smaller asteroid. with colliders, and i was able to get as far as when i blow up the big asteroids, 2-3 little asteroids spawned out of it and they were shootable, but they didnt fly out random locations they just kinda fell to the bottom of play area and if shot would be destroyed, but would not destroy player and was not worth any points, right now im just focusing on getting the small asteroids to instantiate properly.

    Thank you for the help adam i really appreciate it. also i remember the begginer section videos went over vector3s and instantiating but i think i may need more in depth help. possibly someone like an online tutor. this is something i truly want to do with my life. I have wanted to be in the game industry for as long as i can remember even though for the majority of my life it was just wanting to test games, now i have seen whats possible with the programming side and this IS what i want to do. so much so that im thinking about going to a programming "boot camp" or taking computer science/game design classes at the community college



     
  34. Adam-Buckner

    Adam-Buckner

    Joined:
    Jun 27, 2007
    Posts:
    5,664
    That's ok. Only bang your head against the wall until you've had enough. You can come back and bang that wall anytime!

    I'm not clear where you are in your project, so I won't go into detail here (refer back to my previous post if it helps).

    If it's still not working, can you let me know the current state of your project?

    Realize that coding and game development is just a series of small things added to small things added to small things that all come together into one large whole. This is why I was trying to break everything down into little tiny pieces.

    Let's try to work on one problem at a time.

    What's the first error you have? You can paste the error and related code, and let's step thru this one problem at a time.

    -

    Some small notes to keep you going (even tho' I said I wouldn't go into detail):

    Building Blocks:
    Look up Vector3 and Float and know the difference, and know that a Vector3 includes three float values.

    Local Scale is the "scale" values in the transform:

    • These are local, as they are relative to their parent, rather than global, which is relative to the world.
    • Scale needs 3 float values (x, y, z), usually wrapped into the Vector3 struct for ease.
    • To randomize a size, you need to set the floats themselves with something like:
    Code (csharp):
    1. myObject.transform.localScale = new Vector3 (Random.Range (minSize, maxSize), Random.Range (minSize, maxSize), Random.Range (minSize, maxSize));
    ... where you define:
    Code (csharp):
    1. public float minSize;
    2. public float maxSize;
    ... and assign a min and max size in the inspector.

    Note: that there are 3 Random Ranges here, one for each float value of (x, y, z). The asteroid is a 3D object, so needs a local scale for all 3 dimensions.

    It is possible to get a "Random Vector3" with either
    Code (csharp):
    1. Random.insideUnitSphere
    or
    Code (csharp):
    1. Random.onUnitSphere
    , but this will simply give a random number for each of the 3 float values based on which you choose, and you won't have control over your range of values. To make an asteroid between "this size" and "that size", you need to define a minimum and maximum size for your asteroid, and choose random values between them.
    Code (csharp):
    1. Random.Range
    is great for this.

    With the rigidbody.velocity, you are correct that you only want to set the X & Z values. But the X & Z just need a single value for each axis. As discussed above
    Code (csharp):
    1. Random.insideUnitSphere
    returns a full Vector3 with 3 float values not one.

    You can tell this by looking at the documentation page and reading the return value:

    The "signature" of
    Code (csharp):
    1. Random.insideUnitSphere
    is:
    public static Vector3 insideUnitSphere;

    The way to read this is:
    • It's public and accessible (or we wouldn't be able to use it!)
    • It's static, so it is accessible without an instance (so we can use if from "anywhere"!)
    • It returns a Vector3 (so when we request Random.insideUnitSphere we are given a new Vector3(x, y, z)!)
    • It's name is insideUnitSphere (so we know what to call!)
    So, to get a random velocity on the X-Z plane you can do this:
    Code (csharp):
    1. Rigidbody asteroidsRB = smallAsteroid.GetComponent<Rigidbody>();
    2.  
    3. Vector3 newVelocityRaw = Random.insideUnitSphere;
    4. asteroidsRB.velocity = new Vector3 (newVelocityRaw.x, 0.0f, newVelocity.z) * smallAsteroidSpeed;
    Note: that this gives up a value for X and Z, but we've reduced Y to 0.0f!

    Yup! You can have the asteroids coming out of the explosion!

    BUT!

    You don't need to set the position to the explosion. If you really wanted to, you'll need a reference to the explosion you have instantiated not the explosion prefab in the project view!

    Remember when you write:
    Code (csharp):
    1. public GameObject asteroid
    ... you are creating a draggable GameObject reference, and this is being filled by the Prefab GameObject from the Project View.

    If you ask for the asteroid.transform.position... you can get this data. It will be the data in the prefab:

    This isn't what you want, really, is it?

    Remember these are all just numbers or values... So, the numbers or values you want are the ones where we put the explosion.

    We put the explosion at:
    Code (csharp):
    1. Instantiate(explosion, transform.position, transform.rotation);
    So - if you want to put your new asteroids in the middle of the explosion, you just need the same numbers:
    Code (csharp):
    1. GameObject smallAsteroid = Instantiate(smallAsteroid, transform.position, transform.rotation);
    This is fine, just instantiate the asteroid at the point above and give them a scale and velocity...

    BUT:

    Look at the physics collision matrix:

    We don't want the asteroids colliding with each other and blowing themselves up! You need to set your physics layer collision matrix to asteroids are on a layer that does not collide with itself, or the very first frame, all of your asteroids will self-destruct with each other, as they will all be created in the same location.

    You can get this by going to Edit > Project Settings > Physics:

    Here is the documentation page:
    http://docs.unity3d.com/Manual/LayerBasedCollision.html

    Let's go thru this one item at a time. I could guess what's going on, but I'm just guessing.

    Now - prefabs make it easy to Instantiate GameObjects, but you don't need a prefab to Instantiate things. The prefab makes it easy to set things up in the scene and save them as an asset which can be referenced.

    Taking any classes you can will always help.

    Think of coding as ... lego, or building blox or something like that. Each piece is very versatile, but essentially does one particular thing, and you need to build up your game using a ton of these little tiny building blocks.

    A lot of the "more advanced" items are simply saving or holding or controlling groups or collections of these tiny building block made into more complex shapes so you don't have to build everything from the ground up.

    Let's approach this with one problem topic at a time and work thru the issues one at a time!

    -

    So much for me not going into detail.

    I hope this helps!
     
    OboShape likes this.
  35. lxkosxl

    lxkosxl

    Joined:
    Nov 28, 2014
    Posts:
    5
    oh my god, so much info to absorb. okay going to do some research get into project mode mindset and ill post error logs and code snippets, Adam I cant tell you the value of the knowledge and education you freely give out in this forum. i TRUELY appreciate all of your efforts, not only in helping me but the others that bang their head against the same wall =)
     
    OboShape likes this.
  36. Beta4

    Beta4

    Joined:
    Nov 6, 2014
    Posts:
    34
    How do I make my object have a 180 rotation on the Z-axis with this code

    Code (CSharp):
    1. rigidbody.rotation = Quaternion.Euler(Input.GetAxis("Horizontal"), 0.0f, rigidbody.velocity.x * -tilt);
    It has something to do with
    Code (CSharp):
    1. rigidbody.rotation = Quaternion.Euler(0,0,180);
    But depending on the last one in the script, it takes over the one before... how do I combine it so that my object rotates on the z-axis while its moving left and right but have my object start out at the 180 degrees on my Z-axis.

    Thanks again guys.
     
  37. OboShape

    OboShape

    Joined:
    Feb 17, 2014
    Posts:
    836
    Morning, thought i might chip in over my morning coffee to help while you wait for the learn team,

    just reading, are you saying that you want your object to face upside down (in the case of the player) before applying the tilt rotation?

    if you were to include both lines of the above, as you say, the second will override the first, as you are applying a fixed rotation value to an object, not a cumulitative one. then you are setting it to another hard coded rotation value.

    (*excuse the compass analogy* in other words if you tell something to face east, then you tell it to face south, its going to end up facing south as thats what you told it to do last, your are not telling it to turn by x degrees, instead rotate to face a set value)

    with your question about putting in a base rotation value to then add the tilt to, your almost there, as you have said what you want to do by combining them :)
    depending on what it is your looking for, you could use the following as the z value is just a float so float arithmetic operations like -/+ etc are ok (it will do the multiplication first then add to the 180)
    Code (CSharp):
    1. rigidbody.rotation = Quaternion.Euler(Input.GetAxis("Horizontal"), 0.0f, 180f + rigidbody.velocity.x * -tilt)
    just out of curiosity, is it for an asset thats currently in the space shooter project? or have you imported a new model?


    im sure the guys will get back to you soon as my morning ramblings dont always make sense lol
     
    Last edited: Dec 11, 2014
  38. Adam-Buckner

    Adam-Buckner

    Joined:
    Jun 27, 2007
    Posts:
    5,664
    Oboshape: You're correct.

    You're also correct in asking about the model. If the model is "upside-down", you should take it back to the modelling package and rotate it there. Also, you could place the model into another "empty parent" Game Object, then rotate the model 180°, and then affect only the *parent* GameObject.
     
  39. Beta4

    Beta4

    Joined:
    Nov 6, 2014
    Posts:
    34
    It is a model from Blender that I created. It imports the correct way at (0,0,180)- but as soon as I pressed play it would have the z axis back to 0. And that was the line of code making it turn back from 180 to 0 on the Z axis, The object created defaults (0, 0, 0) imports to my scene on it's belly, I needed the Z-axis at 180 for it to be correctly displayed.(I'm learning blender (a couple of days so far learning that system) also and cant figure out how to get it to properly display so it imports correctly on its top side with its default at (0,0,0), (even though Im using the Bounding Box Center to rotate it - i.e. the default on Blender becomes (0,0,180)) instead of having to mess with the code at (0,0,180) to get it to display show the top of the ship instead of its belly -need to check other forums on that I guess, lol). Yes I am learn with the shooter demo. Sorry I went on a rant lol. BTW the code works thanks again Obo Shape. And thank you again Adam that is also good solid advice also.
     
  40. Adam-Buckner

    Adam-Buckner

    Joined:
    Jun 27, 2007
    Posts:
    5,664
    I would go into blender, and in the top down view, rotate the model 180° around that axis, apply the change to the transform and mesh in blender, save the model and use that. It's easy to get the axes messed up from a modelling application and Unity. Make sure the model is created on the correct axes in the 3D modelling package before importing the model.
     
  41. Deleted User

    Deleted User

    Guest

    I'm not sure if it has already been posted but with the new UI the last part of the tutorial isn't perfect anymore (http://unity3d.com/learn/tutorials/projects/space-shooter/counting-points)

    I solved this by putting everything relevant about score in a score display script (ScoreDisplay.cs) and assign it to scoretext in the canvas which is the "placeholder" for the score.
    Code (CSharp):
    1.  
    2. using UnityEngine;
    3. using System.Collections;
    4. using UnityEngine.UI;
    5. public class ScoreDisplay : MonoBehaviour {
    6.  
    7.     public GameObject scoretext;
    8.     public int score;
    9.     // Use this for initialization
    10.     void Start () {
    11.         score = 0;
    12.         UpdateScore ();
    13.     }
    14.  
    15.     public void AddScore (int newScoreValue)
    16.     {
    17.         score = score + newScoreValue;
    18.         UpdateScore ();
    19.     }
    20.  
    21.     void UpdateScore ()
    22.     {
    23.         Text text = scoretext.GetComponent<Text>(); //get the text component in the gameobject you assigned
    24.         text.text = "Score:" + score; //set the text in the text component
    25.     }
    26. }
    27.  

    In DestroyByContact I referred to ScoreDisplay rather then GameController by doing it like this:
    Code (CSharp):
    1.  
    2. using UnityEngine;
    3. using System.Collections;
    4.  
    5. public class DestroyByContact : MonoBehaviour
    6. {
    7.     public GameObject explosion;
    8.     public GameObject playerExplosion;
    9.     public int scoreValue;
    10.     private ScoreDisplay scoreDisplay;
    11.  
    12.     void Start ()
    13.     {
    14.         GameObject scoreDisplayObject = GameObject.FindWithTag ("ScoreDisplay");
    15.         if (scoreDisplayObject != null)
    16.         {
    17.             scoreDisplay = scoreDisplayObject.GetComponent <ScoreDisplay>();
    18.         }
    19.         if (scoreDisplay == null)
    20.         {
    21.             Debug.Log ("Cannot find 'ScoreDisplay' script");
    22.         }
    23.     }
    24.  
    25.  
    26.     void OnTriggerEnter(Collider other)
    27.     {
    28.         if (other.tag == "Boundary")
    29.         {
    30.             return;
    31.         }
    32.         Instantiate (explosion, transform.position, transform.rotation);
    33.             if (other.tag == "Player")
    34.             {
    35.                 Instantiate (playerExplosion, other.transform.position, other.transform.rotation);
    36.             }
    37.         scoreDisplay.AddScore (scoreValue);
    38.         Destroy (other.gameObject);
    39.         Destroy (gameObject);
    40.     }
    41. }
    42.  
    And last but not least I made a new tag called scoredisplay. I hope this helps for people running into the same "problem" :)
     
  42. Deleted User

    Deleted User

    Guest

    Ouch, doing it this way actually sucks for the last part of the excersise. Made it work with the GameController thing, no need to try the code above LOL

    Code (csharp):
    1.  
    2. using UnityEngine;
    3. using System.Collections;
    4. using UnityEngine.UI;
    5.  
    6. public class GameController : MonoBehaviour
    7. {
    8.     public GameObject hazard;
    9.     public Vector3 spawnValues;
    10.     public int hazardCount;
    11.     public float spawnWait;
    12.     public float startWait;
    13.     public float waveWait;
    14.    
    15.     public GameObject scoreText;
    16.     private int score;
    17.    
    18.     void Start ()
    19.     {
    20.         score = 0;
    21.         UpdateScore ();
    22.         StartCoroutine (SpawnWaves ());
    23.     }
    24.    
    25.     IEnumerator SpawnWaves ()
    26.     {
    27.         yield return new WaitForSeconds (startWait);
    28.         while (true)
    29.         {
    30.             for (int i = 0; i < hazardCount; i++)
    31.             {
    32.                 Vector3 spawnPosition = new Vector3 (Random.Range (-spawnValues.x, spawnValues.x), spawnValues.y, spawnValues.z);
    33.                 Quaternion spawnRotation = Quaternion.identity;
    34.                 Instantiate (hazard, spawnPosition, spawnRotation);
    35.                 yield return new WaitForSeconds (spawnWait);
    36.             }
    37.             yield return new WaitForSeconds (waveWait);
    38.         }
    39.     }
    40.    
    41.     public void AddScore (int newScoreValue)
    42.     {
    43.         score = score + newScoreValue;
    44.         UpdateScore ();
    45.     }
    46.    
    47.     void UpdateScore ()
    48.     {
    49.         Text text = scoreText.GetComponent<Text>(); //get the text component in the gameobject you assigned
    50.         text.text = "Score:" + score; //set the text in the text component
    51.     }
    52. }
    53.  
     
    Last edited by a moderator: Dec 13, 2014
  43. Deleted User

    Deleted User

    Guest

    I can't seem to figure out how to solve this problem. I got the new UI score thingy working with game controller. But as I add restart and gameover text labels to the canvas it wants me to select the scoretext in the inspector for the restart and gameover labels as well. I find that strange, cause I only want to assign the scoretext to the scoretext label. Is there a way to have a script that contains several texts and feeds that to several labels without having to assign the script to each individual label?
     
  44. OboShape

    OboShape

    Joined:
    Feb 17, 2014
    Posts:
    836
    Morning,
    from what im reading you have the canvas, with one or more UI Text elements under it pertaining to Score, Restart and GameOver. so thats cool.

    in the same way the GUI Text elements worked in the tutorial.

    instead of having
    Code (CSharp):
    1. public GUIText scoreText;
    you will have to put
    Code (CSharp):
    1. public Text scoreText;
    also seen as you are using the new UI you will need an additional line at the top of the page to say that you are using UI functions. put the following line at the top of the script, just under using UnityEngine.
    Code (CSharp):
    1. using UnityEngine.UI;
    now you can drag and drop the Text objects onto the inspector slot as before. hope that helps, while you wait for learn team.
     
  45. Adam-Buckner

    Adam-Buckner

    Joined:
    Jun 27, 2007
    Posts:
    5,664
    Woot! What he said! (OboShape! Thanks a million, again!)

    You can simply replace the GUIText with Text and as both the GUIText and Text have a text property, later in the code when it reads:
    Code (csharp):
    1. scoreText.text = ...
    ... it will "just work", even tho' the type of the variable has changed.

    This is the same with the game over text and the restart text.

    If you want to see this done, watch the Space Shooter to Mobile episode of live training which should be up next week.
     
  46. Beta4

    Beta4

    Joined:
    Nov 6, 2014
    Posts:
    34

    This has been a couple of days or so since you posted this... where do I do that in blender (apply the change to the transform and mesh in blender) I can rotate it but when I save it, the model is still on its belly in Unity.
    Thanks again!
     
  47. OboShape

    OboShape

    Joined:
    Feb 17, 2014
    Posts:
    836
    ive only used blender slightly, currently going through a few lessons myself, but I've had a quick look through the forum here and theres a vid related to applying correct rotation to an object from blender to unity. its due to the transform Axis in blender and unity being different. have a wee look see if t helps, its nearer the end where he applies the rotation in blender to suit unity importing.

     
  48. Beta4

    Beta4

    Joined:
    Nov 6, 2014
    Posts:
    34
    You know your stuff Obo- This was a big help - Thanks again!
     
  49. OboShape

    OboShape

    Joined:
    Feb 17, 2014
    Posts:
    836
    no worries, glad its working :) i know how frustrating it is when i was starting out
     
  50. Adam-Buckner

    Adam-Buckner

    Joined:
    Jun 27, 2007
    Posts:
    5,664
    Yes. Thanks oboshape!

    There are two issues to be aware of. Z-axis differences between Unity and Blender, and mesh vs object differences in Blender.

    Be aware that in Unity, z is "away" and y is "up", whereas in Blender z is "up" and y is "away". In general, z is usually depth, but is depth up and down? (blender) or is z depth away from you and your camera in the scene? (Unity)

    This means you may have I to correct your model by 90* on the x axis. When importing a .blend file, Unity does this for you in the transform, but it can lead to problems if you address the transform of the model directly. In general, it is often best to have the model as a child object to a base game object and affect the base game object's transform, not the model's. If you do it this, the orientation of the model is mostly irrelevant as you are not affecting the model's transform.

    The other issue is a Blender issue. Unity will look at the mesh for its mesh data when dealing with the model. Blender has two ways of looking at a model: as a mesh or as an object. There can be multiple meshes in a Blender object. If you rotate an object in object mode (you can tell this because the vertices, edges or faces are not indicated) , this is very much like rotating the parent game object in Unity. The mesh data is unchanged, but the parent object is rotated, and the total rotation of the model includes its local data and the parent's object data.

    There are two solutions to this. One is to make sure you are in mesh mode and then rotate the mesh. The other is to be in object mode, rotate the model and then apply the rotation. You will have to google the specifics. There are a lot of pages and vids on it... But you can dig around in what I believe is the object menu and look for "Apply rotation and scale".
     
    OboShape likes this.
Thread Status:
Not open for further replies.