I’ve managed to achieve this with dying and respawning back to a checkpoint, and even then it was because of following a tutorial and copying some code, but I can’t figure out how I can get the same result just from exiting one scene and (re)loading another. Obviously, using SceneManager.LoadScene destroys everything and resets the level from the start. Is there an alternative I can use where it doesn’t destroy the previous scene, or specifically the character’s location? Or maybe some code? I’ve tried experimenting with a couple of older scripts involving a HealthManager and a Checkpoints script, as they include parts to do with respawnPoints, but I can’t get them to work when loading from one scene to another. These are all the scripts I have so far, just to give an idea of what I have:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class HealthManager : MonoBehaviour
{
//The counters will count down and will keep counting down based on the length variables
public int maxHealth;
public int currentHealth;
public float invincibilityLength;
public Renderer playerRenderer;
public float flashLength;
public float respawnLength;
public GameObject deathEffect;
public Image blackScreen;
public float fadeSpeed;
public float waitForFade;
private float invincibilityCounter;
private float flashCounter;
private bool isRespawning;
private Vector3 respawnPoint;
private bool isFadetoBlack;
private bool isFadefromBlack;
public PlayerController thePlayer;
void Start()
{
thePlayer = FindObjectOfType<PlayerController>();
currentHealth += maxHealth;
respawnPoint = thePlayer.transform.position;
}
void Update()
{
//These functions are checked every frame until the player takes damage
if(invincibilityCounter > 0)
{
invincibilityCounter -= Time.deltaTime;
flashCounter -= Time.deltaTime;
if(flashCounter <= 0)
//The Flash Counter is currently set at 0.1 and will be within the 0 region as it counts down. During this period, the playerRenderer will alternate between on and off
{
playerRenderer.enabled = !playerRenderer.enabled;
//The Flash Counter will keep counting down and reloop depending on the Flash Length time
flashCounter = flashLength;
}
//This makes sure after the flashing and invincibility has worn off that the player renderer is always turned back on so you can see the player
if(invincibilityCounter <= 0)
{
playerRenderer.enabled = true;
}
}
if (isFadetoBlack)
{
blackScreen.color = new Color(blackScreen.color.r, blackScreen.color.g, blackScreen.color.b, Mathf.MoveTowards(blackScreen.color.a, 1f, fadeSpeed * Time.deltaTime));
if (blackScreen.color.a == 1f)
{
isFadetoBlack = false;
}
}
if (isFadefromBlack)
{
blackScreen.color = new Color(blackScreen.color.r, blackScreen.color.g, blackScreen.color.b, Mathf.MoveTowards(blackScreen.color.a, 0f, fadeSpeed * Time.deltaTime));
if (blackScreen.color.a == 0f)
{
isFadefromBlack = true;
}
}
}
public void HurtPlayer(int damage, Vector3 direction)
{
//If the invincibility countdown reaches zero it stops, making you no longer invincible and prone to taking damage again
if (invincibilityCounter <= 0)
{
currentHealth -= damage;
if (currentHealth <= 0)
{
Respawn();
}
else
{
thePlayer.Knockback(direction);
invincibilityCounter = invincibilityLength;
playerRenderer.enabled = false;
flashCounter = flashLength;
}
}
}
public void Respawn()
{
//A StartCoroutine must be set up before the IEnumerator can begin
if (!isRespawning)
{
StartCoroutine("RespawnCo");
}
}
//IEnumerators or Coroutines will execute the code separately at specified times while the rest of the code in a codeblock will carry on executing as normal
public IEnumerator RespawnCo()
{
isRespawning = true;
thePlayer.gameObject.SetActive(false);
Instantiate(deathEffect, thePlayer.transform.position, thePlayer.transform.rotation);
yield return new WaitForSeconds(respawnLength);
isFadetoBlack = true;
yield return new WaitForSeconds(waitForFade);
isFadefromBlack = true;
isRespawning = false;
thePlayer.gameObject.SetActive(true);
thePlayer.transform.position = respawnPoint;
currentHealth = maxHealth;
invincibilityCounter = invincibilityLength;
playerRenderer.enabled = false;
flashCounter = flashLength;
}
public void HealPlayer(int healAmount)
{
currentHealth += healAmount;
if(currentHealth > maxHealth)
{
currentHealth = maxHealth;
}
}
public void SetSpawnPoint(Vector3 newPosition)
{
respawnPoint = newPosition;
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class Checkpoint : MonoBehaviour
{
public HealthManager theHealthManager;
public Renderer cpRenderer;
public Renderer postRenderer;
public SpriteRenderer pcRenderer;
public Material cpOff;
public Material cpOn;
public Material postOff;
public Material postOn;
public bool checkpoint1On;
public GameObject[] infoPanels;
//Make sure to assign a value to a bool with '=' and in an 'if' statement somewhere in the code to prevent warnings.
//private bool checkpoint1IsActivated;
private bool infoPanel1Activated;
void Start()
{
theHealthManager = FindObjectOfType<HealthManager>();
}
void Update()
//Key presses are better handled in the Update function and will recognise keys being pressed once every frame.
{
if (checkpoint1On == true)
{
if (infoPanel1Activated == false)
{
if (Input.GetKeyDown(KeyCode.Space))
{
infoPanels[0].SetActive(true);
infoPanel1Activated = true;
}
}
else
{
if (infoPanel1Activated == true)
{
if (Input.GetKeyDown(KeyCode.Space))
{
infoPanels[0].SetActive(false);
infoPanel1Activated = false;
}
}
}
}
}
public void Checkpoint1On()
{
cpRenderer.material = cpOn;
postRenderer.material = postOn;
pcRenderer.color = new Color(1f, 1f, 1f, 1f);
checkpoint1On = true;
}
//[] makes a variable an Array (a list). The 'foreach' loop will check through all the Checkpoint objects
//Checkpoint[] checkpoints = FindObjectsOfType<Checkpoint>();
//For each Checkpoint Array called 'checkpoints', look for 'cp' and turn the others in the list off
/*foreach (Checkpoint cp in checkpoints)
{
cp.CheckpointOff();
}
theRenderer.material = cpOn;*/
public void Checkpoint1Off()
{
cpRenderer.material = cpOff;
postRenderer.material = postOff;
pcRenderer.color = new Color(1f, 1f, 1f, 5f);
checkpoint1On = false;
}
public void OnTriggerStay(Collider other)
{
if (other.gameObject.CompareTag("Player"))
{
if (GameManager.currentGold >= 5)
{
if (Input.GetKeyDown(KeyCode.Return))
{
theHealthManager.SetSpawnPoint(transform.position);
Checkpoint1On();
checkpoint1On = true;
}
}
else if (GameManager.currentGold <= 5)
{
checkpoint1On = false;
}
}
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
public class EntranceTrigger : MonoBehaviour
{
public GameObject[] buttonPrompts;
public HealthManager theHealthManager;
public bool entranceVicinity;
//public bool exitVicinity;
//public bool allowInteraction = false;
private int xbox360Controller = 0;
private int ps4Controller = 0;
private bool outsideHut;
private PlayerController thePlayer;
void Start()
{
thePlayer = FindObjectOfType<PlayerController>();
theHealthManager = FindObjectOfType<HealthManager>();
if(SceneManager.GetActiveScene() == SceneManager.GetSceneByName("start_area"))
{
outsideHut = true;
}
/*else if(SceneManager.GetActiveScene() == SceneManager.GetSceneByName("hut_interior"))
{
insideHut = true;
outsideHut = false;
}*/
}
public void OnTriggerEnter(Collider other)
{
if (outsideHut)
{
if (other.gameObject.CompareTag("Player"))
{
entranceVicinity = true;
//exitVicinity = false;
ControllerDetection();
if (entranceVicinity && ps4Controller == 1)
{
PS4Prompts();
}
else if (entranceVicinity && xbox360Controller == 1)
{
Xbox360Prompts();
}
else
{
PCPrompts();
}
}
}
}
public void OnTriggerExit(Collider other)
{
entranceVicinity = false;
//exitVicinity = false;
}
public void Update()
{
if (entranceVicinity)
{
if (xbox360Controller == 1)
{
if (Input.GetKeyDown("joystick button 2"))
{
SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex + 2);
}
}
else if (ps4Controller == 1)
{
if (Input.GetKeyDown("joystick button 0"))
{
SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex + 2);
}
}
else
{
if (Input.GetKeyDown(KeyCode.Return))
{
SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex + 2);
}
}
}
}
public void Hide()
{
buttonPrompts[0].SetActive(false);
buttonPrompts[1].SetActive(false);
buttonPrompts[2].SetActive(false);
}
public void Xbox360Prompts()
{
buttonPrompts[1].SetActive(true);
Invoke("Hide", 3f);
}
public void PS4Prompts()
{
buttonPrompts[2].SetActive(true);
Invoke("Hide", 3f);
}
public void PCPrompts()
{
buttonPrompts[0].SetActive(true);
Invoke("Hide", 3f);
}
public void ControllerDetection()
{
string[] names = Input.GetJoystickNames();
for (int x = 0; x < names.Length; x++)
{
//print(names[x].Length);
if (names[x].Length == 19)
{
//print("PS4 CONTROLLER IS CONNECTED");
ps4Controller = 1;
xbox360Controller = 0;
if (ps4Controller == 1)
{
Debug.Log("PS4 controller detected");
}
}
else if (names[x].Length == 33)
{
//print("XBOX 360 CONTROLLER IS CONNECTED");
ps4Controller = 0;
xbox360Controller = 1;
if (xbox360Controller == 1)
{
Debug.Log("Xbox 360 controller detected");
}
}
else
{
ps4Controller = 0;
xbox360Controller = 0;
}
if(xbox360Controller == 0 && ps4Controller == 0)
{
Debug.Log("No controllers detected");
}
/*if (!string.IsNullOrEmpty(names[x]))
{
xbox360Controller = 1;
ps4Controller = 1;
}
else if(string.IsNullOrEmpty(names[x]))
{
xbox360Controller = 0;
ps4Controller = 0;
Debug.Log("Controllers not detected");
}*/
}
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
public class ExitTrigger : MonoBehaviour
{
public GameObject[] buttonPrompts;
public bool exitVicinity;
public GameObject thePlayer;
private int xbox360Controller = 0;
private int ps4Controller = 0;
private bool insideHut;
private HealthManager theHealthManager;
void Start()
{
theHealthManager = FindObjectOfType<HealthManager>();
if (SceneManager.GetActiveScene() == SceneManager.GetSceneByName("hut_interior"))
{
insideHut = true;
exitVicinity = true;
}
}
public void OnTriggerEnter(Collider other)
{
if (insideHut)
{
if (other.gameObject.CompareTag("Player"))
{
exitVicinity = true;
ControllerDetection();
if (exitVicinity && ps4Controller == 1)
{
PS4Prompts();
}
else if (exitVicinity && xbox360Controller == 1)
{
Xbox360Prompts();
}
else
{
PCPrompts();
}
}
}
}
public void OnTriggerExit(Collider other)
{
exitVicinity = false;
}
public void Update()
{
if (exitVicinity)
{
if (xbox360Controller == 1)
{
if (Input.GetKeyDown("joystick button 2"))
{
SceneManager.LoadScene("start_area");
}
}
else if (ps4Controller == 1)
{
if (Input.GetKeyDown("joystick button 0"))
{
SceneManager.LoadScene("start_area");
}
}
else
{
if (Input.GetKeyDown(KeyCode.Return))
{
SceneManager.LoadScene("start_area");
}
}
}
}
public void Hide()
{
buttonPrompts[0].SetActive(false);
buttonPrompts[1].SetActive(false);
buttonPrompts[2].SetActive(false);
}
public void Xbox360Prompts()
{
buttonPrompts[1].SetActive(true);
Invoke("Hide", 3f);
}
public void PS4Prompts()
{
buttonPrompts[2].SetActive(true);
Invoke("Hide", 3f);
}
public void PCPrompts()
{
buttonPrompts[0].SetActive(true);
Invoke("Hide", 3f);
}
public void ControllerDetection()
{
string[] names = Input.GetJoystickNames();
for (int x = 0; x < names.Length; x++)
{
//print(names[x].Length);
if (names[x].Length == 19)
{
//print("PS4 CONTROLLER IS CONNECTED");
ps4Controller = 1;
xbox360Controller = 0;
if (ps4Controller == 1)
{
Debug.Log("PS4 controller detected");
}
}
else if (names[x].Length == 33)
{
//print("XBOX 360 CONTROLLER IS CONNECTED");
ps4Controller = 0;
xbox360Controller = 1;
if (xbox360Controller == 1)
{
Debug.Log("Xbox 360 controller detected");
}
}
else
{
ps4Controller = 0;
xbox360Controller = 0;
}
if (xbox360Controller == 0 && ps4Controller == 0)
{
Debug.Log("No controllers detected");
}
/*if (!string.IsNullOrEmpty(names[x]))
{
xbox360Controller = 1;
ps4Controller = 1;
}
else if(string.IsNullOrEmpty(names[x]))
{
xbox360Controller = 0;
ps4Controller = 0;
Debug.Log("Controllers not detected");
}*/
}
}
}
The idea was to get the position where the player interacts with the entrance trigger that loads up the next scene. Once leaving the building/scene, I want the player to be in the same spot as when they entered.
