In this video tutorial we completely finish our Mario Clone!!! It has been a ton of fun for me. I hope you have liked it as well? In this video we will Learn how to Program Wall Jumping, Use Raycasts, Animate Enemies, Create Enemies that Attack, Use Gizmos, Draw a Sprite Sheet, Slice Sprite Sheets and a whole bunch more.
Like always the code follows the video below. The Unity Project files are here
If you enjoy videos like this consider donating $1 or simply turn off AdBlock. Either helps a lot!
[googleplusone]
Code for Mario Clone
BrickBlock.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class BrickBlock : MonoBehaviour {
// Used to change the sprite
private SpriteRenderer sr;
// The sprite to change into
public Sprite explodedBlock;
// Wait time before switching sprites
public float secBeforeSpriteChange = .2f;
void Awake(){
sr = GetComponent
}
// Called when something hits the BrickBlock
void OnCollisionEnter2D(Collision2D col){
// Check if the collision hit the bottom of the block
if (col.contacts [0].point.y < transform.position.y) {
// Play sound
SoundManager.Instance.PlayOneShot (SoundManager.Instance.rockSmash);
// Change the Block sprite
sr.sprite = explodedBlock;
// Wait a fraction of a second and then destroy the BrickBlock
DestroyObject (gameObject, secBeforeSpriteChange);
}
}
}
CameraMove.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CameraMove : MonoBehaviour {
// Put Manny here to track his movement
public Transform cameraTarget;
// How quickly the camera moves towards Manny
public float cameraSpeed;
// Min and max X and Y movements
public float minX;
public float minY;
public float maxX;
public float maxY;
// Update used when dealing with Rigid Bodies
void FixedUpdate(){
// Make sure the camera has a target
if (cameraTarget != null) {
// Lerp smoothes movement from the starting position
// to the targets position
var newPos = Vector2.Lerp (transform.position,
cameraTarget.position,
Time.deltaTime * cameraSpeed);
// Define the cameras new postion
var vect3 = new Vector3 (newPos.x, newPos.y, -10f);
// Clamp gets the cameras x position and clamps
// it between the min and max value
var clampX = Mathf.Clamp (vect3.x, minX, maxX);
var clampY = Mathf.Clamp (vect3.y, minY, maxY);
// Move the camera
transform.position = new Vector3(clampX, clampY, -10f);
}
}
}
Coin.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
// Needed to manipulate the UI
using UnityEngine.UI;
public class Coin : MonoBehaviour {
// Called when something hits the Coin
void OnCollisionEnter2D(Collision2D col){
// Play coin sound
SoundManager.Instance.PlayOneShot (SoundManager.Instance.getCoin);
// Increase the Score Text component
increaseTextUIScore();
Destroy (gameObject);
}
// Increases the score the the text UI name passed
void increaseTextUIScore(){
// Find the Score UI component
var textUIComp = GameObject.Find(“Score”).GetComponent
// Get the string stored in it and convert to an int
int score = int.Parse(textUIComp.text);
// Increment the score
score += 10;
// Convert the score to a string and update the UI
textUIComp.text = score.ToString();
}
}
Manny.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Manny : MonoBehaviour {
// Defines Mannys speed horizontally
public float speed = 5;
// Defines Mannys facing direction
public bool facingRight = true;
// Jump speed
public float jumpSpeed = 5f;
// Mannys components
// private SpriteRenderer sr;
private Rigidbody2D rb;
private Animator animator;
// Will flip depending if on ground
bool isJumping = false;
// Used to check if Manny is on the ground
// You draw a line out away from the sprite a defined
// distance and check if it collides with something
// If it hits nothing Raycast() returns null
private float rayCastLength = 0.005f;
// Sprite width and height
private float width;
private float height;
// How long is the jump button held
private float jumpButtonPressTime;
// Max jump amount
public float maxJumpTime = 0.2f;
// —– 1. NEW STUFF —–
// Special Y velocity value used when jumping off of a wall
public float wallJumpY = 10f;
// —– END OF NEW STUFF —–
void FixedUpdate(){
// Get horizontal movement -1 Left, or 1 Right
float horzMove = Input.GetAxisRaw (“Horizontal”);
// Need to get Mannys y
Vector2 vect = rb.velocity;
// Change x and keep y as is
rb.velocity = new Vector2 (horzMove * speed, vect.y);
// —– 1. NEW STUFF —–
// If Manny is jumping next to a wall his velocity will
// go up in the Y direction
if (IsWallOnLeftOrRight () && !IsOnGround () && horzMove == 1) {
rb.velocity = new Vector2 (-GetWallDirection () * speed * -.75f,
wallJumpY);
}
// —– END OF NEW STUFF —–
// Set the speed so the right Animation is played
animator.SetFloat(“Speed”, Mathf.Abs(horzMove));
// Makes sure Manny is facing the right direction
if (horzMove > 0 && !facingRight) {
FlipManny ();
} else if (horzMove < 0 && facingRight) {
FlipManny ();
}
// Get vertical movement
float vertMove = Input.GetAxis ("Jump");
if (IsOnGround () && isJumping == false) {
if (vertMove > 0f) {
isJumping = true;
// —– NEW STUFF —–
SoundManager.Instance.PlayOneShot (SoundManager.Instance.jump);
// —– END OF NEW STUFF —–
}
}
// If button is held pass max time set
// vertical move to 0
if (jumpButtonPressTime > maxJumpTime) {
vertMove = 0f;
}
// If is jumping and we have a valid jump press length
// make Manny jump
if (isJumping && (jumpButtonPressTime < maxJumpTime)) {
rb.velocity = new Vector2 (rb.velocity.x, jumpSpeed);
}
// If we have moved high enough make Manny fall
// Set Mannys Rigidbody 2d Gravity Scale to 2
if (vertMove >= 1f) {
jumpButtonPressTime += Time.deltaTime;
} else {
isJumping = false;
jumpButtonPressTime = 0f;
}
}
// Makes sure components have been created when the
// game starts
void Awake(){
// sr = GetComponent
animator = GetComponent
rb = GetComponent
// Gets Mannys collider width and height and
// then adds more to it. Used to raycast to see
// if Manny is colliding with anything so we
// can jump
width = GetComponent
height = GetComponent
}
// When moving in a direction face in that direction
void FlipManny(){
// Flip the facing value
facingRight = !facingRight;
Vector3 scale = transform.localScale;
scale.x *= -1;
transform.localScale = scale;
}
public bool IsOnGround(){
// Check if contacting the ground straight down
bool groundCheck1 = Physics2D.Raycast (new Vector2 (
transform.position.x,
transform.position.y – height),
-Vector2.up, rayCastLength);
// Check if contacting ground to the right
bool groundCheck2 = Physics2D.Raycast (new Vector2 (
transform.position.x + (width – 0.2f),
transform.position.y – height),
-Vector2.up, rayCastLength);
// Check if contacting ground to the left
bool groundCheck3 = Physics2D.Raycast (new Vector2 (
transform.position.x – (width – 0.2f),
transform.position.y – height),
-Vector2.up, rayCastLength);
if (groundCheck1 || groundCheck2 || groundCheck3)
return true;
return false;
}
// If Manny falls off the screen destroy the game object
void OnBecameInvisible(){
Debug.Log (“Manny Destroyed”);
Destroy (gameObject);
}
// —– 1. NEW STUFF —–
public bool IsWallOnLeft(){
// -Vector2.right checks to the left with a raycast
// for a wall
return Physics2D.Raycast (new Vector2 (transform.position.x – width,
transform.position.y),
-Vector2.right,
rayCastLength);
}
public bool IsWallOnRight(){
// Vector2.right checks to the left with a raycast
// for a wall
return Physics2D.Raycast (new Vector2 (transform.position.x + width,
transform.position.y),
Vector2.right,
rayCastLength);
}
// Verifies if walls are on left or right for wall jumping
public bool IsWallOnLeftOrRight(){
if (IsWallOnLeft() || IsWallOnRight()) {
return true;
} else {
return false;
}
}
// Gets the wall direction if it exists
// Multiply the results against Manny’s X velocity
public int GetWallDirection(){
if (IsWallOnLeft ()) {
return -1;
} else if (IsWallOnRight ()) {
return 1;
} else {
return 0;
}
}
// —– END OF NEW STUFF —–
}
PrizeBlock.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
// Needed to manipulate the UI
using UnityEngine.UI;
public class PrizeBlock : MonoBehaviour {
public AnimationCurve anim;
public int coinsInBlock = 5;
void OnCollisionEnter2D(Collision2D col){
// Check if the collision hit the bottom of the block
if (col.contacts [0].point.y < transform.position.y) {
// Calls RunAnimation which will be paused
// and resumed over time
StartCoroutine (RunAnimation());
}
// If block contains coins
if (coinsInBlock > 0) {
// Play coin sound
SoundManager.Instance.PlayOneShot (SoundManager.Instance.getCoin);
// Increase the Score Text component
increaseTextUIScore();
coinsInBlock–;
}
}
IEnumerator RunAnimation(){
// Get starting position of PrizeBlock
Vector2 startPos = transform.position;
// Cycle through all the keys in the animation curve
for (float x = 0; x < anim.keys[anim.length-1].time; x += Time.deltaTime) {
// Change the block position to what is defined
// on the AnimationCurve
transform.position = new Vector2 (startPos.x,
startPos.y + anim.Evaluate (x));
// Continue looping at next update
yield return null;
}
}
// Increases the score the the text UI name passed
void increaseTextUIScore(){
// Find the Score UI component
var textUIComp = GameObject.Find("Score").GetComponent
// Get the string stored in it and convert to an int
int score = int.Parse(textUIComp.text);
// Increment the score
score += 10;
// Convert the score to a string and update the UI
textUIComp.text = score.ToString();
}
}
Snail.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Snail : MonoBehaviour {
// Snail speed
public float speed = 2;
// Snail Direction
Vector2 direction = Vector2.right;
void FixedUpdate(){
// Move the snail
GetComponent
}
void OnTriggerEnter2D(Collider2D col){
// If you hit SnailStart & SnailEnd flip direction
transform.localScale = new Vector2 (-1 * transform.localScale.x,
transform.localScale.y);
direction = new Vector2 (-1 * direction.x, direction.y);
}
// If Manny hits the top of the snail kill the snail
// and otherwise kill Manny
void OnCollisionEnter2D(Collision2D col){
if (col.gameObject.name == “Manny”) {
// If hit from above play dead animation, remove
// the collider so the snail falls off the screen
// and kill Snail after 3 seconds
if (col.contacts [0].point.y > transform.position.y) {
GetComponent
GetComponent
direction = new Vector2 (direction.x, -1);
DestroyObject (gameObject, 3);
} else {
// Kill manny
SoundManager.Instance.PlayOneShot (SoundManager.Instance.mannyDies);
DestroyObject (col.gameObject, .5f);
}
}
}
}
SoundManager.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SoundManager : MonoBehaviour {
// Holds the single instance of the SoundManager that
// you can access from any script
public static SoundManager Instance = null;
// All sound effects in the game
// All are public so you can set them in the Inspector
public AudioClip jump;
public AudioClip getCoin;
public AudioClip rockSmash;
// —– NEW STUFF —–
public AudioClip mannyDies;
// —– END OF NEW STUFF —–
// Refers to the audio source added to the SoundManager
// to play sound effects
private AudioSource soundEffectAudio;
// Use this for initialization
void Start() {
// This is a singleton that makes sure you only
// ever have one Sound Manager
// If there is any other Sound Manager created destroy it
if (Instance == null) {
Instance = this;
} else if (Instance != this) {
Destroy (gameObject);
}
AudioSource theSource = GetComponent
soundEffectAudio = theSource;
}
// Other GameObjects can call this to play sounds
public void PlayOneShot(AudioClip clip) {
soundEffectAudio.PlayOneShot(clip);
}
}