0
\$\begingroup\$
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;

public class HouseExit : MonoBehaviour
{
    public Transform player;


    public void Houseexit()
    {
        SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex - 1);
    }

    void OnCollisionEnter2D(Collision2D col)
    {
        if (col.gameObject.CompareTag("Player"))
        {   
            Houseexit();
            GameObject.Find("Wizard").transform.position = GameObject.Find("SpawnPos").transform.position;
        }
    }
}

This code belongs to the scene "Goblin House 1" and I'm trying to find the wizard and the spawn position both from level 1.

\$\endgroup\$
0
1
\$\begingroup\$

LoadScene() does not instantly load the new scene before the function returns.

It can't, not least because part of the work of loading the new scene, when you're not using additive scene loading (which you aren't, in this case), is deleting everything from the previous scene.

But your HouseExit script is still running its collision handler, so we can't delete it yet.

So when you call LoadScene() like this, what you're really doing is requesting the new scene to be loaded at the end of this frame, after the current scene has been unloaded.

Doing it that way, the HouseExit script is long gone before the wizard or spawn point exist. So trying to manipulate objects in the future from an object in the past just does not make sense.

Instead, you can think about saving a note for the newly loaded scripts to read when they load. Let's say we do something like this...

public class SpawnPointPicker : MonoBehaviour {

    static string _nextSpawnPointName;

    public static void SetSpawnPoint{string name} {
        _nextSpawnPointName = name;
    }

    void Start() {
        if (string.IsNullOrWhiteSpace(_nextSpawnPointName)) {
            Debug.Log("No spawn point set. Staying in default position.");
            return;
        }

        var spawnPoint = GameObject.Find(_nextSpawnPointName);

        if (spawnPoint == null) {
            Debug.LogWarning($"No spawn point found with name {_nextSpawnPointName}.");
            return;
        }

        transform.position = spawnPoint.transform.position!
    }
}

Your HouseExit script can now call SpawnPointPicker.SetSpawnPoint() to set the name of the point where the wizard should spawn the next time it loads.

Put an instance of this SpawnPointPicker component on your wizard. When it loads, it will look up this saved spawn point name and try to move itself to a corresponding object.

This way, we can use the static variable to retain information between scenes and send the information about where to spawn into the future where it will be needed, rather than trying to time travel from an object that was destroyed in the past.

\$\endgroup\$
2
  • \$\begingroup\$ Thank you so much! \$\endgroup\$ – sun Mar 27 at 5:48
  • \$\begingroup\$ If this worked for you, click the checkmark on the left of the answer to mark it as "Accepted" \$\endgroup\$ – DMGregory Mar 27 at 12:40

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.