Do you like my tutorials?

Then consider supporting me on Ko-fi

Talking about Tipsy Tower game, C#, Game development and Unity3D.

The tutorial series about Tipsy Tower continues with another update, this time using Unity (I told you I am taking it seriously). I added a lot of features to the first prototype, like the zoomable camera – which actually zooms, unlike the one I did with Phaser – a gradient background, a timer which only counts but does not stop the game at the moment, for a testing purpose, a score system and a responsive canvas background.
Click to drop a crate. Although most of the concepts have been explained in the completely commented source code, some features like the canvas background and texts would need a video or a series of images to be explained in depth. While I am thinking about the best way to show you how to create a game from scratch with Unity, have a look at the code, I commeted it line by line and you’ll surely learn something from it, especially if you read the first step before digging into this version. crateScript.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class crateScript : MonoBehaviour {

	// boolean variable to tell us if the crate already hit something
	public bool hit = false;

	// this function is executed when the game object become ivisible, in this case
	// when it leaves the stage
	void OnBecameInvisible(){

		// destroying game object
		Destroy (gameObject);
	}

	// this function is executed once the crate hits something
	void OnCollisionEnter2D(Collision2D coll) {
		hit = true;
	}
}
movingCrateScript.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class movingCrateScript : MonoBehaviour {

	// this function is executed at each frame
	void Update () {

		// since we can't just change the x position of a game object, we have to create a position which is the same
		// as the original game object position
		Vector3 newPosition = transform.position;

		// this is how we can set a tween, using PingPong on a variable (in this case the time),
		// so that it is never larger than length and never smaller than 0.
		// The returned value will move back and forth between 0 and 4.4f
		newPosition.x =  Mathf.PingPong (Time.time * 5.0f, 5f) - 2.5f;

		// and finally we apply new position to game object's position
		transform.position = newPosition;
	}
}
MainScript.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

// you need to use this class to access UI elements
using UnityEngine.UI;

public class MainScript : MonoBehaviour {

	// crateObject is the physic crate prefab
	public GameObject crateObject;

	// a variable used only inside this class, for PRIVATE use. 
	// canDrop is true if the player can drop a crate, false when the player can't
	private bool canDrop = true;

	// Unity can zoom camera, so we will store into this variable the size of the orthographic projection, that is the level of zoom
	private float targetCameraOrtho = 5f;

	// this will be a time-based game, so here's a variable to keep track of the time left
	public int timeLeft = 60;

	void Start(){

		// Invoking the method called "tick" (first argument) in 1 (second argument) second, then repeatedly every 1 (third argument) second
		InvokeRepeating ("tick", 1, 1);

		// calling updateUIText, will write timeLeft value inside "TimeText" text
		updateUIText ("TimeText", timeLeft.ToString ());
	}

	// this function is executed at each frame
	void Update () {	

		// find an object called "movinCrate" and store it into movingCrate variable
		GameObject movingCrate = GameObject.Find ("movingCrate");

		// checking for player input AND canDrop to be true.
		// it means the player can drop a crate
		if (Input.GetButtonDown ("Fire1") && canDrop) {

			// set canDrop to false
			canDrop = false;

			// calling cangeAlpha function to set movingCrate's alpha to zero (completely transparent)
			changeAlpha (movingCrate, 0f);

			// instantiate a crateObject instance and assign it to physicsCrate variable
			GameObject physicsCrate = Instantiate(crateObject);

			// set physicsCrate position as the same of movingCrate position
			physicsCrate.transform.position = movingCrate.transform.position;
		}

		// declaring an array of game objects
		GameObject[] droppedCrates;

		// filling the array with all objects with tag "Physics Crate"
		droppedCrates = GameObject.FindGameObjectsWithTag("Physics Crate");

		// in maxHeight variable we will store the maximum crate height
		int maxHeight = 0;

		// score is calculated in real time
		int score = 0;

		// this boolean variable will tell us if all crates have landed or hit something
		bool allCratesLanded = true;

		// looping through droppedCrates array
		foreach (GameObject droppedCrate in droppedCrates){

			// looking for crateScript reference
			crateScript crateReference = droppedCrate.GetComponent<crateScript>();

			// hit is now crateReference.hit
			bool hit = crateReference.hit;

			// if the crate already hit something...
			if(hit){

				// getting crate height
				int crateHeight = Mathf.RoundToInt ((droppedCrate.transform.position.y + 4.09f) / 0.77f);

				// update max crate height
				maxHeight = Mathf.Max(maxHeight, crateHeight);

				// if crate height is greater than zero... (when falling down the hill, it could be -1)
				if (crateHeight > 0) {

					// ...update score
					score += crateHeight;
				}
			}
			else{

				// if the crate did not hit anything yet, then allCratesLanded is false
				allCratesLanded = false;
			}
		}

		// calling updateUIText, will write score value inside "ScoreText" text
		updateUIText ("ScoreText", score.ToString ());

		// if the player can't drop and all crates have landed...
		if(!canDrop && allCratesLanded){		

			// setting canDrop to true again, now the player can drop another crate
			canDrop = true;

			// setting moving crate alpha to 1
			changeAlpha (movingCrate, 1f);

			// getting moving crate position
			Vector2 currentCratePos = movingCrate.transform.position;

			// updating current crate y position
			currentCratePos.y = maxHeight * 0.77f + 5 * 0.77f;

			// moving the crate by actually applying the transform position
			movingCrate.transform.position = currentCratePos;

			// change camera zoom according to moving crate vertical position
			targetCameraOrtho = 5 + (currentCratePos.y - 3.5f) / 2f;
		}

		// getting camera instance
		Camera camera = Camera.main;

		// if we need to update camera zoom...
		if (camera.orthographicSize != targetCameraOrtho) {

			// zooming in/out moving from current camera ortographic size to target camera orthographic size
			camera.orthographicSize = Mathf.Lerp (camera.orthographicSize, targetCameraOrtho, Time.deltaTime * 2);

			// once we zoom, we also need to update camera position to keep the ground at the bottom of the stage
			Vector3 position = camera.transform.position;

			// subtracting 5 (the initial orthographic size) to current ortographic size will do
			position.y = camera.orthographicSize - 5f;

			// updating camera position
			camera.transform.position = position;
		}
	}

	// this function changes the alpha of a game object
	void changeAlpha(GameObject sprite, float alpha){

		// since we can't just change the alpha, we have to create a color which is the same
		// as the original game object color
		Color color = sprite.GetComponent<Renderer>().material.color;

		// then we change color's alpha
		color.a = alpha;

		// and finally we apply new color to game object's color
		sprite.GetComponent<Renderer>().material.color = color;
	}

	// this function is called each second
	void tick(){

		// decreasing time left
		timeLeft--;

		// calling updateUIText, will write timeLeft value inside "TimeText" text
		updateUIText ("TimeText", timeLeft.ToString ());

		// if timeLeft is zero...
		if (timeLeft == 0) {

			// stop invoking the timer
			CancelInvoke ();
		}
	}

	// this function will update a UI text
	void updateUIText(string textElement, string textToWrite){

		// finding a game object called as textElement argument
		GameObject canvasElement = GameObject.Find (textElement);

		// getting the Text compment inside the game object
		Text scoreToDisplay = canvasElement.GetComponent<Text> ();

		// updating text content
		scoreToDisplay.text = textToWrite;
	}
}
Next time I’ll show you the final game, with some more extra features, meanwhile download the complete unity project.

Never miss an update! Subscribe, and I will bother you by email only when a new game or full source code comes out.