Wednesday, September 24, 2014

Set Depth Camera to show DigitDisplay

The Depth Camera can be used to show the bottom panel when the MainCamera is following the character.

At first, the scene consists of a background and a bottom panel which shows the digits.


Step 1: Choose "bottom" object, add a Layer named "Bottom", and modify the Layer as "Bottom".



Step 2: Create a Camera and Set as the image shows:
Change "Clear Flags" to "Depth only" and "Culling Mask" to "Bottom"

Step 3: Modify the MainCamera:
Change the "Culling Mask" value without Bottom and assign "Depth" value as "-1".

Step 4: Remove "Audio Listener" of "Camera" object:

Step 5: Write a script to "Camera" in order to show the game digit.

Is Trigger and OnTriggerEnter(), Destroy()

1. Trigger:

  • If two objects are both added Collider component and at least one of them is checked the "Is Trigger" attribute, then OnTriggerEnter() can be used in anyone.


  • Trigger can go into the object.
2. Destroy():

Destroy(gameObject);
Destroy(gameObject, 2.0f); //delay 2 seconds

Camera Follow Target

using UnityEngine;
using System.Collections;

public class CameraFollow : MonoBehaviour {
    public GameObject target;
    public GameObject enemy;
    
    TargetController myTargetController;
    float velocity=0.0f;
    float newPositionX;
    
    // Update is called once per frame
    void Update () {
        //Camera Move
        if(target.transform.position.x>0 &&
           target.transform.position.x<33.5)
        {
            newPositionX=Mathf.SmoothDamp(transform.position.x,target.transform.position.xref velocity1.0f);
            transform.position=new Vector3(newPositionXtransform.position.ytransform.position.z);
        }
        //Active object when reach to a position
        if (transform.position.x > 2.8f) {
            if(enemy!=null){
                enemy.SetActive(true);
            }
        }
    }
}




AnimationController for the frames not in one texture

using System.Collections;

public class NewBehaviourScript : MonoBehaviour {
    public Texture [] frames;
    public bool direction=true;//head direction
    public bool destroy=false;//Destroy the animation after finish playing
    public int lastFrameNo=0//stop at a certain frame
    public bool oneTime=false;//do not repeat animation

    private int frameNumber=0;
    private int index=0;
    private float myTime=0;//time counter
    private int myIndex=0;

    // Update is called once per frame
    void Update () {
        frameNumber = frames.Length;

        if(!oneTime){
            myTime+=Time.deltaTime;
            myIndex=(int)(myTime*(frameNumber-1));//(frameNumber-1makes all animations played in 1s
            index=myIndex%frameNumber;
        }
        renderer.material.mainTexture=frames[index];//assign the frame to object

        if (direction) {
            renderer.material.mainTextureScale=new Vector2(1.0f,1);//set the heading direction
        }else{
            renderer.material.mainTextureScale=new Vector2(1.0f,1);
        }

        if (index == frameNumber - 1 && destroy) {
            //Destroy the animation
            Destroy(gameObject);
        }

        if (lastFrameNo != 0) {
            //stay on the certain frame
            if(index==lastFrameNo-1){
                oneTime=true;
            }
        }
    }
}

Customize GUI Button of Unity3D

First, I will give an example about how to implement a customized button, and then I would like to discuss how GUIs work under the function OnGUI().

Initially, there is a scene with a background:


Step 1: Create a GUISkin
Right click your mouse under project tab, choose "Create" -> "GUI Skin"
Drag the material pictures into the proper position
Then pull down the scroller bar and find "Custom Styles", put the other material into Element0 and assign the name as "easy"
Step 2: Write a script to show GUI and Drag it onto "MainCamera"

Step 3: Assign the startGUISkin with GUISkin in assets which we have already created in step 1

Step 4: Run and See



NOTE:
  • All the GUIs should be written in the OnGUI() function, which is called every frame.
  • GUI.Button(Rect,"label") use the default button skin. However, we also can use "Custom Styles" by writing GUI.Button(Rect,"label",GUI.skin.GetStyle("name")) .
  • If you want to hide GUI, then just set a boolean variable to controller it. Once the function doesn't run the GUI.Button(), the button will not show on the screen.
  • If(GUI.Button()) is a most widely used way to judge whether a button is clicked or not.
  • BTW, you can also modify the GUI.skin without assign a new GUISkin to it.

Character Player Controller

enum GameState
{
idle,
runLeft,
runRight,
jumpLeft,
jumpRight,
idleLeftJump,
idleRightJump,
celebrate,
die
}

var gameState:GameState;
private var moveDirection=true;
private var exit:boolean=false;
private var youWin:boolean=false;
private var youDie:boolean=false;
function Update(){
//Define GameState
if(Input.getAxis("Horizontal")>0){
moveDirection=true;
if(Input.GetButton("Jump")){
gameState=GameState.jumpRight;
}else{
gameState=GameState.runRight;
}
}else if(Input.getAxis("Horizontal")<0){
moveDirection=false;
if(Input.GetButton("Jump")){
gameState=GameState.jumpLeft;
}else{
gameState=GameState.runLeft;
}
}else{
if(Input.GetButton("Jump")){
if(moveDirection){
gameState=GameState.idleRightJump;
}else{
gameState=GameState.idleLeftJump;
}
}else{
gameState=GameState.idle;
}
}
if(youWin){
gameState=GameState.celebrate;
}
if(youDie){
gameState=GameState.die();
}
//Assign every state with a Vector3(x,y,x) variable
if(controller.isGrounded){
switch(gameState){
case GameState.runRight:
velocity=speed*Vector3(1,0,0);
break;
case GameState.runLeft:
velocity=speed*Vector3(-1,0,0);
break;
case GameState.jumpRight:
velocity=speed*Vector3(1,jumpSpeed,0);
break;
case GameState.jumpLeft:
velocity=speed*Vector3(-1,jumpSpeed,0);
break;
case GameState.idleLeftJump:
case GameState.idleRightJump:
velocity=speed*Vector3(0,jumpSpeed,0);
default:
velocity=Vector3.zero;
break;
}
}else{
velocity.y-=gravity*Time.deltaTime;
}
//Implement movement
controller.Move(velocity*Time.deltaTime);
}

Wednesday, September 17, 2014

Simulate the sound effect like real

var AudioClip sound;
function Start(){
    AudioSource.PlayClipAtPoint(sound, <MainCamera Position>);
}

Persistent Storage

PlayerPrefs
  • Set Value:
            PlayerPrefs.SetInt("HighScore", score);
  • Get Value:
            PlayerPrefs.GetInt("HighScore");
  • Clear Data:
            PlayerPrefs.DeleteKey("HighScore");
            
            PlayerPrefs.DeleteAll();

For details:

The summer of realizing object movement in Unity3D

1. Using Translate() function:

transform.Translate(
 speed*Input.GetAxis("Horizontal")*Time.deltaTime,
 speed*Input.GetAxis("Vertical")*Time.deltaTime,
0);

"speed" is the variable to controller the move speed.

Input.GetAxis("Horizontal") gets the states of left and right button: if left button is pressed return -1 and if right button is pressed return 1;
Input.GetAxis("Vertical") gets the states of up and down button: up returns 1 and down returns -1.

Time.deltalTime is constant which stands for the time interval between frames. Its value is about 0.02 seconds. Here it is just used as a constant to reduce the move speed.

2. Using Vector to replace x,y,z:

transform.Translate(
  Vector3.right*speed*Input.GetAxis("Horizontal")*Time.deltaTime
)

Vector3.right is a constant vector equals (1,0,0);
The similar as Vector3.up, Vector3.down, Vector3.right

3. Using velocity attribute:

velocity is a Vector3 type attribute of CharacterController and RigidBody which describes the direction and speed of the movement.
For example:
var bomb:Rigidbody;
bomb.velocity=new Vector3(3*speed,0,0)

4. CharacterController.Move:

CharacterController.Move

Attempts to move the controller by motion, the motion will only be constrained by collisions. It will slide along colliders.CollisionFlags is the summary of collisions that occurred during the Move. This function does not apply any gravity.


Implement a timer counter for game by Using Time.deltaTime

To achieve this goal, I will give an example of TimeRemainDisplay:

Step 1: Get Resources:
Step 2: Create an Empty Object and name it as "TimeRemainDisplay". Write a script to control the Display.
Textures, labels, buttons and other UIs should be write under the OnGUI() function. 
From the line 15 to 19, the program is drawing the every number picture on the screen.

leftTime.ToString()[i] gets the ith number of leftTime. However it is a char, so we need to change it to String type. After that, use Parse function to change the value to an integer as the index of the Texture array.

GUI.DrawTexture() draws the UI on the screen, the first argument is a type of Rect which the first two value is the position and the last two are the width and height. The second argument is the object to draw.

Step 3 Drag the pictures to assign the texture array.
Step 4 Run the game.


Collision Detection

There are two requirements before detect the collision:

  • Both of the items should have Collider Component;
  • The relative moving object need to add rigid body.
Step 1: Add the Box Collider on the Rock


Step 2: Add the Capsule Collider and Rigid Body on the projectile

Step 3: Write code to control the effect of collision and drag it on Rock
Note: OnTriggerEnter() is a function that can detect the collision. It also can get which object conflicts the object. So, the collider must check the Trigger attribute and set its unique tag.
Step 4: Run the game


  


Another way to detect collision: Do not check Trigger attributes and use OnCollisionEnter() function.

function OnCollisionEnter(collision:Collision){
    if(collision.gameObject.tag=="plane"){
        Destroy(gameObject);
    }
}

The difference between these two methods:
the collider with trigger can enter into the other object while it only conflict at the edge without trigger.

Create the projectile for plane

Using Instantiate(object, position, rotation) function:

Add the code on the object:
Drag the projectile prefab to assign the projectile variable:
Run the game:

Tuesday, September 16, 2014

How to make a sprite for 2D Games

Sprite not only supports the object to move but also some 2D animations like explosion, projectile fly, etc.

Prefabs can be reused in the game with just drugging it into "Hierarchy". Here I will show how to make a sprite prefab for Unity.

1. Create a Sprite:
            Choose "GameObject" -> "Create Other" -> "Sprite" as the image bellow shows:

2. Rename the object.
3. Choose the image imported in the "assets" then change the "texture type" to "Sprite(2D\uGUI)":

4. drug the image onto the sprite object and change the z value to "-1", then it will show on the screen.

Some times we also need to use sprite sheet to implement animation like explosion. Here are the steps to make that.


1. Choose the explosion image, change its texture type into Sprite and also modify its  Sprite Mode to "Multiple":

2. Click "Sprite Editor" and slice the sprite sheet:

3. Create a Sprite and name it as "explosion". Add the material to "explosion":

4. Click "Window"-> "Animation"->"Add Curve"->"Sprite Renderer"->"Sprite":



5. Drag the other slices into the Animation Editor:

6. Modify the animation attributes as the images shows:

7. Play and we will see the animation. However, when the animation finishes playing, the object stays at the last image. We want to delete the object, so we need to modify the animation.
  • Add a script to the object:
  • Add an event on the animation and choose the function:

8. Run the game and after animation completes, the object is destroyed.

Set MainCamera to adjust 2D game

Unity is also a good tool to develop 2D games, however it is not convenient to design the game on an initial camera shape which is shown bellow:


So, firstly, let's change the shape of MainCamera:
  Change the value of "Projection" from "Perspective" to "Orthographic" shown as bellow:


Then we add directional light and a background of the scene:


  • Since the value of z axis controls the layer of the game, so the items of the game must have the same z value! 
  • The item with smaller value of z axis is put in front of the bigger value one.