‘Dodge The Spike’-Endless Runner Tech Blog
6 min readMar 9, 2022
This blog contains the steps required to make an Endless runner game similar to the famous Dinosaur Game. I have used Unity as my game engine and the scripts are written in C#.
Note: I will be updating this blog as I am still working on the game.
Links for all the Assets used
Creating the character
Create an empty game object and add the Sprite Renderer component to it
- Set the layer of the game object to ‘Player’ and rename the object to ‘Player’
Add the RigidBody2D component to the Player
- Change the body type to Dynamic. Under constraints, freeze the Z axis rotation. This is done so that the player does not rotate about its Z axis when any collision occurs.
Add the BoxCollider2D component to the Player
- Click on ‘Edit Collider’ and adjust the box collider appropriately.
Creating the background
Create a new rectangular tilemap
- Create a duplicate of the child object(tilemap). Name the first one to ‘Background’ and the second one to ‘Collision’.
- Add the desired assets in the tile palette to start designing the background.
- Draw on the Background tilemap and create the background as per your choice
- Set the Layer to ‘Default’
Select the ‘Collision’ tilemap and add Tilemap Collider 2D, Rigidbody 2D and Composite Collider 2D components.
Under Tilemap Collider 2D, check ‘Used by Composite’.
- Under Rigidbody 2D, set the body type to static so that the object does not move once the game has started.
- Draw the desired platform on the ‘Collision’ tilemap
Note: Ensure that you have selected the ‘Collision’ tilemap while drawing the platform.
- Set the Layer to ‘Collision’
Player Movement
- Create a new C# script and add it to the player.
- Name it ‘PlayerMovement’
- This script will be responsible for the player’s movement. In this case, the player only has the abilty to jump.
using System.Collections;using System.Collections.Generic;using UnityEngine;public class PlayerMovement : MonoBehaviour{public Vector3 jump;public float jumpForce = 2.0f;private Rigidbody2D rb;public bool isGrounded;private BoxCollider2D coll;float distToGround;void Start(){rb = GetComponent<Rigidbody2D>();jump = new Vector3(0.0f,2.0f,0.0f);coll = GetComponent<BoxCollider2D>();}void OnCollisionStay2D(){isGrounded = true;}// Update is called once per framevoid Update(){if(Input.GetButtonDown("Jump") && isGrounded){rb.velocity = new Vector2(rb.velocity.x,jumpForce);isGrounded = false;}}private void OnCollisionEnter2D(Collision2D other) {if(other.gameObject.CompareTag("Spike")){Destroy(rb.gameObject);}}}
Spike
- The spike will act as the obstacle which the player has to jump over
- The spike will be given a velocity in the negative direction so it would appear as if it is coming from the right side of the screen
- Add a Polygon Collider 2D component to the spike
- Add Rigidbody 2D component and set the body type to Dynamic
- Freeze the z-axis rotation
using System.Collections;using System.Collections.Generic;using UnityEngine;public class Spike : MonoBehaviour{public float speed = 10.0f;private Rigidbody2D rb;void Start(){rb = this.GetComponent<Rigidbody2D>();rb.velocity = new Vector2(-speed,0.0f); //to make the spike move in negative x direction}// Update is called once per framevoid Update(){if(transform.position.x < -11.5f){//this.gameObject.SetActive(false);}}}
This was just one instance of the spike
To spawn multiple spikes, we make a prefab of the spike and use the Instantiate method to spawn it
using System.Collections;using System.Collections.Generic;using UnityEngine;public class SpawnSpike : MonoBehaviour{public GameObject spike;public float respawnTime = 1.0f;void Start(){StartCoroutine(spikeWave());}private void spawnSpike(){GameObject a= Instantiate(spike) as GameObject;a.transform.position = new Vector2(Random.Range(11.0f,17.0f),-3.5f);}// Update is called once per frameIEnumerator spikeWave(){while(true){yield return new WaitForSeconds(respawnTime);spawnSpike();}}}
- Here we use the random function to randomly set the x position of the spike so that all the spikes are not equidistant from each other.
- We also use IEnumerator to call the spawnSpike method after a few seconds (respawnTime=1.0f). This way, a new spike is spawned at a random position every second.
Score
- Create an UI object for score and highscore.
- Make appropriate changes
using System.Collections;using System.Collections.Generic;using UnityEngine;using UnityEngine.UI;public class Score : MonoBehaviour{public Text score;public float scoreAmount;public float pointIncreasedPerSecond;public AudioSource newHigh;public Text highScore;public bool soundPlayed;void Start(){scoreAmount=0f;pointIncreasedPerSecond = 1f;highScore.text ="HighScore: "+ PlayerPrefs.GetInt("HighScore",0).ToString(); //set default value to 0soundPlayed=false;}// Update is called once per framevoid Update(){score.text = "Score: "+ (int)scoreAmount;scoreAmount+= pointIncreasedPerSecond * Time.deltaTime;if ( scoreAmount > PlayerPrefs.GetInt("HighScore",0)){if (!soundPlayed) {newHigh.Play();soundPlayed = true;}PlayerPrefs.SetInt("HighScore", (int)scoreAmount);highScore.text = "HighScore: "+ (int)scoreAmount;}}public void Reset() {PlayerPrefs.DeleteKey("HighScore");}}
- The score is set to 0 and is incremented by 1 each second
- If the score is greater than the highscore, then the highscore is updated
Buttons
- Create 2 UI buttons, one for restart and one to reset the score
- Add onClick funtion in restart(play again) button and set the function to restart which is present in the RestartGame script
using System.Collections;using System.Collections.Generic;using UnityEngine;using UnityEngine.SceneManagement;public class RestartGame : MonoBehaviour{// Start is called before the first frame updatepublic void RGame(){SceneManager.LoadScene(SceneManager.GetActiveScene().name);Time.timeScale = 1;}}
- Add onClick function in Reset button and add set the function to reset which is present in Score script
Attach Score script to Reset button object