Hierarchy View
The Hierarchy view organizes elements using GameObjects. Some GameObjects may serve as containers for other GameObjects.
Project View
The Project view organizes elements using folders.
GameObject
Bring the GameObject to the full view (three ways):
Duplicate the GameObject (three ways):
Activate or deactivate the GameObject by clicking the Active checkbox in the Inspector view. When the object is deactivated, it is not visible in the scene:
Editor Layout
You can update or create a new layout of the editor's views by using the Layout button:
Global and Local modes
Switch between Global and Local modes:
Scripts
Create a C# script (three ways):
Open a script (three ways):
This tutorial is based on the Unity's Roll-a-ball Tutorial.
Gameboard (playfield)
Add a 3D GameObject (a plane) to the scene (two methods):
Similarily, you can create other 3D objects: cube, sphere, cylinder, etc. All standard 3D objects have dimensions either 1x1x1 or 1x2x1.
Reset the GameObject's Transform using the context-sensitive Gear menu of the Transform component:
Change the scale of the playfield object (two ways):
Note that the plane is a single-sided object and it does not have volume. That's why you can scale the plane only on the X and Z axes but not on the Y axis.
Player
Material
Use a material to add a color or a texture to an object.
Apply the material to the object by dragging the material from the Project view onto the object in the Scene view.
Lighting
Player Movement
To use physics, add the Rigidbody component to the Player GameObject (two ways):
Create a script and attach it to the Player GameObject. Name the script “PlayerController”.
using UnityEngine; // The PlayerController script allows the player to move an associated GameObject using the keyboard. public class PlayerController : MonoBehaviour { // Controls the GameObject's speed. The public variable // shows up as an editable field in the Inspector. public float speed; // Holds the GameObject's Rigidbody component. private Rigidbody rb; // Start is called on the first frame the script is active. // Usually, it is the first frame of the game. private void Start() { // Keep the reference to the GameObject's Rigidbody (if any). rb = GetComponent<Rigidbody>(); } // FixedUpdate is used to apply physics. private void FixedUpdate() { // Accept input from the keyboard. float moveHorizontal = Input.GetAxis("Horizontal"); float moveVertical = Input.GetAxis("Vertical"); // Create the force vector. The force has components // in the xz-plane only. We don't want the y-component. Vector3 movement = new Vector3(moveHorizontal, 0.0f, moveVertical); // Apply the force vector to the Rigidbody. // As a result, the GameObject associated // with the Rigidbody will start moving. rb.AddForce(movement * speed); } }
Follow Camera
First, set the position of the camera by lifting it up by 10 units and tilting it down by 45 degrees:
Next, make the camera follow the Player by attaching the CameraConroller script to the camera:
using UnityEngine; public class CameraConroller : MonoBehaviour { // The player object. Provide it in the camera's Inspector view. public GameObject player; // A difference between the current position of the camera and the position of the player. private Vector3 offset; void Start () { // Calculate the offset by subtracting the position of the player from the position of the camera. // The offset is constant. offset = transform.position - player.transform.position; } // LateUpdate is used to update the follow cameras, procedural animations, and to gather last known state. // LateUpdate is guaranteed to be called after all items in the frame are processed. void LateUpdate () { // Move the camera to a position aligned with the player object. // We execute this code in LateUpdate because we know that the player // has already moved. transform.position = player.transform.position + offset; } }
Collectibles
Spin the PickUp by attaching the Rotator script to it:
using UnityEngine; public class Rotator : MonoBehaviour { // Update is called once per frame. We can use Update instead of FixedUpdate // because we are not using forces in this script. void Update() { // Multiply the rotation angles by Time.deltaTime to make the rotation smooth and frame rate independent. transform.Rotate(new Vector3(15, 30, 45) * Time.deltaTime); } }
Make the PickUp GameObject dynamic by adding the Rigidbody component to it. We need to make it dynamic as we rotate it. Static objects such as a floor or walls do not move.
If you don't add Rigidbody to a moving object, it will remain static and Unity will recalculate its static cache with every movement.
Also, make the PickUp GameObject's Rigidbody kinematic. The kinematic Rigidbody does not respond to physics forces and it can be animated and moved using its transforms:
Turn the PickUp object into a prefab. A prefab is a blueprint for a GameObject or a GameObject family. A prefab instance is a copy of a prefab placed in a scene.
Collisions
We want to pick up our collectibles when the Player collides with them. To do this we need to detect a collision between the collectible GameObject and the Player GameObject.
Detect and test collisions by adding the following code to your PlayerController script:
// OnTriggerEnter is invoked when the GameObject first touches // a trigger collider. This collider is passed as the 'other' parameter. private void OnTriggerEnter(Collider other) { // Deactivate the GameObject only if it has the 'PickUp' tag. // Use the CompareTag method rather than an equality operator // for better efficiency. if (other.gameObject.CompareTag("PickUp")) { // Deactivate the GameObject associated with the other collider. other.gameObject.SetActive(false); } }
This tutorial is based on the Unity tutorial Space Shooter
Player
The Player GameObject has the number of components:
As we will be moving the ship using physics:
Add the Capsule Collider to the Player GameObject. The collider defines the volume of the object.
You may also consider using a Mesh Collider instead of the Capsule Collider. In this case, you need to supply the mesh collider yourselves.
On the collider component:
Another example of the PlayerController script:
using UnityEngine; // The Boundary values shows up as a group in the GameObject's Inspector view. [System.Serializable] public class Boundary { public float xMin, xMax, zMin, zMax; } public class PlayerController : MonoBehaviour { // Controls the GameObject's speed. public float speed; // Controls the GameObject's tilt along the z-axis. public float tilt; // Restricts the boundary of the GameObject's position. public Boundary boundary; // Holds the GameObject's Rigidbody component. private Rigidbody rb; private void Start() { rb = GetComponent<Rigidbody>(); } private void FixedUpdate() { // Accept input from the keyboard. float moveHorizontal = Input.GetAxis("Horizontal"); float moveVertical = Input.GetAxis("Vertical"); // Create the movement vector. Vector3 movement = new Vector3 (moveHoriz, 0.0f, moveVert); // Set the GameObject's velocity. rb.velocity = speed * movement; // Restrict the GameObject's position to the boundary. rb.position = new Vector3 ( Mathf.Clamp(rb.position.x, boundary.xMin, boundary.xMax), 0.0f, Mathf.Clamp(rb.position.z, boundary.zMin, boundary.zMax) ); // Tilt/bank the GameObject along the z-axis. The negative value makes the tilt in // the opposite direction to velocity. We are using rb.velocity.x to tilt the object // in the left/right direction. rb.rotation = Quaternion.Euler (0.0f, 0.0f, rb.velocity.x * -tilt); } }
A missile is a GameObject that moves across the screen and collides with other GameObjects possibly destroying them.
Create GameObjects in hierachy
Set up visual effects
Set up logic
using UnityEngine; public class Mover : MonoBehaviour { public float speed; private Rigidbody rb; // Start is invoked on the first frame the GameObject is instantiated. void Start() { rb = GetComponent<Rigidbody> (); // Move the GameObject forward. The transform.forward property // is the local z-axis of the GameObject. rb.velocity = transform.forward * speed; } }
Shoot the missiles
Add the following code to your player GameObject:
using UnityEngine; public class PlayerController : MonoBehaviour { // The missle prefab. public GameObject shot; // Specify the type of the shotSpawn as a Transform. public Transform shotSpawn; // A delay when the next shot is fired. For example, // fireRate 0.25 fires four shots per second. public float fireRate; // Indicates when we can fire the next shot. private float nextFire; void Update() { // We can put detection of the fire button in Update because we are not using physics. if (Input.GetButton("Fire1") && Time.time > nextFire) { // Limit the fire rate. nextFire = Time.time + fireRate; // shotSpawn is located at the front of the Player. Instantiate( shot, // an object to instantiate shotSpawn.position, // the shot's initial position shotSpawn.rotation // the shot's initial rotation ); } } }
Remove the missiles
We need to remove missiles that did not collide with any objects. Otherwise, they will live forever hogging the game's resources.
using UnityEngine; public class DestroyByBoundary : MonoBehaviour { // Use the OnTriggerExit event as we want to destroy the missiles when they leave the BoundingBox. void OnTriggerExit(Collider other) { Destroy (other.gameObject); } }
Hazards
using UnityEngine; public class RandomRotator : MonoBehaviour { // Determines the maximum tumble value. public float tumble; private Rigidbody rb; void Start() { rb = GetComponent<Rigidbody> (); // angularVelocity determines how fast a GameObject is rotating. // Random.insideUnitSphere gives a random Vector3 value. rb.angularVelocity = Random.insideUnitSphere * tumble; } }
Add the following script to the hazard GameObject (or rather a prefab) in order to destroy it upon a collision with a missile of the player:
using UnityEngine; public class DestroyByContact : MonoBehaviour { // Explosion is rendered when the hazard is destroyed. public GameObject explosion; // PlayerExplosion is rendered when the player is destroyed. public GameObject playerExplosion; // ScoreValue keeps the current number of destroyed hazards. public int scoreValue; // GameController manages the entire game. For example, it spawns the waves of hazards. private GameController controller; void Start() { // Find the instance of the GameController. The FindWithTag method finds the first instance of // a given GameObject. GameObject controllerObject = GameObject.FindWithTag("GameController"); if (controllerObject != null) { // Get the GameController component associated with the GameController object. controller = controllerObject.GetComponent<GameController>(); } if (controller == null) { Debug.Log("Cannot find 'GameController' script."); } } void OnTriggerEnter(Collider other) { // Show an object this GameObject collided with in the Console window. Debug.Log(other.name); // Make sure that this GameObject cannot be destroyed by a collision with the BoundingBox or // a hazard. if (other.CompareTag("BoundingBox") || other.CompareTag("Hazard")) return; // Check if the explosion GameObject is assigned to this GameObject. if (explosion != null) { // Instantiate an explosion in the same position as the hazard. Instantiate (explosion, transform.position, transform.rotation); } // Check if this GameObject (which is a hazard) collided with the Player. if (other.CompareTag("Player")) { // Instantiate a player explosion in the same position as the player. Instantiate(playerExplosion, other.transform.position, other.transform.rotation); // The Player died - game over. controller.GameOver(); } controller.AddScore(scoreValue); // Destory the missile when it touches the hazard. // The Destroy method marks the object to be destroyed. All of the marked objects // are destroyed at the end of the frame. Destroy(other.gameObject); // Destroy the GameObject this script is attached to, and all of its children and attached components. Destroy(gameObject); } }
GameController
Below, there is an example of the GameController which manages the entire game.
using UnityEngine; using System.Collections; public class GameController : MonoBehaviour { public GameObject[] hazards; public Vector3 spawnRange; public int hazardCount; // the number of hazards public float spawnWait; public float startWait; public float waveWait; private bool gameOver; private int score; void Start() { gameOver = false; score = 0; StartCoroutine(SpawnWaves ()); } void Update() { // Spawns waves of hazards. SpawnWaves is a co-routine. That's why it returns IEnumerator. IEnumerator SpawnWaves() { while(true) // allows for continued waves of hazards { // Initial delay. yield return new WaitForSeconds (startWait); for (var i = 0; i < hazardCount; ++i) { // Pick a random hazard. GameObject hazard = hazards[Random.Range(0,hazards.Length)]; // Spawns the hazard only if the game is not over. if (!gameOver) { Vector3 spawnPosition = new Vector3( Random.Range(-spawnRange.x, spawnRange.x), spawnRange.y, spawnRange.z); // y=0, z=16 Quaternion spawnRotation = Quaternion.identity; // no rotation Instantiate(hazard, spawnPosition, spawnRotation); } // Wait before spawning the next hazard. yield return new WaitForSeconds(spawnWait); } // Wait before spawning the next wave. yield return new WaitForSeconds(waveWait); if (gameOver) { break; } } } public void AddScore(int newScore) { score += newScore; } public void GameOver() { gameOver = true; } } }
Show or hide the grid from the Gizmos menu in the upper-right corner of the Scene view:
Move the Scene view to the top-down view by clicking Y in the gizmo:
Use a material to add colour or a texture to a model.
There are three main audio components in Unity:
Associate an audio clip with a GameObject, using an Audio Source component (two ways):
Play a sound when the player clicks the fire button:
private AudioSource audioSource; ... void Start() { audioSource = GetComponent<AudioSource>(); } void Update() { if (Input.GetButton("Fire1")) { audioSource.Play(); } }
GameObjects and components related to Unity UI:
UI controls can be grouped in two categories:
There are three Canvas render modes:
Add a UI Text element to the scene:
When we add the first UI element to the scene, two other elements are added automatically:
UI elements have the Rect Transform tool:
You can use the Anchor Presets tool from the Rect Transform to anchor a UI element to a specific place in Canvas, for example, a left-top corner.
By default, UI elements are anchored to the middle of the screen.
Access a UI Text element from a script. The GameObject that owns the script has to have the 'scoreText' slot associated with a UI Text element.
using UnityEngine; using UnityEngine.UI; public class PlayerController : MonoBehaviour { // Holds the reference to the UI Text element that displays the score. public Text scoreText; private void Start() { scoreText.text = "Score: 0"; } // ... update the score, etc. }
Access the Build Settings:
If you change the platform, you need to press the [Switch Platform] button:
Add the scene to the Build Settings window (two ways):
If you don't add a scene to Build Settings, Unity will build the project with the currently opened scene.