Player doesnt move to spawnpoint

When my player hits the portal i can see through a print statement that it is able to find the correct destination portal in the other scene but my player only spawns in the default position in the scene. Github link to my project: https://github.com/dan-jt/rpg-project
(Portal changes are in the feature branch not main branch)
Ive also tried the Warp method and no luck.

The first thing I did was take a look at your Portal.cs script… it’s possible that your GitHub repo is not completely updated, because the Portal script is not even looking for the destination portal or the player…

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

namespace RPG.SceneManagement{
    public class Portal : MonoBehaviour{

        [SerializeField] private Collider playerCollider;
        [SerializeField] private int sceneToLoadIndex = 1;


        private void OnTriggerEnter(Collider other) {
            if (other == playerCollider){
                StartCoroutine(Transition());
            }
        }

        private IEnumerator Transition(){
            DontDestroyOnLoad(gameObject);
            yield return SceneManager.LoadSceneAsync(sceneToLoadIndex);
            print("Scene Loaded");
            Destroy(gameObject);
        }
    }
}

During the Transition, the only thing that is happening is the new scene is loaded and a Debug indicating that the scene has been loaded.

For comparison, here is the course version of the Portal at the point that we are relocating the player after transition:

Portal.cs course repo
using System;
using System.Collections;
using UnityEngine;
using UnityEngine.SceneManagement;

namespace RPG.SceneManagement
{
    public class Portal : MonoBehaviour
    {
        [SerializeField] int sceneToLoad = -1;
        [SerializeField] Transform spawnPoint;

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

        private IEnumerator Transition()
        {
            DontDestroyOnLoad(gameObject);
            yield return SceneManager.LoadSceneAsync(sceneToLoad);
            
            Portal otherPortal = GetOtherPortal();
            UpdatePlayer(otherPortal);

            Destroy(gameObject);
        }

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

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

                return portal;
            }

            return null;
        }
    }
}

Ahh sorry i thought i had updated it, sorry about that. Correct Portal script is below:

public class Portal : MonoBehaviour{

        private enum DestinationIdentifier{
            A, B, C, D, E, F, None
        }

        [SerializeField] private Collider playerCollider;
        [SerializeField] private GameObject player;
        [SerializeField] private int sceneToLoadIndex = -1;
        [SerializeField] private Transform spawnPoint;
        [SerializeField] private DestinationIdentifier destination;
        [SerializeField] private DestinationIdentifier source;

        private NavMeshAgent playerNavMesh;


        private void Awake(){
            playerNavMesh = player.GetComponent<NavMeshAgent>();
        }


        private void OnTriggerEnter(Collider other) {
            if (destination == DestinationIdentifier.None) return;
            if (other == playerCollider){
                StartCoroutine(Transition());
            }
        }

        private IEnumerator Transition(){
            if (sceneToLoadIndex < 0){
                Debug.Log("Scene to load not set");
                yield break;
            }
            DontDestroyOnLoad(gameObject);

            yield return SceneManager.LoadSceneAsync(sceneToLoadIndex);

            Portal otherPortal = GetOtherPortal();
            UpdatePlayer(otherPortal);
            Destroy(gameObject);
        }

        private void UpdatePlayer(Portal otherPortal){
            if (player != null && playerNavMesh != null){
                Vector3 targetPos = otherPortal.spawnPoint.position;
                print("target pos: " + targetPos);
                playerNavMesh.Warp(targetPos);
                print("Player position after warp: " + player.transform.position);
                player.transform.rotation = otherPortal.spawnPoint.rotation;
            } else{
                if (player == null)
                {
                    Debug.LogError("Player is null.");
                }

                if (playerNavMesh == null)
                {
                    Debug.LogError("NavMeshAgent is null.");
                }
            }
        }

        private Portal GetOtherPortal(){
            foreach (Portal portal in FindObjectsByType<Portal>(FindObjectsSortMode.None)){
                if (portal == this) continue;
                if (portal.source != destination) continue;

                return portal;
            }
            return null;
        }
    }

The two print statements i have in UpdatePlayer both correctly give the world position of the destination spawnpoint yet the player no move.

Alright i was trying my best to avoid tags/strings to find the player but i caved and went with whats in the course script and it worked!
I’m still not exactly sure why mine didnt work, maybe you could explain that?

Appreciate your help!

The reason we use tags to locate the player after we’ve transitioned is because once the new scene loads, the player in the old scene (which is a serialized reference) no longer exists, which will create a missing reference exception. The old player simply doesn’t exist anymore. I’m assuming with this code, you were getting the LogError “Player is null.” when you transitioned.

As the only object in each scene with the Player tag should be the Player, using GameObject.FindWithTag(“Player”) becomes the most efficient method of locating the player once we’ve transitioned to a new scene.

Ahh I see. Thanks mate

Privacy & Terms