Hi. I would like to allow the player to start from the level they lost on rather than having to start the game again. Does anyone know how to do this?
Thank You!
Hi. I would like to allow the player to start from the level they lost on rather than having to start the game again. Does anyone know how to do this?
Thank You!
I’m a noob, but I managed to do it on mine (though there might be a better way): Ice Breaker
In the LoseColider script, I setup a variable to store the current level (scene):
public static int currentLevel;
Then modified this which triggers when the Lose Collider is struck:
void OnTriggerEnter2D (Collider2D trigger) {
// Plays Sound
AudioSource.PlayClipAtPoint (loseSound, transform.position);
// Gets Current Level for Continuing
currentLevel = Application.loadedLevel;
Now, in the LevelManager Script:
private LoseColider currentLevel;
//Continue The Game Function
public void ContinueLevel(int currentLevel) {
Application.LoadLevel(LoseColider.currentLevel);
}
Now setup a button on the Lose Scene with a button and Add Component - Script - LevelManager
Setup the Onclick to run the LevelManager.ContinueLevel
Poke around and see if it works - it will be a great challenge for you if things don’t work right away, which is awesome.
Good luck!
This worked for me! Thank you!
This looks like it’d be really handy for my project too, however I am struggling to get the code working, but no idea what’s going on…
Rubber Duck Debugging. Talk through it slowly, and if you hit something that you don’t understand, look it up. Trust me, it’s helped me so much. I screwed up my code so much that Im only now occasionally getting stuff to work on the first try. Also, pay attention to what unity is telling you about the errors. Double clicking on the error will usually take you to the place in the code that doesn’t work.
My origonal problem was copying the earlier code and not later. My mistake, running into a new issues, but I think if I just focus I might find out what’s wrong with it…
I’m having a kind of irritating issue with my code. This is mostly caused due to the lives. I manage to have the levels reload, but sadly it doesn’t reload the player lives whenever it’s activated.
As I explain this I come up with an idea that perhaps I shouldn’t be trying to alter the LevelManager, but the GameManager script instead. I’ve experimented and I feel to run into the same problem over and over again which is that it claims a line in LevelManager is not functioning when I choose continue and I’ve got no idea how to fix this beyond what I’ve already attempted.
Here are the LevelManager, GameManager and LoseCollider to give you an idea of what I might be missing.
LevelManager:
ing UnityEngine;
using UnityEngine.UI;
using System.Linq;
public class LevelManager : MonoBehaviour
{
private LoseCollider currentLevel;
/// <summary>
/// Initialisation
/// </summary>
private void Start()
{
if (GameObject.Find("Canvas")) // This is a bit messy. It checks to see if there is a canvas, if so, updates the remaining lives
{ // which prevents a null reference exception error occuring on non-playable levels (Win, Loose, Start)
UpdateUIPlayerLivesRemaining();
}
}
public void LoadLevel(string name)
{
Brick.breakableCount = 0;
Application.LoadLevel(name);
}
public void QuitRequest()
{
Application.Quit();
}
public void LoadNextLevel()
{
Brick.breakableCount = 0;
Application.LoadLevel(Application.loadedLevel + 1);
}
public void BrickDestroyed()
{
if (Brick.breakableCount <= 0)
{
LoadNextLevel();
}
}
/// <summary>
/// Updates the player lives UI.Text object with the player's remaining lives
/// </summary>
public void UpdateUIPlayerLivesRemaining()
{
Text uiDisplayPlayerLives = GetTextObjectByName("PlayerLives");
GameManager gameManager = GameObject.FindObjectOfType<GameManager>();
uiDisplayPlayerLives.text = "lives x " + gameManager.PlayerLivesRemaining.ToString();
}
/// <summary>
/// Resets the location of the Ball to the Paddle
/// </summary>
public void ResetBall()
{
Ball ball = GameObject.FindObjectOfType<Ball>();
ball.ResetLaunchPosition();
}
// Helper method which could be moved to a separate class later
/// <summary>
/// Returns a UI.Text object for the specified name
/// </summary>
/// <param name="name">The name of the UI.Text object to return</param>
/// <returns></returns>
private Text GetTextObjectByName(string name)
{
var canvas = GameObject.Find("Canvas"); // Hard coded, assumes the canvas will always be called "Canvas"
var texts = canvas.GetComponentsInChildren<Text>();
return texts.FirstOrDefault(textObject => textObject.name == name);
}
public void ContinueLevel(int currentLevel)
{
Application.LoadLevel(LoseCollider.currentLevel);
}
}
GameManager:
using UnityEngine;
public class GameManager : MonoBehaviour
{
private LoseCollider currentLevel;
// GameManager instance
private GameManager gameManager = null;
// Player
private int playerDefaultLives = 5; // Hard coded value
private int playerLivesRemaining = 0;
/// <summary>
/// Returns the number of lives remaining for the player
/// </summary>
public int PlayerLivesRemaining
{
get {return playerLivesRemaining; }
}
/// <summary>
/// Pre-Initialisation
/// </summary>
private void Awake()
{
// singleton pattern for GameManager
if (gameManager != null)
{
Destroy(gameObject);
}
else
{
gameManager = this;
GameObject.DontDestroyOnLoad(gameObject);
}
}
/// <summary>
/// Initialises a new game by setting the player lives to the default value (3)
/// </summary>
public void NewGame()
{
playerLivesRemaining = playerDefaultLives;
}
/// <summary>
/// Decreases the player's lives by one and checks for a game over state.
/// </summary>
public void PlayerLosesLife()
{
LevelManager levelManager = FindObjectOfType<LevelManager>();
--playerLivesRemaining;
if (playerLivesRemaining < 0)
{
GameOver();
}
else
{
levelManager.UpdateUIPlayerLivesRemaining();
levelManager.ResetBall();
}
}
/// <summary>
/// Loads the "Loose" scene ;) and destroys the GameManager
/// </summary>
private void GameOver()
{
LevelManager levelManager = GameObject.FindObjectOfType<LevelManager>();
levelManager.LoadLevel("Lose");
Destroy(this);
}
public void ContinueLevel(int currentLevel)
{
Application.LoadLevel(LoseCollider.currentLevel);
playerLivesRemaining = 5;
}
}
LoseCollider:
using UnityEngine;
public class LoseCollider : MonoBehaviour
{
private GameManager gameManager;
public static int currentLevel;
/// <summary>
/// Pre-Initialisation
/// </summary>
private void Awake()
{
gameManager = GameObject.FindObjectOfType<GameManager>();
}
/// <summary>
/// Handles the OnTriggerEnter2D event triggered by another object entering a trigger collider attached to the LoseCollider
/// </summary>
/// <param name="collider">The other Collider2D involved in the collision</param>
private void OnTriggerEnter2D(Collider2D collider)
{
gameManager.PlayerLosesLife();
currentLevel = Application.loadedLevel;
}
}
Again, there may be a better practice for this, as it was the first game I programmed.
I make my lives a public static, in the ball script.
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
public class ball : MonoBehaviour {
private Paddle paddle;
public static bool hasStarted = false;
private Vector3 paddleToBallVector;
private Vector2 currentVelocity;
public AudioClip bouncer;
public static int lives = 3;
public Text livesText;
public GameObject howToplay;
public Text scoreText;
// Use this for initialization
void Start () {
paddle = GameObject.FindObjectOfType<Paddle>();
paddleToBallVector = this.transform.position - paddle.transform.position;
}
// Update is called once per frame
void Update ()
{
livesText.text = "Level: " + Application.loadedLevel.ToString()+ " Lives: "+ lives.ToString();
scoreText.text = "Score: "+ Brick.score.ToString();
//livesText.text =
if (!hasStarted) {
// Lock the ball to the paddle
this.transform.position = paddle.transform.position + paddleToBallVector;
//Starts Game, Launches Ball
if (Input.GetMouseButtonDown (0)) {
print ("Mouse Clicked, launch ball.");
hasStarted = true;
Destroy(howToplay);
this.GetComponent<Rigidbody2D> ().velocity = new Vector2 (2f, 10f);
}
}
}
void OnCollisionEnter2D (Collision2D collision)
{
AudioSource.PlayClipAtPoint (bouncer, transform.position);
//this.GetComponent<Rigidbody2D> ().velocity = new Vector2 ((currentVelocity));
Vector2 tweak = new Vector2 (Random.Range (0f, 0.1f), Random.Range (0f, 0.1f));
if (this.GetComponent<Rigidbody2D>().velocity.x < 0) {
tweak = -tweak;
}
GetComponent<Rigidbody2D>().velocity += tweak;
if (hasStarted) {
GetComponent<AudioSource>().Play ();
}
//this.GetComponent<Rigidbody2D> ().velocity = new Vector2 ();
//this.GetComponent<Rigidbody2D> ().velocity = new Vector2 (Random.Range(0f,0.2f), Random.Range(02f,0.2f)+currentVelocity);
}
Then, in the Lose Collider I subtract the lives:
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
public class LoseColider : MonoBehaviour {
private LevelManager levelManager;
public static int currentLevel;
public static ball lives;
public AudioClip loseSound;
void OnTriggerEnter2D (Collider2D trigger) {
// Plays Sound
AudioSource.PlayClipAtPoint (loseSound, transform.position);
// Reduce Score
Brick.score = Brick.score - 200;
// Gets Current Level for Continuing
currentLevel = Application.loadedLevel;
print ("Current Level "+currentLevel);
// Reduce Lives
ball.lives = ball.lives-1;
// Check to see if Continue or End
if (ball.lives <= 0)
{
Brick.breakableCount = 0;
ball.hasStarted = false;
ball.lives =3;
levelManager = GameObject.FindObjectOfType<LevelManager>();
levelManager.LoadLevel("Lose Screen");
}
// Should I continue
else if (ball.lives > 0) {
print ("Continue");
ball.hasStarted = false;
}
}
void OnCollisionEnter2D (Collision2D collision) {
print ("Collision");
}
}