How to reference object in another scene?

Im making a parkour game and im trying to get a stopwatch to time the player.

i have a canvas with the crosshair of the player and the stopwatch there and when switching between scenes, i use a singleton pattern to only have one canvas.

this is the code that i am using to go to the next level

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.SceneManagement;
using TMPro;

public class NxtLvl : MonoBehaviour
{
    public GameObject carrotGFX;

    public GameObject panel;

    public bool gameOver;

    public Timer timer;

    public TMP_Text timeText;

    [SerializeField]
    private Canvas canvas;
   
    public GameObject crosshairTimerCanvas;


    Vector3 timerStartPos;
    void Awake()
    {
    timerStartPos = timer.transform.position;

    canvas.gameObject.SetActive(false);
    }

    void OnTriggerEnter(Collider other)
    {

    gameOver = true;
    canvas.gameObject.SetActive(true);
    carrotGFX.SetActive(false);

    timer.transform.SetParent(panel.transform);
   
    timer.transform.position = new Vector3(771, 400, 0);

    timer.StopCoroutine("StopWatch");
    Debug.Log("Stopwatch paused");

    Cursor.lockState = CursorLockMode.None;
        Cursor.visible = true;
    }

    public void NextLevel(string scene)
    {
    Debug.Log("Next Level");
    SceneManager.LoadScene(scene);
    gameOver = false;
    canvas.gameObject.SetActive(false);

    timer = GameObject.FindGameObjectWithTag("CrosshairTimer");

    timer.transform.SetParent(crosshairTimerCanvas.transform);

    timeText.gameObject.SetActive(true);
    timer.transform.position = timerStartPos;

    Debug.Log("Waiting");


    Debug.Log("Wait time complete, resuming stopwatch");
    timer.StartCoroutine("StopWatch");

    Debug.Log("Stopwatch resumed");

    }
}

this is the line i am having trouble with

timer = GameObject.FindGameObjectWithTag(“CrosshairTimer”);

it keeps on saying
Cannot implicitly convert type ‘UnityEngine.GameObject’ to ‘Timer’

how do i fix this??

FindGameObjectWithTag returns a gameobject, not a Timer. If you want the Timer component, you need to use GetComponent().

Next, you don’t reference things from other scenes if you’re just switching scenes. If something is a Singleton, it’s usually floating around and you need to access it through the Singleton script. Like. Singleton.Instance.Whatever, which is sort of the point of a singleton.

sry im not that good with unity, so wha exactly do i need to do, am i supposed to make like a gameobject variable called _timer and do GetComponent?

cuz the thing is, the nxtlvl script sits on the carrot(pretty much a gamemanager and the objective in the game)

timer = GameObject.FindGameObjectWithTag(“CrosshairTimer”).GetComponent();
will get the Timer script attached to the CrosshairTimer-tagged GameObject.

1 Like

now it says
NullReferenceException: Object reference not set to an instance of an object
NxtLvl.NextLevel (System.String scene) (at Assets/Scripts/NxtLvl.cs:64)

@seejayjames @Brathnann help me pls

ok so what happens now is that the timer gets put under tha panel in scene 1 so when i go to scene 2, the timer is still in panel in scene 1 so how do i get timer to move from scene 1 to scene 2 crosshair timer canvas

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.SceneManagement;
using TMPro;

public class NxtLvl : MonoBehaviour
{
    public GameObject carrotGFX;

    public GameObject panel;

    public bool gameOver;

    public Timer timer;

    public TMP_Text timeText;

    [SerializeField]
    private Canvas canvas;
   
    public GameObject crosshairTimerCanvas;


    Vector3 timerStartPos;
    void Awake()
    {
    timerStartPos = timer.transform.position;

    canvas.gameObject.SetActive(false);
    }

    void OnTriggerEnter(Collider other)
    {

    gameOver = true;
    canvas.gameObject.SetActive(true);
    carrotGFX.SetActive(false);
   
    timer.transform.position = new Vector3(771, 400, 0);

    timer.StopCoroutine("StopWatch");
    Debug.Log("Stopwatch paused");

    Cursor.lockState = CursorLockMode.None;
        Cursor.visible = true;
    }

    public void NextLevel(string scene)
    {
    Debug.Log("Next Level");

    //Switches to next scene
    SceneManager.LoadScene(scene);
    gameOver = false;
    canvas.gameObject.SetActive(false);

    timer = GameObject.FindGameObjectWithTag("CrosshairTimer").GetComponent<Timer>();

    timeText.gameObject.SetActive(true);
    timer.transform.position = timerStartPos;


    Debug.Log("Waiting");


    Debug.Log("Wait time complete, resuming stopwatch");
    timer.StartCoroutine("StopWatch");

    Debug.Log("Stopwatch resumed");

    }
}

changed code a bit, it still says line 63 nullreferenceexception object reference not set to instance of object

timer.transform.position = timerStartPos;

WHAT DOES THIS MEAN HOW DO I FIX

That most likely means the GetComponent call on line 59 is returning null. GetComponent is designed to return null when the GameObject doesn’t have an active component of that type attached. The line with the error is the first time you’re trying to use the reference returned by the GetComponent call, which would be why you see the null reference error on that line.

edit: Also, I see in the earlier code you are calling LoadScene. If the timer is supposed to be in the new scene, and not the old scene, note that this won’t work. LoadScene doesn’t complete immediately. It schedules the scene to be loaded after the current frame update completes. So all code for this frame will execute still in the old scene, even after LoadScene is called. (If you were already aware of that, then ignore this comment)

i fixed it so it works but when i finish level 2, the timer doesnt stop. i think this is because i use the same timer in all my scenes and it has dontdestroyonload on it.

in the gamemanager/carrot of level 2, i cant reference the timer through code bc its in the dontdestroyonload scene

how do i fix this???

FindGameObjectWithTag will find the GameObject across all active scenes, including the DontDestroyOnLoad scene. So you must be running into some other problem if you’re unable to reference it.

i edited the code so ik that i dont have a timer so heres what i got

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.SceneManagement;
using TMPro;
public class NxtLvl : MonoBehaviour
{
    public GameObject carrotGFX;

    public bool gameOver;
    public Timer timer;
    public TMP_Text timeText;
    [SerializeField]
    private Canvas canvas;
  
    public GameObject crosshairTimerCanvas;
    Vector3 timerStartPos;
    void Awake()
    {
    timerStartPos = timer.transform.position;
    canvas.gameObject.SetActive(false);
    }
    void OnTriggerEnter(Collider other)
    {
     //Initiate game over and turn on game over canvas
    gameOver = true;
    canvas.gameObject.SetActive(true);
    carrotGFX.SetActive(false);
  
   

    if(timer != null) //Check if we have a timer or not
    {
        //if we do have timer, set position to center of the screen
        timer.transform.position = new Vector3(771, 400, 0);
    }
    else
    {
        Debug.Log("No timer");
        return; //If no timer, don’t do anything
    }
    //Stop timer
    timer.StopCoroutine("StopWatch");
    Debug.Log("Stopwatch paused");
    //Show mouse
    Cursor.lockState = CursorLockMode.None;
        Cursor.visible = true;
    }
    public void NextLevel(string scene)
    {

    //Load the next level
    Debug.Log("Next Level");
    SceneManager.LoadScene(scene);
    gameOver = false;

    //Disable gameover canvas
    canvas.gameObject.SetActive(false);
    //Enable timer text and resume timer
    timeText.gameObject.SetActive(true);
    timer.StartCoroutine("StopWatch");


    //Set timer text to original position
    timeText.transform.position = timerStartPos;
    }
}

now i know that i have no timer but when i try to add the getcomponent stuff, it still doesnt work

can i just send u the unity package and u try to edit it to work?

heres the project so far if u wanna see it

6754876–779338–CarrotThief_V0.1.unitypackage (2.43 MB)

When you’ve got the GetComponent stuff in, you should be looking at the scene hierarchy when it fails. Verify there really is a GameObject active in the hierarchy with that specific tag, written exactly. Since you’re using FindGameObjectWithTag, it will only return 1 object with that tag. So you need to also verify there is only exactly 1 GameObject in the entire hierarchy with that tag. If you have another GameObject with that tag assigned, and it doesn’t have the Timer component, well that is probably the problem.

After you have verified all that, then verify that 1 GameObject actually has an active Timer component. If you’ve verified all of that, then the GetComponent call will not return null. So something in that list of things I just mentioned is the problem.

As for troubleshooting, you can use FindGameObjectsWithTag and check the length of the returned array. If the length of the returned array is anything other than 1, then there is your problem. If the GameObject is in the scene but inactive, then it won’t be found. If the script is attached but inactive then GetComponent won’t find it.

If you’re still having trouble using tags with GetComponent, you can drop this and go an entirely other route. Instead create a static reference to the Timer script, and just use that everywhere you need it.

Example of that last thing:
Inside your Timer class add the following

public static Timer Instance = null;

void Awake()
{
    if (Instance == null)
    {
        Instance = this;
    }
    else
    {
        Debug.Log("OOPS!  There is already a Timer!  Destroying this new one");
        Destroy(gameObject);
    }
}

Everywhere else you access the Timer via Timer.Instance now instead of your Timer reference you’ve been trying to use. No more FindGameObjectWithTag or GetComponent.

No thanks

the canvas that the timer sits on is marked as crosshaircanvas but it has no timer component, the actual timer text has the component but no tag, do u think this is the problem?

Yeah. When you FindGameObjectWithTag, you get exactly the GameObject with that specific tag. If the Timer component is on a different GameObject, then you’re getting getting the wrong GameObject, which would explain why GetComponent doesn’t find an instance of Timer.

OMG YES IT WORKED TYSM UR THE BEST <3333<3<3<3<3 ILY TYTYTYTYYTYYTYTYYTYTYTYTYTYTYYTYTYTYTYYTYTYTYTYTTYTYY