Walker Boys Studio – Unity Training – Lab 2

This is my 2nd post related to Unity 3D and Walker Boys Studio’s free tutorials. I decided to start learning Unity and follow with the amazing tutorials created by them.a

You can read more about this second lab by following this link: Walker Boys Studio – Unity Training – Lab 2.

If you want to see my result (a nice small game called “2D Space Shooter”) please click on the image below.

Note that this is not intended to be a complete working game, it has been created in order to learn basic game development in Unity 3D. More complicated projects will follow but, for now, the target was to learn only the basic stuff.

Project Description

Student Name

Marcel Corbeanu, from Romania :-) .


26.05.2011 – 30.05.2011

Project Details

I’ll try to discuss below my solutions to each of the homeworks.

1. Extra Socket to Fire With

I created 2 new Prefabs and attached them to the prefabPlayer Prefab. Now, the question is: when these 2 new Prefabs “get activated”? Well, the idea is to activate them when the user will collect the “FireB” powerup and so, in scriptSceneManager.js, I created a private variable called “fireType” (it can take only two values A and B, default A).

Basically, when it’s value will be equal to A, we’ll be talking about single fire; when it’s value will be equal to B the player will have double fire.

Note that the player will lose the upgraded fire if it’ll lose a life – I think this makes the game even more intersting.

2. Random Variables

The goal here was to generate a random speed and a random scale for all the enemies.
This was actually pretty straight forward, as I used Random.Range(minValue, maxValue), where both values are public variables (exposed to the Inspector).

In scriptAsteroid.js, I created 2 private variables called “currentSpeed” and “currentScale” and, as soon as the game starts (function Start()), I populate them with random values (see above paragraph) and I use these values in the Update function. Each time the enemy gets repositioned new random values are generated.

3. Add a Pickup Item

Actually, we had to add 2 pick-up items, one for the double shot (tagged “pickup_fireB”) and one for new life (tagged “pickup_newLife”).

The logic for the powerups is created in a brand new javascript file, called scriptPowerup.js. All the powerups have a Collider with it’s isTrigger = true (but it’ll work with isTrigger = false as well). The  object that we’re interested to collide the powerups with is prefabPlayer so this object has both a Collider (isTrigger = true) and a RigidBody (useGravity = false, isKinematic = true).
We then use the OnTriggerEnter function (found in scriptPowerup.js) in order to determine the object that collided with the powerup. If that object is tagged as “player” then we search for the actual tag of the powerup (see above paragraph) and, based on that, we play the correct sound, make the powerup dissapear, update a property found in scriptSceneManager.js, etc.

4. Extra Credit

A. Pickup Item for Lives

Was explained above, in #3.

B. Player Feedback (Player Flashes if Hit)

This was done using an InvokeRepeat statement placed in scriptAsteroid.js, as there is located the logic for asteroid-player collisions. Basically, we call a function for a number of times (5 times at 0.03s to be exact) and each time we use transform.renderer.enabled = !transform.renderer.enabled, basically reversing the visibility (on/off).

We also make sure that, say if a blink is already in progress, we reset it before we start a new blink :-)

C. Levels – Create several ‘New’ levels with a different range of difficulty

The levels logic could have been created in different way but the way I decided to do it was the following: I only have a single game scene (the one that was created in the tutorials) and, for each level, I add at least one new enemy (with it’s new properties) and write some text on screen, just to let the player know that a new level has started. I also reset the level timer :-).

All the logic is done in scriptSceneManager.js, as this is the brain of the program and so here is all the ”global” logic like: current level, lives, shieldOn, all the game constants, etc

D. Blocking Cubes – Create a solid block that Asteroids can hit against

This was done by creating a new Prefab (prefabBlock), and using scriptAsteroid.js as the main script file. The block is tagged as “block”.

The collision logic for the block works like this:

  • a block will not kill another block (2 blocks will not kill each other)
  • a block will kill with an asteroid
  • a block will kill with a player
  • a bullet will not be able to kill a block

So, in order to create the logic listed above, I used the asteroid script (scriptAsteroid.js) but I had to change it a little bit. I had to add the part where an “asteroid” collides with a “block” and, in OnTriggerEnter(), I used the following statement: if (tag == “asteroid” && other.tag == “block”) do something.

Software Used

  • Unity 3D
  • Adobe Soundbooth CS5 – for editing the sound files
  • Sfrx (from DrPetter.se) – for generating the sound effects

Final Thoughts

First of all, I think you did another great job by creating this 2nd lab. I’m sure the others are also great, I can’t wait to start the work on the next one :)

Some thoughts …

I think I changed the initial script quite a bit, mostly because, as the game got complicated, I needed to feel comfortable with the way the code was structured. I used many constants in scriptSceneManager.js in order to define different values like, for example, the movement limits for enemies, default fire type, etc.

Most of the audio logic is based on the method that’s using AudioSource.PlayAtPoint and all the AudioSource sources are linked in the main manager file (scriptSceneManager.js).

I decided not to use any static variables and, instead, create in each file a variable called “sceneManager”, where sceneManager = gameObject.Find(“prefabSceneManager”).GetComponent(“scriptSceneManager”). This is updated only once, in the Start() function of each javascript file and it works like a reference to the scriptSceneManager component. It gives me a way to quickly access any variable or method found there.

In order to let the player know that he got a powerup or the game level changed I used a 3DText Game Object in the center of the screen. As with all the global stuff, the logic was done in scriptSceneManager.js and accessed through the reference “var sceneManager” (explained above).

All the enemies (asteroids and blocks) have a variable called “activeFromLevel” (default 1) which states from which level that particular enemy will become active. This is the way I use in order to add new enemies with each level.

The enemies, blocks or powerups are not dynamically instantiated at any time and they are not destroyed (that was the initial logic and I kept that), instead they are reused by repositioning them. The bullets and the 3DText (explained above) are the only Game Objects that do get dynamically instantiated when they are needed (and then, of course, destroyed when they will not be useful to the game).

Also, I remove the player from the screen only at the end of the game (with Destroy()). I also created a short pause (2-3 seconds) before jumping to the win/lose screen (so that the “jump” will not be so abrupt) :-) . Actually, the pause is more useful when you die and you see the “game lost” screen, because you die after an explosion and I think it was important to display the explosion first and then redirect to “game lost” screen. On “game won” you don’t actually see much of a difference :-) .

The powerups get a random rotation when they are repositioned, which makes the game look more interesting. The catch here was to move them in global space (Space.World) instead of the default local space.

Whenever I have to change a variable in scriptSceneManager.js I use a dedicated function (much like a “setter” function). The only way I access a variable directly is when I read it’s value (I wish Unity’s javascript be a little be more complex, much like ActionScript 3 is).

There are a couple of public variables in scriptSceneManager.js and they are used to get the total nr of levels, nr of lives, total level time, etc. I don’t actually use them in the actual game, I make copies of them, mostly because I like to have the “original” values in case I need them later (for example, the game time is needed before each new level starts, in order to reset the level time).

I made sure that the objects don’t register collisions outside of the screen, by setting transform.collider.isTrigger = false using another script file (called scriptMisc1.js) that is attached to the bullets, the asteroids and the blocks. The initializations in scriptMisc1.js must be done before any other initializations (because it’s possible to generate the same position for 2 asteroid, and then they will register a collision and we’ll hear an explosion for something that happened outside of the screen) so I do it in function Awake().

Every Game Object (being either a bullet, an asteroid, a powerup, a block or the player) is dynamically repositioned at the start of the game (so we can eliminate any surprise and keep track of everything).

You don’t get any points for picking-up the powerups but maybe you should :-) . Anyway, that’s not important now!

Break down your Time

  • Research
    • 9h:15 – looking at the videos and, when needed, over the documentation
  • Art
    • aproximately 1h:00
  • Design
    • aproximately 4h:00 – enemies, menues, and GUI, along with some coding there
  • Coding
    • 6h:30 – rest of the coding for the game, along with looking the 2nd time though the lab videos
    • 11h:00 – all the homeworks + different testing
  • Playtesting
    • aproximately 4h:00 at least, mostly in the last day. I also tested much during coding (I’m used to do this).

Thank you again for all your work in putting together the huge list of videos and the documentation for the tutorials, exams and labs.

Filed in: English, Unity 3D
Tags: , , ,

Related Posts

Bookmark and Promote!

Leave a Reply

Submit Comment