Hi all. This is a beginners tutorial to create a simple air hockey game using unity 3D.
This was a project I had done for a college competition.
It has average graphics and a simple AI code to start with.
So lets get started.
Download the game files for PC :
https://drive.google.com/folderview?id=0B14CKd6vH9dSZ0NFUFRrZlpLT2M&usp=sharing
Open up unity and create a New Project. (Call it whatever u want, I'm not good at commenting on this sort of stuff, so forgive me).
You may create folders and stuff if you want to keep your project clean, but for my purposes, I kept things messed up. Nonetheless the code and prefabs are simple to understand.
Our first concern : CREATE THE TABLE IN 3D
First of all lets move the camera up (you may not do it though, however for the purpose of the project I worked on I used the camera on position (0.02,7.64,-11.67). If you chose to not take this value then make sure that you work all the way based on your relative values. Values following here WILL NOT WORK).
1.Go to Gameobject > 3D Object > Cube..
2. Move the cube in the x,y and z axes by adjusting its transform values. Try to put it as shown below: ( On the center of the game screen)

Set the camera rotation to some random value ( For me hit and trial of values gave me an appropriate value which worked fine : (45,0,0)).
3. Change the scale of the cube: X : 12, Y : 17, Z : 2. You may use other values as well but make sure you get such a view:

4. Now right click on the flie explorer ( In the project tab) , goto Create > Material. Lets call it table.
5. Drag this material onto the table.
6.Create a new gameObject as before and call it Directional_Light. Click on it, the
Add Component > Rendering > Light.
7. Now add the following values to Directional_Light' transform :
Position = ( -21.6 , -0.4 , -34)
Rotation = (50 ,330 , 0).
8. Click on Table, in Inspector goto Shader (at the bottom , click on the drop-down) > Legacy Shaders > Decal.
9. Expand the option now, and choose any colour you want. For me Light whitish-bluish worked fine.
Progress so far :

Step 2: Making the whole world:
1. Create a new GameObject > Cylinder, lest call it Player_Puck. try to flatten it by scaling in the y direction.
2. Create another Gameobject > Cylinder, call it player_mallet and drag it onto Player_Puck (this will cause it to become a child of Player_Puck). Flatten the mallet in the x and z axes so that it is like a flat cylinder on top of the puck.
3.Create a new material called Player. Drag this onto our pluck and mallet (as we did for the table).
4.Set the shader value to Legacy Shaders > Self - Illumin. Choose any colour you want ( I chose green).
If you have followed me till now this is what your game should probably look like :

1. Now repeat the steps as above, only this time create a new material named AI and change the colour for it. Position the AI GameObject at the other corner of the table. (My AI is in blue).
2. Now create another cylinder, add a new material to it, with yet another color and call it striker. This is what we're gonna be hitting in the game.

3. Now Goto Player_Puck > Add Component > Rigidbody. Keep its mass high (I used the calue 1 e+09 though it was unecessary for such a high value).
Similarly add rigidbody to AI and Striker both. Keep the mass of AI same as the player and that of the striker relatively very small in comparision to the other two.
Why we do this is because we do not want the stiker to apply any considerable force to our player or AI during gameplay, otherwise they would be flying out of conrtol.
4. Goto rigidbody of the 3 and check freeze rotation in all x,y and z axes. We are not concerned with any torques here, thus we do this.
5.Freeze the position of the player in the Y axis as well. This would stop any unattended glitches later on. (Coz I had experienced some of it).
Now create a new cube called edge_1. Position it on one corner of the table. Similarly surround all the four corners.

Now Create gameObjects called Goal_Player and Goal_AI. Add BoxColliders to both of them.
Check the isTrigger on both the colliders. Try and place the respective gameObjects at the edge of the table on the 2 ends. It is here that when the striker would fall, a point would be won.
The green boxes below are where I placed them.

Assigning tags :
1. Goto to the Player_Puck gameobject. In the inspector click on tag drop-down menu and select Player.
2. Repeat above for Striker, but this time go to Add tag > Expand Tags > + > Striker (OR any other name but make sure to code accordingly).
Now goto the striker gameobject and select the Striker tag for it.
3.Repeating above step add a Tag "PLAYER_GOAL" to out player_goal gameobject and "AI_GOAL" also.
These tags will help us in coding.
Now create two more gameobjects called P_Score and E_Score and add component Text Mesh to each of them. Place them on left and right corners of screen, these will show the score.
Change the text on the text meshes as per your choice..,I've written this...

CODING (My favorite part) :
Player.cs
using UnityEngine;
using System.Collections;
public class Player : MonoBehaviour {
BoxCollider coll;
Rigidbody striker;
GameObject st;
public float playerSpeed; //set value from inspector
public float strikerSpeed; //speed at which striker moves
AI ai;
void Awake() {
strikerSpeed = PlayerPrefs.GetFloat ("Striker_Speed");
}
// Use this for initialization
void Start () {
ai = GameObject.Find ("AI").GetComponent<AI> ();
coll = GameObject.Find ("Table").GetComponent<BoxCollider> ();
striker = GameObject.FindGameObjectWithTag ("Striker").GetComponent<Rigidbody> ();
st = GameObject.FindGameObjectWithTag ("Striker");
}
// Update is called once per frame
void Update () {
//Input to move the player
if (Input.GetKey ("left"))
transform.Translate (-playerSpeed * Time.deltaTime, 0f, 0f);
if (Input.GetKey ("right"))
transform.Translate (playerSpeed * Time.deltaTime, 0f, 0f);
if (Input.GetKey ("up"))
transform.Translate (0f, 0f, playerSpeed * Time.deltaTime);
if (Input.GetKey ("down"))
transform.Translate (0f, 0f, -playerSpeed * Time.deltaTime);
//Collision detection with edges, basically we are restricting player movement
if (transform.position.x <= -4.74f)
transform.position = new Vector3 (-4.74f, transform.position.y, transform.position.z);
if (transform.position.x >= 4.74f)
transform.position = new Vector3 (4.74f, transform.position.y, transform.position.z);
if (transform.position.z >= -1f)
transform.position = new Vector3 ( transform.position.x, transform.position.y, -1f);
if (transform.position.z <= -8.4f)
transform.position = new Vector3 ( transform.position.x, transform.position.y, -8.4f);
}
void OnCollisionEnter(Collision c) {
if (c.gameObject.tag == "Striker") {
ai.counter = 0f; //see AI.cs for explanation
//Controls to hit the striker
if (Input.GetKey ("space")) { //if you keep space pressed and up arrow key and then touch, stiker is smashed
//---Control Part---
if (Input.GetKey ("up")) {
if (Input.GetKey ("right")) {
striker.velocity = new Vector3 (strikerSpeed, striker.velocity.y, strikerSpeed);
} else {
striker.velocity = new Vector3 (-strikerSpeed, striker.velocity.y, strikerSpeed);
}
}
}
else { //no space pressed and then touch then a gentle push is given
if (Input.GetKey ("right")) {
striker.velocity = new Vector3 (strikerSpeed * 0.5f, striker.velocity.y, strikerSpeed * 0.60f);
} else {
striker.velocity = new Vector3 (strikerSpeed * -0.5f, striker.velocity.y, strikerSpeed * 0.60f);
}
}
}
}
}
Striker.cs
using UnityEngine;
using System.Collections;
public class Striker : MonoBehaviour {
GameManager gm;
void Awake() {
}
// Use this for initialization
void Start () {
gm = GameObject.FindGameObjectWithTag ("MainCamera").GetComponent<GameManager> ();
}
// Update is called once per frame
void Update () {
}
void OnTriggerEnter(Collider c) {
if (c.tag == "AI_GOAL") {
gm.pScore += 1f;
gm.Reset (1);
}
if (c.tag == "PLAYER_GOAL") {
gm.eScore += 1f;
gm.Reset (0);
}
}
}
-----------END OF Striker.cs----------------
GameManager.cs
using UnityEngine;
using System.Collections;
public class GameManager : MonoBehaviour {
GameObject striker,player,ai,pS,eS; //pS - playerScore, eS - enemyScore
//for score
public float pScore,eScore; //p-player,e-enemy
// Use this for initialization
void Start () {
pScore = 0f;
eScore = 0f;
striker = GameObject.FindGameObjectWithTag ("Striker");
player = GameObject.FindGameObjectWithTag ("Player");
ai = GameObject.Find ("AI");
pS = GameObject.Find ("P_Score");
eS = GameObject.Find ("E_Score");
}
// Update is called once per frame
void Update () {
pS.gameObject.GetComponent<TextMesh> ().text = "YOU:" + pScore;
eS.gameObject.GetComponent<TextMesh> ().text = "OPP:" + eScore;
}
public void Reset(int status) {
//Reset all the gameObjects to original position to start a new game session
if (status == 1) //recieved when striker hits any goal, check Striker.cs
striker.transform.position = new Vector3 (0.06f, striker.transform.position.y, 2.82f);//if enemy wins,
//place on player side
else
striker.transform.position = new Vector3 (0.06f, striker.transform.position.y, -4.59f);
striker.gameObject.GetComponent<Rigidbody>().velocity = new Vector3 (0f,0f,0f);//stop the striker
player.transform.position = new Vector3 (0.88f, player.transform.position.y, -8.17f);
ai.transform.position = new Vector3 (0.88f, ai.transform.position.y, 6.65f);
}
}
-----------<END OF GameManager.cs>-------------
Now go to the editor and assign values to playerSpeed, strikerSpeed and difficulty.
You should be good to go now.
Conclusion:
At the end of this tutorial you are ready to make a basic AI, are able to work with average graphics and are able to set up basic collision detection and stuff...
The challenge would now be to experiment with some of this stuff and make something of your own, I learnt only by making new stuff...
If you like this tutorial then pleas let me know...I will be back with more...Even if I am missing out on something please tell me...
You can support me by checking and playing out my games...
https://play.google.com/store/apps/details?id=com.FMech.T_Bounce&hl=en
This was a project I had done for a college competition.
It has average graphics and a simple AI code to start with.
So lets get started.
Download the game files for PC :
https://drive.google.com/folderview?id=0B14CKd6vH9dSZ0NFUFRrZlpLT2M&usp=sharing
Open up unity and create a New Project. (Call it whatever u want, I'm not good at commenting on this sort of stuff, so forgive me).
You may create folders and stuff if you want to keep your project clean, but for my purposes, I kept things messed up. Nonetheless the code and prefabs are simple to understand.
Our first concern : CREATE THE TABLE IN 3D
First of all lets move the camera up (you may not do it though, however for the purpose of the project I worked on I used the camera on position (0.02,7.64,-11.67). If you chose to not take this value then make sure that you work all the way based on your relative values. Values following here WILL NOT WORK).
1.Go to Gameobject > 3D Object > Cube..
2. Move the cube in the x,y and z axes by adjusting its transform values. Try to put it as shown below: ( On the center of the game screen)

Set the camera rotation to some random value ( For me hit and trial of values gave me an appropriate value which worked fine : (45,0,0)).
3. Change the scale of the cube: X : 12, Y : 17, Z : 2. You may use other values as well but make sure you get such a view:

4. Now right click on the flie explorer ( In the project tab) , goto Create > Material. Lets call it table.
5. Drag this material onto the table.
6.Create a new gameObject as before and call it Directional_Light. Click on it, the
Add Component > Rendering > Light.
7. Now add the following values to Directional_Light' transform :
Position = ( -21.6 , -0.4 , -34)
Rotation = (50 ,330 , 0).
8. Click on Table, in Inspector goto Shader (at the bottom , click on the drop-down) > Legacy Shaders > Decal.
9. Expand the option now, and choose any colour you want. For me Light whitish-bluish worked fine.
Progress so far :

Step 2: Making the whole world:
1. Create a new GameObject > Cylinder, lest call it Player_Puck. try to flatten it by scaling in the y direction.
2. Create another Gameobject > Cylinder, call it player_mallet and drag it onto Player_Puck (this will cause it to become a child of Player_Puck). Flatten the mallet in the x and z axes so that it is like a flat cylinder on top of the puck.
3.Create a new material called Player. Drag this onto our pluck and mallet (as we did for the table).
4.Set the shader value to Legacy Shaders > Self - Illumin. Choose any colour you want ( I chose green).
If you have followed me till now this is what your game should probably look like :

1. Now repeat the steps as above, only this time create a new material named AI and change the colour for it. Position the AI GameObject at the other corner of the table. (My AI is in blue).
2. Now create another cylinder, add a new material to it, with yet another color and call it striker. This is what we're gonna be hitting in the game.

3. Now Goto Player_Puck > Add Component > Rigidbody. Keep its mass high (I used the calue 1 e+09 though it was unecessary for such a high value).
Similarly add rigidbody to AI and Striker both. Keep the mass of AI same as the player and that of the striker relatively very small in comparision to the other two.
Why we do this is because we do not want the stiker to apply any considerable force to our player or AI during gameplay, otherwise they would be flying out of conrtol.
4. Goto rigidbody of the 3 and check freeze rotation in all x,y and z axes. We are not concerned with any torques here, thus we do this.
5.Freeze the position of the player in the Y axis as well. This would stop any unattended glitches later on. (Coz I had experienced some of it).
Now create a new cube called edge_1. Position it on one corner of the table. Similarly surround all the four corners.

Now Create gameObjects called Goal_Player and Goal_AI. Add BoxColliders to both of them.
Check the isTrigger on both the colliders. Try and place the respective gameObjects at the edge of the table on the 2 ends. It is here that when the striker would fall, a point would be won.
The green boxes below are where I placed them.

Assigning tags :
1. Goto to the Player_Puck gameobject. In the inspector click on tag drop-down menu and select Player.
2. Repeat above for Striker, but this time go to Add tag > Expand Tags > + > Striker (OR any other name but make sure to code accordingly).
Now goto the striker gameobject and select the Striker tag for it.
3.Repeating above step add a Tag "PLAYER_GOAL" to out player_goal gameobject and "AI_GOAL" also.
These tags will help us in coding.
Now create two more gameobjects called P_Score and E_Score and add component Text Mesh to each of them. Place them on left and right corners of screen, these will show the score.
Change the text on the text meshes as per your choice..,I've written this...

CODING (My favorite part) :
Player.cs
using UnityEngine;
using System.Collections;
public class Player : MonoBehaviour {
BoxCollider coll;
Rigidbody striker;
GameObject st;
public float playerSpeed; //set value from inspector
public float strikerSpeed; //speed at which striker moves
AI ai;
void Awake() {
strikerSpeed = PlayerPrefs.GetFloat ("Striker_Speed");
}
// Use this for initialization
void Start () {
ai = GameObject.Find ("AI").GetComponent<AI> ();
coll = GameObject.Find ("Table").GetComponent<BoxCollider> ();
striker = GameObject.FindGameObjectWithTag ("Striker").GetComponent<Rigidbody> ();
st = GameObject.FindGameObjectWithTag ("Striker");
}
// Update is called once per frame
void Update () {
//Input to move the player
if (Input.GetKey ("left"))
transform.Translate (-playerSpeed * Time.deltaTime, 0f, 0f);
if (Input.GetKey ("right"))
transform.Translate (playerSpeed * Time.deltaTime, 0f, 0f);
if (Input.GetKey ("up"))
transform.Translate (0f, 0f, playerSpeed * Time.deltaTime);
if (Input.GetKey ("down"))
transform.Translate (0f, 0f, -playerSpeed * Time.deltaTime);
//Collision detection with edges, basically we are restricting player movement
if (transform.position.x <= -4.74f)
transform.position = new Vector3 (-4.74f, transform.position.y, transform.position.z);
if (transform.position.x >= 4.74f)
transform.position = new Vector3 (4.74f, transform.position.y, transform.position.z);
if (transform.position.z >= -1f)
transform.position = new Vector3 ( transform.position.x, transform.position.y, -1f);
if (transform.position.z <= -8.4f)
transform.position = new Vector3 ( transform.position.x, transform.position.y, -8.4f);
}
void OnCollisionEnter(Collision c) {
if (c.gameObject.tag == "Striker") {
ai.counter = 0f; //see AI.cs for explanation
//Controls to hit the striker
if (Input.GetKey ("space")) { //if you keep space pressed and up arrow key and then touch, stiker is smashed
//---Control Part---
if (Input.GetKey ("up")) {
if (Input.GetKey ("right")) {
striker.velocity = new Vector3 (strikerSpeed, striker.velocity.y, strikerSpeed);
} else {
striker.velocity = new Vector3 (-strikerSpeed, striker.velocity.y, strikerSpeed);
}
}
}
else { //no space pressed and then touch then a gentle push is given
if (Input.GetKey ("right")) {
striker.velocity = new Vector3 (strikerSpeed * 0.5f, striker.velocity.y, strikerSpeed * 0.60f);
} else {
striker.velocity = new Vector3 (strikerSpeed * -0.5f, striker.velocity.y, strikerSpeed * 0.60f);
}
}
}
}
}
-------END OF Player.cs---------------
AI.cs
using UnityEngine;
using System.Collections;
public class AI : MonoBehaviour {
public float speed;
GameObject striker;
Rigidbody strikerRB;
float forceDir;
public float counter;
public float strikerSpeed;
Vector3 basePoint;
public float difficulty;
float smashCance;
void Awake() {
difficulty = PlayerPrefs.GetFloat ("Difficulty");
}
// Use this for initialization
void Start () {
striker = GameObject.FindGameObjectWithTag ("Striker");
strikerRB = GameObject.FindGameObjectWithTag ("Striker").GetComponent<Rigidbody> ();
//set difficulty
//based on the value the more the difficulty the more behind or close to the goal the ai is
//it plays defensive and gets extra time to think and play in high difficulty
//ideally difficuly = 1 must be invincible, if there are no game glitches
if (difficulty < 0.45f) { //easy
basePoint = new Vector3 (0.88f, transform.position.y, 0.85f);
difficulty = 0.2f;
} else if (difficulty >= 0.45f && difficulty < 1f) {
basePoint = new Vector3 (0.88f, transform.position.y, 3.3f);
difficulty = 0.7f;
}
else if(difficulty == 1f){
basePoint = new Vector3 (0.88f, transform.position.y, 6.65f);
}
}
// Update is called once per frame
void Update () {
counter += 1f * Time.deltaTime; //acts like a timer
Debug.Log (counter);
if(striker.transform.position.z >= -0.2f) { //if striker is in its half
if (counter >= 1f) { //wait for one second to see if the stiker comes to you or stops, if it does not come then :
Vector3 newPos = new Vector3 (striker.transform.position.x -0.5f, striker.transform.position.y, striker.transform.position.z + 0.5f);
//move towards the striker to its position
transform.position = Vector3.MoveTowards (transform.position, newPos, 4f * Time.deltaTime);
//4f * Time.deltaTime states time to transit the two positions
} else //if less than 1 second change your x-position based on difficulty, i.e. try to move closer to striker
transform.position = new Vector3 (striker.transform.position.x * difficulty, transform.position.y, transform.position.z);
}
else //if in other half then move towards base position
transform.position = Vector3.MoveTowards (transform.position, basePoint, 2f * Time.deltaTime);
}
void OnCollisionEnter(Collision c) {
if (c.gameObject.tag == "Striker") {
counter = 0f; //on hitting reset the wait time...
forceDir = (int)Random.Range (0, 10);//for hitting to the left or right
smashCance = (int)Random.Range (0, 10); //chance that it will smash the striker
//hit the striker with force
if (forceDir <= 5)
strikerRB.velocity = new Vector3 (-strikerSpeed, strikerRB.velocity.y, -strikerSpeed);
else
strikerRB.velocity = new Vector3 (strikerSpeed, strikerRB.velocity.y, -strikerSpeed);
}
}
}
--------END OF AI.cs---------
using UnityEngine;
using System.Collections;
public class Striker : MonoBehaviour {
GameManager gm;
void Awake() {
}
// Use this for initialization
void Start () {
gm = GameObject.FindGameObjectWithTag ("MainCamera").GetComponent<GameManager> ();
}
// Update is called once per frame
void Update () {
}
void OnTriggerEnter(Collider c) {
if (c.tag == "AI_GOAL") {
gm.pScore += 1f;
gm.Reset (1);
}
if (c.tag == "PLAYER_GOAL") {
gm.eScore += 1f;
gm.Reset (0);
}
}
}
-----------END OF Striker.cs----------------
GameManager.cs
using UnityEngine;
using System.Collections;
public class GameManager : MonoBehaviour {
GameObject striker,player,ai,pS,eS; //pS - playerScore, eS - enemyScore
//for score
public float pScore,eScore; //p-player,e-enemy
// Use this for initialization
void Start () {
pScore = 0f;
eScore = 0f;
striker = GameObject.FindGameObjectWithTag ("Striker");
player = GameObject.FindGameObjectWithTag ("Player");
ai = GameObject.Find ("AI");
pS = GameObject.Find ("P_Score");
eS = GameObject.Find ("E_Score");
}
// Update is called once per frame
void Update () {
pS.gameObject.GetComponent<TextMesh> ().text = "YOU:" + pScore;
eS.gameObject.GetComponent<TextMesh> ().text = "OPP:" + eScore;
}
public void Reset(int status) {
//Reset all the gameObjects to original position to start a new game session
if (status == 1) //recieved when striker hits any goal, check Striker.cs
striker.transform.position = new Vector3 (0.06f, striker.transform.position.y, 2.82f);//if enemy wins,
//place on player side
else
striker.transform.position = new Vector3 (0.06f, striker.transform.position.y, -4.59f);
striker.gameObject.GetComponent<Rigidbody>().velocity = new Vector3 (0f,0f,0f);//stop the striker
player.transform.position = new Vector3 (0.88f, player.transform.position.y, -8.17f);
ai.transform.position = new Vector3 (0.88f, ai.transform.position.y, 6.65f);
}
}
Now go to the editor and assign values to playerSpeed, strikerSpeed and difficulty.
You should be good to go now.
Conclusion:
At the end of this tutorial you are ready to make a basic AI, are able to work with average graphics and are able to set up basic collision detection and stuff...
The challenge would now be to experiment with some of this stuff and make something of your own, I learnt only by making new stuff...
If you like this tutorial then pleas let me know...I will be back with more...Even if I am missing out on something please tell me...
You can support me by checking and playing out my games...
https://play.google.com/store/apps/details?id=com.FMech.T_Bounce&hl=en
Hello Great tutorial. all that is missing is GameManager script where does it go. And thanks for the tutorial this is a great game.
ReplyDeleteThanks for appreciating the post.
DeleteAttach the script to the MainCamera gameobject.
Unity3D Beginner Tutorials: Unity3D Air Hockey Beginner Tutorial >>>>> Download Now
Delete>>>>> Download Full
Unity3D Beginner Tutorials: Unity3D Air Hockey Beginner Tutorial >>>>> Download LINK
>>>>> Download Now
Unity3D Beginner Tutorials: Unity3D Air Hockey Beginner Tutorial >>>>> Download Full
>>>>> Download LINK TS
Hello man, very good tutorial.
ReplyDeleteCan you help me?
Could you send the menu script?
Thanks
Best mini air hockey tables, Looking for best one? Who needs a standard-sized table? Air hockey is so enjoyable that the best mini air hockey table offers huge loads of fun. Here are your 5 best options. There’s no argume pingpongtableguide The 12 Best Air Hockey Tables Of All Time
ReplyDeleteUnity3D Beginner Tutorials: Unity3D Air Hockey Beginner Tutorial >>>>> Download Now
ReplyDelete>>>>> Download Full
Unity3D Beginner Tutorials: Unity3D Air Hockey Beginner Tutorial >>>>> Download LINK
>>>>> Download Now
Unity3D Beginner Tutorials: Unity3D Air Hockey Beginner Tutorial >>>>> Download Full
>>>>> Download LINK cf