Improvements to Unity Endless Runner tutorial from http://catlikecoding.com/unity/tutorials/runner/; Find more information about my version at http://ideascomecheap.blogspot.com/search/label/Unity%20Endless%20Runner%20Tutorial
public static class GameEventManager { | |
public delegate void GameEvent(); | |
public static event GameEvent GameStart, GameOver, | |
GamePause, GameResume; | |
public static void TriggerGameStart() { | |
if (GameStart != null) { | |
GameStart(); | |
} | |
} | |
public static void TriggerGameOver() { | |
if (GameOver != null) { | |
GameOver(); | |
} | |
} | |
public static void TriggerGamePause() { | |
if (GamePause != null) { | |
GamePause(); | |
} | |
} | |
public static void TriggerGameResume() { | |
if (GameResume != null) { | |
GameResume(); | |
} | |
} | |
} |
// This is a new file that is not mentioned in the tutorial | |
// | |
// To use this, create a new empty under manager with this attached | |
// | |
// This is created so that Android application can be exited by pressing the back button | |
using UnityEngine; | |
public class GameExitManager : MonoBehaviour { | |
void Update () { | |
if (Input.GetKeyDown("escape")) { | |
Application.Quit(); | |
} | |
} | |
} |
using UnityEngine; | |
public class GameStateManager : MonoBehaviour { | |
enum State { PLAY, PAUSE } | |
private State gameState; | |
public GUITexture speakerToggleControl; | |
void Start() { | |
GameEventManager.GameStart += GameStart; | |
GameEventManager.GameOver += GameOver; | |
GameEventManager.GamePause += GamePause; | |
GameEventManager.GameResume += GameResume; | |
gameState = State.PLAY; | |
enabled = false; | |
} | |
void Update() { | |
if (gameState == State.PLAY && Input.GetKeyDown("escape")) { | |
Time.timeScale = 0.0f; | |
GameEventManager.TriggerGamePause(); | |
} | |
else if (gameState == State.PAUSE && | |
(Input.GetButtonDown("Jump") || | |
((Application.platform == RuntimePlatform.Android) && (Input.touchCount > 0 && | |
Input.GetTouch(0).phase == TouchPhase.Began && | |
!speakerToggleControl.HitTest(Input.GetTouch (0).position))))) { | |
Time.timeScale = 1.0f; | |
GameEventManager.TriggerGameResume(); | |
} | |
else if (gameState == State.PAUSE && Input.GetKeyDown("escape")) { | |
Application.Quit(); | |
} | |
} | |
private void GameStart() { | |
enabled = true; | |
} | |
private void GameOver() { | |
enabled = false; | |
} | |
private void GamePause() { | |
gameState = State.PAUSE; | |
} | |
private void GameResume() { | |
gameState = State.PLAY; | |
} | |
} |
using UnityEngine; | |
using System; | |
using System.Collections; | |
public class GUIManager : MonoBehaviour { | |
public GUIText boostsText, | |
distanceText, | |
gameOverText, | |
instructionsText, | |
runnerText, | |
highScoresText, | |
gamePauseText, | |
onPauseInstructionsText; | |
public GUITexture boostsSign, | |
speakerToggleControl, | |
highScoresSign; | |
private static GUIManager instance; | |
void Start() { | |
instance = this; | |
GameEventManager.GameStart += GameStart; | |
GameEventManager.GameOver += GameOver; | |
gameOverText.enabled = false; | |
// Hans | |
boostsText.enabled = false; | |
boostsSign.enabled = false; | |
distanceText.enabled = false; | |
highScoresText.enabled = false; | |
highScoresSign.enabled = false; | |
GameEventManager.GamePause += GamePause; | |
GameEventManager.GameResume += GameResume; | |
gamePauseText.enabled = false; | |
onPauseInstructionsText.enabled = false; | |
if (Application.platform == RuntimePlatform.Android) { | |
instructionsText.text = "Tap to play or press back to quit"; | |
onPauseInstructionsText.text = "Tap to resume or press back to quit"; | |
} | |
} | |
void Update() { | |
if ((Input.GetButtonDown("Jump")) || | |
((Application.platform == RuntimePlatform.Android) && (Input.touchCount > 0 && | |
Input.GetTouch(0).phase == TouchPhase.Began && | |
!speakerToggleControl.HitTest(Input.GetTouch(0).position)))) { | |
GameEventManager.TriggerGameStart(); | |
} | |
else if (Input.GetKeyDown("escape")) | |
{ | |
Application.Quit(); | |
} | |
} | |
private void GameStart() { | |
gameOverText.enabled = false; | |
instructionsText.enabled = false; | |
runnerText.enabled = false; | |
highScoresText.enabled = false; | |
highScoresSign.enabled = false; | |
boostsText.enabled = true; | |
boostsSign.enabled = true; | |
distanceText.enabled = true; | |
enabled = false; | |
} | |
private void GameOver() { | |
boostsText.enabled = false; | |
boostsSign.enabled = false; | |
distanceText.enabled = false; | |
gameOverText.enabled = true; | |
instructionsText.enabled = true; | |
highScoresText.enabled = true; | |
highScoresSign.enabled = true; | |
enabled = true; | |
} | |
private void GamePause() { | |
gamePauseText.enabled = true; | |
onPauseInstructionsText.enabled = true; | |
} | |
private void GameResume() { | |
gamePauseText.enabled = false; | |
onPauseInstructionsText.enabled = false; | |
} | |
public static void SetBoosts(int boosts) { | |
instance.boostsText.text = boosts.ToString(); | |
} | |
public static void SetDistance(float distance) { | |
instance.distanceText.text = distance.ToString("f0"); | |
} | |
public static void SetHighScoreBoard(ArrayList highScores) { | |
string highScoreBoard = "High Scores"; | |
for (int i = 0; i < highScores.Count; i++) { | |
highScoreBoard += "\n"; | |
highScoreBoard += (i+1).ToString() + ". "; | |
highScoreBoard += highScores[i].ToString(); | |
} | |
instance.highScoresText.text = highScoreBoard; | |
Rect highScoresTextSize = instance.highScoresText.GetScreenRect(); | |
//print(highScoresTextSize); | |
float highScoresSignWidth = highScoresTextSize.width + 60; | |
float highScoresSignHeight = highScoresTextSize.height + 40; | |
// The object position in the scene (x = 0.5, y = 0.9) will be the reference for the rect. | |
// These position will be treated as 0 of left and top. x goes from left to right and y from top to bottom. | |
// Hence, the left will be width/2, while top will be height (since the object pivot is bottom left - | |
// try setting both left and top as 0 to see this) substracted by half of padding (40/2 as of above). | |
float highScoresSignLeft = -1 * highScoresSignWidth/2; | |
float highScoresSignTop = -1 * highScoresTextSize.height - 20; | |
instance.highScoresSign.guiTexture.pixelInset = new Rect(highScoresSignLeft, | |
highScoresSignTop, | |
highScoresSignWidth, | |
highScoresSignHeight); | |
} | |
} |
using UnityEngine; | |
using System; | |
using System.Collections; | |
public class HighScoreSaveLoadManager : MonoBehaviour { | |
public int noOfHighScores; | |
private ArrayList highScores = new ArrayList(); | |
private static HighScoreSaveLoadManager instance; | |
void Start () { | |
instance = this; | |
LoadHighScore(); | |
} | |
public static int GetHighScoresQuota() { | |
return instance.noOfHighScores; | |
} | |
public static ArrayList GetHighScores() { | |
return instance.highScores; | |
} | |
public static void SetHighScores(ArrayList updatedHighScore) { | |
instance.highScores = updatedHighScore; | |
SaveHighScore(); | |
} | |
private static void SaveHighScore() { | |
for (int i = 0; i < instance.highScores.Count; i++) { | |
PlayerPrefs.SetInt("HighScore"+i.ToString(), (int) instance.highScores[i]); | |
} | |
} | |
private static void LoadHighScore() { | |
ArrayList loadHighScores = new ArrayList(); | |
int counter = 0; | |
while (true) { | |
if (PlayerPrefs.HasKey("HighScore"+counter.ToString())) { | |
loadHighScores.Add(PlayerPrefs.GetInt("HighScore"+counter.ToString())); | |
counter++; | |
} | |
else { | |
break; | |
} | |
} | |
instance.highScores = loadHighScores; | |
} | |
} |
using UnityEngine; | |
using System; | |
using System.Collections; | |
public class Runner : MonoBehaviour { | |
public static float distanceTraveled; | |
public float acceleration; | |
public Vector3 boostVelocity, jumpVelocity; | |
public float gameOverY; | |
private bool touchingPlatform; | |
private Vector3 startPosition; | |
private static int boosts; | |
void Start() { | |
GameEventManager.GameStart += GameStart; | |
GameEventManager.GameOver += GameOver; | |
GameEventManager.GamePause += GamePause; | |
GameEventManager.GameResume += GameResume; | |
startPosition = transform.localPosition; | |
renderer.enabled = false; | |
rigidbody.isKinematic = true; | |
enabled = false; | |
} | |
private void GameStart () { | |
boosts = 0; | |
GUIManager.SetBoosts(boosts); | |
distanceTraveled = 0f; | |
GUIManager.SetDistance(distanceTraveled); | |
transform.localPosition = startPosition; | |
renderer.enabled = true; | |
rigidbody.isKinematic = false; | |
enabled = true; | |
} | |
private void GameOver() { | |
RecordScoreIfNecessary(); | |
renderer.enabled = false; | |
rigidbody.isKinematic = true; | |
enabled = false; | |
} | |
private void GamePause() { | |
enabled = false; | |
} | |
private void GameResume() { | |
enabled = true; | |
} | |
void Update () { | |
if ((Input.GetButtonDown("Jump")) || | |
((Application.platform == RuntimePlatform.Android) && (Input.touchCount > 0 && Input.GetTouch(0).phase == TouchPhase.Began))) { | |
Jump (); | |
} | |
distanceTraveled = transform.localPosition.x; | |
GUIManager.SetDistance (distanceTraveled); | |
if (transform.localPosition.y < gameOverY) { | |
GameEventManager.TriggerGameOver(); | |
} | |
} | |
void FixedUpdate() { | |
if (touchingPlatform) { | |
rigidbody.AddForce(acceleration, 0f, 0f, ForceMode.Acceleration); | |
} | |
} | |
void OnCollisionEnter() { | |
touchingPlatform = true; | |
} | |
void OnCollisionExit() { | |
touchingPlatform = false; | |
} | |
public static void AddBoost() { | |
boosts += 1; | |
GUIManager.SetBoosts(boosts); | |
} | |
private void Jump() { | |
if (touchingPlatform) { | |
rigidbody.AddForce(jumpVelocity, ForceMode.VelocityChange); | |
touchingPlatform = false; // This allow one jump after colliding with side of platform, but not more | |
} | |
else if (boosts > 0) { | |
rigidbody.AddForce(boostVelocity, ForceMode.VelocityChange); | |
boosts -= 1; | |
GUIManager.SetBoosts (boosts); | |
} | |
} | |
public void RecordScoreIfNecessary() { | |
int roundedScore = (int) Math.Round(distanceTraveled); | |
ArrayList highScores = HighScoreSaveLoadManager.GetHighScores(); | |
int highScoresQuota = HighScoreSaveLoadManager.GetHighScoresQuota(); | |
highScores.Add(roundedScore); | |
highScores.Sort(); | |
highScores.Reverse(); | |
if (highScores.Count > highScoresQuota) { | |
highScores.RemoveRange(highScoresQuota, highScores.Count - highScoresQuota); | |
} | |
// for (int i = 0; i < highScores.Count; i++) { | |
// Debug.Log(highScores[i]); | |
// } | |
GUIManager.SetHighScoreBoard(highScores); | |
HighScoreSaveLoadManager.SetHighScores(highScores); | |
} | |
} |
using UnityEngine; | |
using System.Collections; | |
public class SpeakerToggleControl : MonoBehaviour { | |
private bool soundStatus; | |
public Texture speakerOn; | |
public Texture speakerOff; | |
private enum BgmStatus { OFF = 0, ON = 1}; | |
void Start() { | |
if (PlayerPrefs.HasKey("BgmStatus")) { | |
if (PlayerPrefs.GetInt("BgmStatus") == (int) BgmStatus.ON) { | |
soundStatus = true; | |
SetAudioListener(true); | |
} | |
else { | |
soundStatus = false; | |
SetAudioListener(false); | |
} | |
} | |
else { | |
soundStatus = true; | |
SetAudioListener(true); | |
SaveBgmStatus(BgmStatus.ON); | |
} | |
GameEventManager.GameStart += GameStart; | |
GameEventManager.GamePause += GamePause; | |
GameEventManager.GameResume += GameResume; | |
} | |
void OnMouseUp() { | |
if (soundStatus) | |
{ | |
SetAudioListener(false); | |
} | |
else | |
{ | |
SetAudioListener(true); | |
} | |
soundStatus = !soundStatus; | |
SaveBgmStatus(soundStatus); | |
} | |
void SetAudioListener(bool status) { | |
if (status) { | |
AudioListener.pause = false; | |
AudioListener.volume = 1; | |
guiTexture.texture = speakerOn; | |
} | |
else { | |
AudioListener.pause = true; | |
AudioListener.volume = 0; | |
guiTexture.texture = speakerOff; | |
} | |
} | |
void SaveBgmStatus(bool status) { | |
if (status) { | |
PlayerPrefs.SetInt("BgmStatus", (int) BgmStatus.ON); | |
} | |
else { | |
PlayerPrefs.SetInt("BgmStatus", (int) BgmStatus.OFF); | |
} | |
} | |
void SaveBgmStatus(BgmStatus status) { | |
PlayerPrefs.SetInt("BgmStatus", (int) status); | |
} | |
void GameStart() { | |
guiTexture.enabled = false; | |
} | |
void GamePause() { | |
guiTexture.enabled = true; | |
} | |
void GameResume() { | |
guiTexture.enabled = false; | |
} | |
} |
This comment has been minimized.
This comment has been minimized.
I need this idea... |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This comment has been minimized.
Amazing project....!! Good