UNITY 3D – Game Programming – Part 9 - CodeProject

:

Introduction

In part nine of the article we will introduce more enhancements to the overall look and feel of our game. Specifically speaking, we will introduce a main menu, sound effects, and visual effects! Enhancing the appeal of our little game!

If you have not already done so, please take a moment and read:

  1. Unity 3D – Game Programming – Part 1
  2. Unity 3D – Game Programming – Part 2

  3. Unity 3D – Game Programming – Part 3

  4. Unity 3D – Game Programming – Part 4

  5. Unity 3D – Game Programming – Part 5

  6. Unity 3D – Game Programming – Part 6

  7. Unity 3D – Game Programming – Part 7

  8. Unity 3D – Game Programming – Part 8

  9. Unity 3D – Game Programming – Part 9

  10. Unity 3D – Game Programming – Part 10

Unity 3D Networking Article(s):

  1. Unity 3D - Network Game Programming

Unity 3D Leap Motion and Oculus Rift Article(s):

  1. Unity 3D - Leap Motion Integration

In the first part of the series we started by the very basics of the Unity 3D environment. Getting a feel of the IDE and the different sections which you will be working with throughout your project. We also covered how to use the tools in the designer to apply different transformation to a selected Game Object: positioning, rotation and scaling. We finally looked at how to create our first script and using the script apply a rotation transform on the Y-Axis of our cube.

In the second part of the series, we looked at more of the transformation of a given object through coding. We also looked at how to create light sources that are crucial for the rendering of your objects in the scene.

In the third part of the series we looked at how to process user input through the keyboard and based on the key code take particular actions.

In the fourth part of the series, we looked at creating a simple user interface. The user interface that we developed provided us a means to feedback to the user, and also another method for the user to input to our game or simulation.

In the fifth part, we started the idea of a simple game. We also looked at how to import 3D models into the game engine.

In the sixth part, we expanded on our game idea and making it more interesting and more complete. We introduced several concepts regarding game play and game design as well as created a simple user interface for our game.

In the seventh part, we answered some of the questions that got raised in Part 6.

In the eighth part, we creating a better user experience and also visuals for our players.

In part nine of the series, we will continue on enhancing the visual effects of our little game. We will also be introducing a start menu for the game where the user can select some options and also determine the difficulty of our game. In addition, there will be sound effects and visual effects to enhance the overall look and feel of the game.

Windows Phone 8.x Demo:

I have provided a free phone application that you can download and preview the demos on your Windows Phone. To download the mobile application, follow the link: CodeProjectArticleSample

https://www.codeproject.com/KB/game/876015/Icon_106.png
Code Project Articles Sample Mobile App

Live Preview of Article Code and Visuals:

https://www.codeproject.com/KB/game/876015/preview_screen.png

Link to live preview: http://www.noorcon.com/CodeProject/CodeProjectArticlePreview.html

Background

NOTE: For this particle, I will be using Expression Design to create some simple menus and buttons or other visual components, which will be used to enhance the visual appeal of the game!

NOTE: For this particle, I will be using SketchUp to create some simple building blocks, which I will use to import into Unity! I am not a 3D Modeler or Designer, so please be patient and excuse the mess!

It is assumed that the reader of this article is familiar with programming concepts in general. It is also assumed that the reader has an understanding and experience of the C# language. It is also recommended that the reader of the article is familiar with Object-Oriented Programming and Design Concepts as well. We will be covering them briefly throughout the article as needed, but we will not get into the details as they are separate topics altogether. We also assume that you have a passion to learn 3D programming and have the basic theoretical concepts for 3D Graphics and Vector Math.

Lastly, the article uses Unity 3D version 4.6.1 which is the latest public release as of the initial publication date. Most of the topics discussed in the series will be compatible with older versions of the game engine, and perhaps also the new version which is supposed to be release sometime this year. There is however, one topics which is significantly different in the current 4.6.1 version compared to the older version of the game engine, and that is the UI (User Interface) pipeline. This is due to the new UI architecture in the engine which is far superior to what we had prior to this release. I for one, am very happy with the new UI architecture.

Using the code

Downloading the project/source code for article series: Download source.

With each consecutive article that is submitted, the project/source code will be also expanding. The new project files and source files will be inclusive of older parts in the series.

NOTE: To get the latest code, go to the most recent published part in the series and download the code.

Improving the Game

In part 8, we designed and developed a cannon that was supposed to behave kind of like an obstacle for the player. The cannon was designed to shoot cannon balls based on some random specifications that were defined within our logic. We also discussed sound and how to add sound to our game.

NOTE: We did not cover everything regarding Audio. It is a large and broad topic, therefore, it is left for the reader to pursue it further on their own.

Model for Gold Coins

No matter how small or large your project is, one of the most important aspects of it will be the visual part. For our gold coins up to part 8, we used a Capsule Primitive and assigned it a material which we defined in the previous series of the articles.

I have decided to replace our coin model with something much more appealing. There are many 3D models available for free that you can use in your projects. I decided to grab a free gold coin model.

I don’t know about you, but I believe this looks much nicer then what we had previously! In any case, the model is included in the download source for you.

The original model is under the models folder and is named TyveKrone. For our game, I had to make several modifications to the original model, therefore, I created a new Prefab and placed it under the following folder: prefabs->part_9->Gold_Coin under the Assets folder.

Several things you will note about the prefab:

  1. The scale has been increased by a multiple of 10! This is because the original model was very small due to its original units and also dimension. Therefore, to make it feasible for our game, I have to scale it up by a factor of 10.

  2. It is rotate 90 degrees on its X-Axis.

  3. I attached it a Sphere Collider, and set its Is Trigger to True. Also, the Radius is set to 0.01 on the collider. This collider was added so that it calls the event that handles the on Trigger Enter.

  4. Two scripts have also been attached to the prefab: GoldCoinRotation.cs and Coin.cs. The only difference between GoldCoinRotation.cs and the rotateCoin.cs script is the rotation axis. Since the new model Axis are different then our original coin primitive, I decided to make a new script that will apply the rotation just for the new model without breaking the old parts of the articles. Coin.cs is the same as what we had before.

In order for us to use the new model, all we need to do it replace the reference on the playerInput.cs script with the new model. So our Coin Prefab reference should point to our GoldCoin Prefab.

Adding Sound FX to the Cannon / Cannon Ball

To make our game more interesting, it would be nice to add some sound effects to it. Especially when the cannon ball is fired! It is really very simple to add simple sound effects to our project. First, we need to decide what kind and what type of sound effects we want for our game, then we need to either create these sound effects ourselves, or get some that already exist.

I want a cannon sound effect, therefore, I did some search online and came up with one that I was pleased with. I placed all of the audio that I have used for the article series under the audio folder. In the audio folder, you will notice a file called CannonBall, this is my sound that will be used for the cannon ball shooting effect.

In order to incorporate this audio in our game, we need to modify our CannonBall Prefab. You will need to add a new Audio Source Component to the prefab. Once, you have the Audio Source component, all you need to do is to associate the Audio Clip property to the actual audio clip (sound file) under the audio folder, in this case, CannonBall. Check mark the Play On Awake property, and make sure that the Loop property is false. We only want the audio to be played once on awake; that is when the object actually gets initialized!

Adding More Metrics to the User Interface

We already had two metrics in our user interface design: the score and the timer. The score was the sum of all coins collected, and the timer was well, the time left for the player to collect the gold coins. I have introduced two new metrics to the user interface: number of coins collected and a health bar for the player.

Number of coins collected has no explaining to do, as it is displaying how many coins the player has collected in the game, the health bar is introduced as a means to measure and display the health of the player. This is due to the cannon and the cannon balls we implemented as an obstacle in the game. So if the player gets hit by a cannon ball he/she will be damaged and therefore their health will decrease.

I will not cover how to implement the number of coins collected, as it is simple and follows the same logic and UI design as our previous two metrics score and time.

What I will cover is the implementation and the UI design of the health bar for our player as there are several ways to do this. Again, for a simple game such as ours, I will use the simplest means of implementing.

Let’s take a look and see one way of implementing the representation of the health bar for the player. Also note, that I have added a few more icons to make it more eye appealing.

Designing and Implementing the Health Bar

I am going to show you one of the simplest ways to do a health bar! It really can’t get any simpler than this. The health bar I want to implement is going to be rectangular and it is going to have two graphical parts to it. The first will be the frame, and the second will be the actual color(s) representing the health bar.


Figure 4-Health Bar Images

Figure 4 demonstrates the look of my health bar. Technically it will be comprised of two separate images, one representing the frame and the other the actual health bar. When the two are combined together, you will get the effect as indicated by number 2 in Figure 4.

Going back to Unity 3D’s IDE, we want to display the health bar above the player. In order to achieve this, we need to attach a Canvas UI object to our character player, and change the Render Mode attribute to World Space from Screen Space Overlay. This will render the health bar according to its location in the 3D world, and it will not be rendered as any other object in the scene from the eyes of the camera. The next thing you would do is to reset it so that it is positioned relative to the center of the character player. You would change the Rect Transform to the following: (0,0,0) respectively on the (x,y,z) axis. By default the actual size of the Canvas is going to be very large compared to your world, so the best way to adjust this, is not by reducing the Height and the Width, as that is the actual resolution, you don’t want to reduce that, you will use the Scale Vector to scale accordingly, so in my case, I have scaled the Canvas down to (0.03, 0.03, 1) on the (x,y,z) axis.

The steps described above are the key to the visual implementation of the health bar. We are not done yet, we need to add two Image UI objects to our canvas, one for each image type. Go ahead and add two Image UI objects, the first one will reference the image sprite that will represent the actual health bar, and the second will reference the image sprite that represents the frame for our health bar.

Your structure should look something like the following:


Figure 5-HealthBar Canvas Attached to Player Character

You will need to adjust the Rect Transform on each image object to place them accordingly over the player. In my case, the following are the Rect Transform numbers:

  • Anchor for both images are set to the center.

  • The X, Y and Z positions are set to 0, 20, and 0 respectively.

  • The width and height of imgHealthBar is set to 10x1

  • The width and height of imgHealthBarFrame is set to 10x2

As you can see all of the attributes are the same with the exception of the width and height of the frame which is 10x2. The frame need to be bigger than what it contains. The order is also important here, imgHealthBar will be rendered before imgHealthBarFrame, and hence the frame will be always on top of the health bar. Also notice that we did not touch the scale factor! This is because the Canvas will do the work for us!

There is one more important step that you will need to do. For imgHealthBar UI object, under the Image (Script) Component change the Image Type from Simple to Filled, also change the Fill Method to Horizontal, and the Fill Origin to Left, also make sure that the Fill Amount is set to 1, even though we set this through the script anyway.

The last step is to reference our health bar from our script and be able to control it. In order to do this, we need to introduce a few new variables. I use an integer to store the player’s health value and another variable of type Image to reference imgHealthBar in the UI Canvas.

Here is the full script listing for playerInput.cs:

using UnityEngine;
using UnityEngine.UI;
using System.Collections;

public class playerInput : MonoBehaviour {

 public Text lblScore;   	// text UI element for displaying score
 public Text lblTimer;   	// text UI element for displaying timer
 public Text lblNumOfCoins;  	// text UI element for displaying coins collected

 public Canvas endGameCanvas; 	// Canvas holding UI elements for End of Game

 public Text lblEndOfGameScore;
 public Text lblEndOfGameTime;
 public Text lblEndOfGameCoinCont;

 public GameObject coinPrefab; 	// variable used to store the coin prefab

 public GameObject hitEffect;

 private int score;    		// internal score variable

 public int health;    		// keep track of player health
 public Image healthBar;   	// visual health bar for player

 public int SCORE
 {
  get{ return this.score; }
 }

 private float levelTime;   	// variable holing time to complete level
 private float timeLeft;    	// variable for the actual timer count down

 public bool END_GAME;    	// variable indicating end of game

 public int numOfCoinsInLevel;  	// will be initialized at the Start of the game
 public int numOfCoinsCollected;  	// will be incremented each time we collect a coin

 // Use this for initialization
 void Start () {

  //GameObject _GM = GameObject.Find ("_GameMaster") as GameObject;

  Debug.Log (GameMaster.GameMode);

  if (this.healthBar != null)
   this.healthBar.fillAmount = 1.0f;

  this.health = 100;

  #region COIN CREATION
  // This checks to make sure we have the prefab, also so that it does not break previous code
  if(this.coinPrefab!=null){
   // we need to create the coins dynamically per region
   // Coins for Region 1
   for (int i=0; i<16; i++) {
    // Fill the Top part of Region 1
    if(i<4){
     GameObject coin = GameObject.Instantiate(this.coinPrefab,
                      		new Vector3(Random.Range(-4.5f, 4.5f), 0.25f, Random.Range(3.0f, 4.5f)),
                                this.coinPrefab.transform.rotation) as GameObject;
     coin.name = "R1TopC"+i;
    }
    // Fill the Bottom part of Region 1
    if(i>3 && i<8){
     GameObject coin = GameObject.Instantiate(this.coinPrefab,
                                new Vector3(Random.Range(-4.5f, 4.5f), 0.25f, Random.Range(-4.5f, -3.0f)),
                                this.coinPrefab.transform.rotation) as GameObject;
     coin.name = "R1BottomC"+i;
    }
    // Fill the Left part of Region 1
    if(i>7 && i<12){
     GameObject coin = GameObject.Instantiate(this.coinPrefab,
                                new Vector3(Random.Range(-4.5f, -3.0f), 0.25f, Random.Range(-4.5f, 4.5f)),
                                this.coinPrefab.transform.rotation) as GameObject;
     coin.name = "R1LeftC"+i;
    }
    if(i>11 & i<16){
     GameObject coin = GameObject.Instantiate(this.coinPrefab,
                                new Vector3(Random.Range(3.0f, 4.5f), 0.25f, Random.Range(-4.5f, 4.5f)),
                                this.coinPrefab.transform.rotation) as GameObject;
     coin.name = "R1RightC"+i;
    }
    
   }
   
   // Coins for Region 2
   for (int i=0; i<4; i++) {
    GameObject coin = GameObject.Instantiate(this.coinPrefab,
                                new Vector3(Random.Range(-2.0f, 2.0f), 0.25f, Random.Range(1.5f, 2.0f)),
                                this.coinPrefab.transform.rotation) as GameObject;
    coin.name = "R2C"+i;
   }
   
   // Coins for Region 3
   for (int i=0; i<4; i++) {
    GameObject coin = GameObject.Instantiate(this.coinPrefab,
                                new Vector3(Random.Range(-2.0f, 2.0f), 0.25f, Random.Range(-0.5f, 0.5f)),
                                this.coinPrefab.transform.rotation) as GameObject;
    coin.name = "R3C"+i;
   }
   
   // Coins for Region 4
   for (int i=0; i<4; i++) {
    GameObject coin = GameObject.Instantiate(this.coinPrefab,
                                new Vector3(Random.Range(-2.0f, 2.0f), 0.25f, Random.Range(-2.0f, -1.5f)),
                                this.coinPrefab.transform.rotation) as GameObject;
    coin.name = "R4C"+i;
   }
  }
  #endregion

  this.score = 0;
  this.levelTime = Time.time + Random.Range (30.0f, 60.0f);
  this.numOfCoinsCollected = 0;

  this.END_GAME = false;

  if (this.endGameCanvas != null) {
   this.endGameCanvas.gameObject.SetActive (false);
  }

  // check to make sure labels are defined before updating
  if (this.lblScore != null)
   this.lblScore.text = this.score.ToString();

  if (this.lblTimer != null)
   this.lblTimer.text = string.Format("{0:F2}", this.levelTime - Time.time);

  if (this.lblNumOfCoins != null)
   this.lblNumOfCoins.text = this.numOfCoinsCollected.ToString ();

  // get number of coins in the scene at the start of the game
  this.numOfCoinsInLevel = GameObject.FindGameObjectsWithTag ("coin").Length;

 }

 // Update is called once per frame
 void Update () {
  if (!this.END_GAME) {

   // compute time left
   this.timeLeft = this.levelTime - Time.time;

   // update UI label for timer
   if (this.lblTimer != null){
    this.lblTimer.text = string.Format("{0:F2}", this.timeLeft);
   }

   // check to see if we need to end the game based on the timer
   if(this.timeLeft<=0.00f || this.numOfCoinsInLevel<=this.numOfCoinsCollected){
    this.END_GAME = true;

    if (this.lblTimer != null && this.lblEndOfGameTime != null){

     if(this.timeLeft>=0.00f){
      this.lblTimer.text = string.Format("{0:F2}", this.timeLeft);
      this.lblEndOfGameTime.text = string.Format("{0:F2}", this.timeLeft);
     }else{
      // this else block is written to ensure that if the timer is up, we always get 0.00
      // and not positive or negative values, i.e. 0.01, or -0.01 and etc...
      this.lblTimer.text = string.Format("{0:F2}", 0.00f);
      this.lblEndOfGameTime.text = string.Format("{0:F2}", 0.00f);
     }
    }

    if(this.lblEndOfGameScore != null && this.lblEndOfGameCoinCont != null){
     this.lblEndOfGameScore.text = this.SCORE.ToString();
     this.lblEndOfGameCoinCont.text = this.numOfCoinsCollected.ToString();
    }

   }

   // code for the movement of player (CP) forward
   if(Input.GetKey(KeyCode.UpArrow)){
    this.transform.Translate(Vector3.forward * Time.deltaTime);
   }
   // code for the movement of player (CP) backward
   if(Input.GetKey(KeyCode.DownArrow)){
    this.transform.Translate(Vector3.back * Time.deltaTime);
   }
   // code for the movement of player (CP) left
   if(Input.GetKey(KeyCode.LeftArrow)){
    this.transform.Rotate(Vector3.up, -5);
   }
   // code for the movement of player (CP) right
   if(Input.GetKey(KeyCode.RightArrow)){
    this.transform.Rotate(Vector3.up, 5);
   } 
  }else{
   if(this.endGameCanvas != null){
    this.endGameCanvas.gameObject.SetActive(true);
   }
  }

 }

 // This event will be raised by object that have their Is Trigger attributed enabled.
 // In our case, the coin GameObject has Is Trigger set to true on its collider.
 void OnTriggerEnter(Collider c){

  // used to detect if we collided with a coin GameObject
  if(c.tag.Equals("coin")){
   Coin coin = c.GetComponent<Coin>();

   // increase score
   this.score += coin.VALUE;
   this.numOfCoinsCollected += 1;

   // update score on the UI
   if (this.lblScore != null)
    this.lblScore.text = this.score.ToString();
   if(this.lblNumOfCoins != null)
    this.lblNumOfCoins.text = this.numOfCoinsCollected.ToString();

   // remove the Coin object from the scene
   Destroy(c.gameObject);
  }

  // used to detect if we collided with a cannon ball GameObject
  if (c.tag.Equals ("cannon_ball")) {
   string info = string.Format("{0}-{1}", c.name, "CANNON BALL!!!");

   Debug.Log(info);

   this.health -= 10;

   // remove the cannon ball object from the scene after a hit
   Destroy(c.gameObject);

   if(this.hitEffect!=null)
   {
    GameObject fx = GameObject.Instantiate(GameMaster.GM.playerHitFx,
                                           this.transform.position,
                                           this.transform.rotation) as GameObject;

    if(this.healthBar != null){
     this.healthBar.fillAmount = (this.health / 100.0f);
    }
   }
  }
 }

 public void butPlayAgain_Click(){

  // get all object of type coin
  /*GameObject[] coins = GameObject.FindGameObjectsWithTag ("coin");

  // remove eahc object from the scene
  foreach (GameObject coin in coins){
   Destroy(coin);
  }

  Start ();*/

  Application.LoadLevel (Application.loadedLevelName);
 }
}

You should already be very familiar with this code if you have been following the series. The only main change is in the OnTriggerEnter(Collider c) function. And that handles the collision with the cannon balls. If we hit a cannon ball, we reduce the health of the player and also instantiate a Prefab that represents an explosion Effect.

Creating a Game Menu

The next step is to create a main menu for the game. So I used our existing scene and saved it as a new scene. Then I removed the unnecessary game object that would not be used in the scene. Namely the player character. To organize the scene better, I created two Empty GameObjects and named them the following: CannonCollection and LightCollection. I moved all Cannon GameObjects under the CannonCollection and all PointLight GameObjects under the LightCollection. Since these are static in the scene it would be better to organize them this way and create less clutter in the Hierarchy Window.


Figure 6-Main Game Menu

I used Expression Design to come up with some UI design elements for my menus and buttons. I created couple of separate Canvas UI objects to handle the UI elements. Used my sprites to configure them to my likings and associating the proper event handlers for each button.

NOTE: Please refer to older parts in the series for a detailed explanation of how to achieve and construct your UI elements if you have not studied them already.

A new GameObject called _GameMaster has been introduced in the scene. The concept here is important albeit the implementation is very simple. The _GameMaster GameObject is an Empty GameObject with a script called GameMaster.cs attached to it.

NOTE: The main point of the _GameMaster GameObject is the concept that I want you to take away from here. And it is done in a simple way, in more complex game, the actual _GameMaster would be much more complex.

Usually speaking, the Game Master will be controlling and managing all of the relevant parts of your game. This includes, the player, the enemies, the audio, the sound effects, the visual effects, and any other relevant object in your game. Basically it is going to be the main Class that will glue all major components together! Your Game Master implementation will come down to really your OOD/OOP skills. I won’t be covering those in this article, as this is just a sample.

Let’s take a look at the GameMaster.cs script:

using UnityEngine;
using UnityEngine.UI;
using System.Collections;

public class GameMaster : MonoBehaviour {

 public static GameMaster GM;

 public static int GameMode;

 public GameObject playerHitFx;
 public GameObject cannonBallFireFx;

 public Image progressBar;
 public Canvas loadingPanelCanvas;

 // Use this for initialization
 void Start () {
  GameMaster.GM = this;
  DontDestroyOnLoad (this);

  if (this.progressBar != null)
   this.progressBar.fillAmount = 0.0f;
 }
 
 // Update is called once per frame
 void Update () {

  if (this.progressBar != null) {
   this.progressBar.fillAmount = Application.GetStreamProgressForLevel("part_9_game");
  }

  if (Application.CanStreamedLevelBeLoaded ("part_9_game")) {
   if(this.loadingPanelCanvas!=null)
    this.loadingPanelCanvas.enabled = false;
  }

 }

 public void butEasy(){
  GameMaster.GameMode = 0;
  this.LoadGame ();
 }

 public void butHard(){
  GameMaster.GameMode = 1;
  this.LoadGame ();
 }

 private void LoadGame(){
  if (Application.CanStreamedLevelBeLoaded ("part_9_game")) {
   Application.LoadLevel ("part_9_game");
  }
 }
}

Several things are happening here, let’s take a look at them more closely. I want to concentrate on the most important sections of the code. The first being the static variables. The first one is of type GameMaster called GM, and the second one is of type int called GameMode. These two variable are static because they will not change throughout the life span of the game.

NOTE: The code is dirty, and can be improved!

The next important section is the Start() function. In the Start() function we are setting the GM variable to the keyword this, representing the instance of the GameMaster object. Then we are using the function called DontDestroyOnLoad (this); which tells the game engine to not destroy the referenced GameObject when loading or unloading scenes from the memory. In other words, the _GameMaster GameObject once in memory will not be destroyed unless the game ends or we manually destroy it in the code.

Something we did not cover in part 8 is the stream loading of a particular level. You can see the implementation of this in the Update() function. The following built in function Application.CanStreamedLevelBeLoaded ("<scene_name>"); return a value between 0 and 1, this value represents the percentage (%) of the necessary GameObjects loaded for a particular scene. This is very useful when you are deploying games online and over the network. As you game becomes more complex, the size of your game is going to increase. That is, as your assets increase and your scenes become more complex, the size of your game file is going to increase accordingly. Do not be surprise to have a project folder in the 2GB to 3GB range!

In our case, we don’t have a lot of complex models and textures, so our model and texture size is super small for the game, but, since we introduced some sound effects and visual effects, the size of our projects has increased accordingly. Especially for the audio part, since that is the main asset that takes much space!

The implementation in the Update() function will make sure that we don’t load our game level until all assets have been downloaded to the user’s machine.

Points of Interest

A lot of new concepts have been introduced in this article. Also notice that even though we have placed the code for the game mode, we are not actually using it to adjust our game play. This is something that I would like you to work on and also give some feedback on improvements on your own.

The code is not well structured and can be cleaned up and organized much better. I would like to hear from you on how you have improved and or implemented your version.

History

This is the ninth article of a series which I would slowly contribute to the Code Project community.

  1. Unity 3D – Game Programming – Part 1
  2. Unity 3D – Game Programming – Part 2

  3. Unity 3D – Game Programming – Part 3

  4. Unity 3D – Game Programming – Part 4

  5. Unity 3D – Game Programming – Part 5

  6. Unity 3D – Game Programming – Part 6

  7. Unity 3D – Game Programming – Part 7

  8. Unity 3D – Game Programming – Part 8

  9. Unity 3D – Game Programming – Part 9

  10. Unity 3D – Game Programming – Part 10

Unity 3D Networking Article(s):

  1. Unity 3D - Network Game Programming

Unity 3D Leap Motion and Oculus Rift Article(s):

  1. Unity 3D - Leap Motion Integration