What's the best way to handle respawning in the 'second' level?

I was experimenting down in the crypts (Level 2) earlier when I noticed an issue. If the player dies down there, they can’t respawn. The player’s respawn point is set to Level 1.

Now, I would just set a local override respawn point for the player when he’s down in the crypts, however my scene has two entrances/exits. What would be the best way to handle respawning at the closest ‘spawn’ to where the player died? It’d be jarring to have entered via the cave, and respawn over the other side at the crypt stairs!

I also wanted to ask, did you have any luck figuring out the lingering ‘selling one item type’ issue from this thread? Can’t Buy/Sell More Than One Item Per Buy/Sell Click - Unity Courses / Ask - GameDev.tv
I was going to post there, but it’s now closed.

Thanks in advance!

The respawn point needs to be individually set in each level. If you ahve two portals into a level, you may wish to consider adding something to the portal script with a “Respawn Point” (or just use the spawn point), and set the respawn point when the player portals in.

I might have gotten distracted on the one item/click part. I’ll take a look again when i get home

Thanks!

I like the idea of using the portal.cs to assign a respawn point, but I’m not sure on how to execute it. I’ve had a go with the changes below, but no dice. I get an NRE ‘object not set’ error on this line:

respawner.respawnLocation = spawnPoint.transform;

Basically, I know that I want to get the portal I came in from, and pass the player’s Portal.cs spawnPoint to the Respawner.cs to update the respawnLocation. I feel like it’s close, but not there yet. Any tips? Thanks!

Full Script Below:

using System.Collections;
using UnityEngine;
using UnityEngine.AI;
using UnityEngine.SceneManagement;
using RPG.Control;
using RPG.Attributes;

namespace RPG.SceneManagement
{
    public class Portal : MonoBehaviour
    {
        enum DestinationIdenifier
        {
            A, B
        }
        
        [SerializeField] int sceneToLoad = -1;
        [SerializeField] Transform spawnPoint;
        [SerializeField] DestinationIdenifier destination;

        [SerializeField] float fadeOutTime = 1f;
        [SerializeField] float fadeInTime = 2f;
        [SerializeField] float fadeWaitTime = 0.5f;

        private void OnTriggerEnter(Collider other)
        {
            if (other.tag == "Player")
            {
                StartCoroutine(Transition());
            }
        }

        private IEnumerator Transition()
        {
            if (sceneToLoad < 0)
            {
                Debug.LogError("Scene to load is not set.");
                yield break;
            }

            DontDestroyOnLoad(gameObject);

            Fader fader = FindObjectOfType<Fader>();
            SavingWrapper wrapper = FindObjectOfType<SavingWrapper>();
            PlayerController playerController = GameObject.FindWithTag("Player").GetComponent<PlayerController>();
            playerController.enabled = false;

            yield return fader.FadeOut(fadeOutTime);

            wrapper.Save();

            yield return SceneManager.LoadSceneAsync(sceneToLoad);
            PlayerController newPlayerController = GameObject.FindWithTag("Player").GetComponent<PlayerController>();
            newPlayerController.enabled = false;

            wrapper.Load();

            Portal otherPortal = GetOtherPortal();
            UpdatePlayer(otherPortal);

            wrapper.Save();

            yield return new WaitForSeconds(fadeWaitTime);
            fader.FadeIn(fadeInTime);

            newPlayerController.enabled = true;
            Destroy(gameObject);
        }

        private Portal GetOtherPortal()
        {
            foreach (Portal portal in FindObjectsOfType<Portal>())
            {
                if (portal == this) { continue; }
                if (portal.destination != destination) { continue; }

                return portal;
            }
            return null;
        }

        private void UpdatePlayer(Portal otherPortal)
        {
            GameObject player = GameObject.FindWithTag("Player");
            player.GetComponent<NavMeshAgent>().Warp(otherPortal.spawnPoint.position);
            player.transform.rotation = otherPortal.spawnPoint.rotation;
        }

        void Update()
        {
            if (GameObject.FindWithTag("Player").GetComponent<Health>().IsDead())
            {
                Respawner respawner = this.GetComponent<Respawner>();
                spawnPoint = GetOtherPortal().spawnPoint.transform;
                respawner.respawnLocation = spawnPoint.transform;
                respawner.Respawn();
            }
        }
    }
}

A few problems with this… One, we don’t want this to be in Update at all. Everything we need is in UpdatePlayer. In Update, you’re trying to find a Respawner on the Portal, but the respawner belongs on the player… The place we want to set the respawnLocation is when we update the player in UpdatePlayer

Respawner respawner = player.GetComponent<Respawner>();
respawner.respawnLocation = otherPortal.spawnPoint;

Ah, I completely blew past UpdatePlayer(). :joy:

That did the trick! My only other question is how would I set the player’s rotation? When going through the portal, I use this to set their correct rotation.

player.transform.rotation = otherPortal.spawnPoint.rotation;

but it doesn’t appear to work when respawning.

Thanks again!

That would be in the Respawner code… you already have a handy reference to the spawner transform, you just have to set the player’s rotation when you respawn to the rotation of the spawner.

1 Like

Done and done. It works perfectly! :smiley:

Thanks again!

1 Like

This topic was automatically closed 24 hours after the last reply. New replies are no longer allowed.

Privacy & Terms