In this part of my tutorial on how to make a Super Mario Clone we cover a ton of topics! We cover how to Fix Collision Errors, Fix Scene Errors, AnimationCurve, Moving the UI with the Camera, Block Collisions, Reacting to Collisions from 1 Direction, Exploding Brick Blocks, Coins, Sounds and More.
Like always the code follows the video below. Here are all the Images and Sounds used.
If you like videos like this consider donating a $1 or simply turn off AdBlock. Either helps a lot 🙂
[googleplusone]
Download all of my Unity game files so far for Pong, Space Invaders, Tetris and Mario
CameraMove.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
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); } } } |
Manny.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 |
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; 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); // 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; } } // 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<SpriteRenderer> (); animator = GetComponent<Animator> (); rb = GetComponent<Rigidbody2D> (); // 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<Collider2D> ().bounds.extents.x + 0.1f; height = GetComponent<Collider2D> ().bounds.extents.y + 0.2f; } // 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); } */ } |
SoundManager.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
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; // 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<AudioSource> (); soundEffectAudio = theSource; } // Other GameObjects can call this to play sounds public void PlayOneShot(AudioClip clip) { soundEffectAudio.PlayOneShot(clip); } } |
PrizeBlock.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 |
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<Text>(); // 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(); } } |
BrickBlock.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
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<SpriteRenderer> (); } // 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); } } } |
Coin.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
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<Text>(); // 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(); } } |
Leave a Reply