Rapid Portal Use Error

For the most part, the portals work as intended in my game. Portal A in scene 0 leads to Portal A in scene 1, Portal B in scene 0 leads to Portal B in scene 1, and vice versa. Exactly how it is shown in the lecture.

I am however finding that if I am re-entering a portal quicker then perhaps expected, the portal isn’t able to keep up with the reloading of the intended scene to spawn. This can lead to problems as it allows players to essentially trigger the portal too quickly before it’s able to be operational. This can lead to things like the player being able to navigate around closed off areas behind where the portal is situated.

Link to video of problem on Youtube
(The Green cubes are the portals colliders. I’ve left them visible to demonstrate the problem)

Whilst this in itself may not be game breaking (it might be in some occurrences, depending on how a scene is set up), I am finding that on some rare edge cases, this rapid portal re-entering is causing a clash to occur between the two portals involved from both scenes. When this occurs, it does break the game, as it leaves the fader in a state of limbo simultaneously incrementing and decrementing from the two scenes portals, which doesn’t allow for the Fader objects alpha channel to ever reach the value of 1, which is its cue to destroy the first portal gameobject in the Portal.cs Transition IEnumerator which calls Fader.cs.

Portal.cs
using UnityEngine;
using System.Collections;
using UnityEngine.AI;
using UnityEngine.SceneManagement;

namespace RPG.SceneManagement
{
    public class Portal : MonoBehaviour
    {
        enum DestinationIdentifier
        {
            A, B, C, D, E
        }

        [Tooltip("Reference buildscene for this portal to load. Default is -1 (null error)")]
        [SerializeField] int sceneToLoad = -1;
        [SerializeField] Transform spawnPoint;

        [Tooltip("Make sure that this & corresponding spawnpoint have same Destination")]
        [SerializeField] DestinationIdentifier destination;
        [SerializeField] float fadeOutTime = .5f;
        [SerializeField] float fadeInTime = .5f;
        [SerializeField] float fadeWaitTime = .5f;

        void OnTriggerEnter(Collider other)
        {
            if (other.tag == "Player")
            {
                StartCoroutine(Transition());
                Debug.Log("Loaded scene " + sceneToLoad);
            }
        }

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

            DontDestroyOnLoad(gameObject);

            Fader fader = FindObjectOfType<Fader>();

            yield return fader.FadeOut(fadeOutTime);
            yield return SceneManager.LoadSceneAsync(sceneToLoad);

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

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

            Destroy(gameObject);
        }

        void UpdatePlayer(Portal otherPortal)
        {
            GameObject player = GameObject.FindWithTag("Player");
            player.GetComponent<NavMeshAgent>().Warp(otherPortal.spawnPoint.position);
            Debug.Log("SpawnPoint position " + otherPortal.spawnPoint.position);

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

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

                return portal;
            }

            return null;
        }
    }
}
Fader.cs
using System.Collections;
using UnityEngine;

namespace RPG.SceneManagement
{
    public class Fader : MonoBehaviour
    {
        CanvasGroup canvasGroup;

        void Start()
        {
            canvasGroup = GetComponent<CanvasGroup>();

        }

        public IEnumerator FadeOut(float time)
        {
            while (canvasGroup.alpha < 1)
            {
                canvasGroup.alpha += Time.deltaTime / time;
                yield return null;
            }
        }

        public IEnumerator FadeIn(float time)
        {
            while (canvasGroup.alpha > 0)
            {
                canvasGroup.alpha -= Time.deltaTime / time;
                yield return null;
            }
        }
    }
}

I guess you could just say ‘don’t use the portal that fast, and it will have enough time to always work’, but I wouldn’t be able to control how someone testing or playing my game would react. It’s not uncommon for someone to accidentally realise that they clicked and entered the wrong room in a game and already be clicking to exit the room straight away even before that new scene is loaded.

Any tips on how I could counteract this problem without just artificially placing the spawn point even further away from the portal? Whilst this may ‘technically’ solve the problem, it would leave a jarring experience for the player everytime they were to enter a door and find that they reappear so far away from the door’s entrance/exit each time.

That’s an annoying one, isn’t it?
We actually fix this exact issue in the lesson “Fixing The Fader”

2 Likes

Ahh, thanks for replying, and that’s good to know. I haven’t reached that section of the course yet. :slightly_smiling_face:

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

Privacy & Terms