0
votes

I am doing a Unity project. I have two scenes in my project.

In the first scene. I set three buttons texted "1 min", "2 mins" and "3 mins". And I want to have the corresponding game duration in my second scene (game scene). I have countdown function in my script.

now I am using singleton pattern following the steps of this tutorial. https://www.youtube.com/watch?v=CPKAgyp8cno

Problem is when I run the game, three texts of time start simultaneously. And my buttons in Scene one could control load scenes but not choose time.

The following are the codes. In the PersistentManager Script which attached to the PersistentManager game object:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class PersistentManagerScript : MonoBehaviour
{public static PersistentManagerScript Instance { get; private set; }

public int Value;
// Start is called before the first frame update

private void Awake()
{
    if (Instance == null)
    {
        Instance = this;
        DontDestroyOnLoad(gameObject);
    }
    else
    {
        Destroy(gameObject);
    }
}

}

In the SceneManager Script:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class SceneManagerScript : MonoBehaviour
{
 public GameObject CountDownIn1;
public GameObject CountDownIn2;
public GameObject CountDownIn3;
public Text ValueText;
public Text ValueText1;
public Text ValueText2;
private void Start()
{
    switch (this.gameObject.name)
    {
        case "Button1min":
            SetGameTimeEqualOne();
            break;
        case "Button2mins":
            SetGameTimeEqualTwo();
            break;
        case "Button3mins":
            SetGameTimeEqualThree();
            break;
    }
}  


public void SetGameTimeEqualOne()
{
    CountDownIn1.SetActive(true);
    ValueText.text = PersistentManagerScript.Instance.Value.ToString();
    Debug.Log("COUNTDOWN1 active");
    //DontDestroyOnLoad(this.CountDownIn1);
}
public void SetGameTimeEqualTwo()
{
    CountDownIn2.SetActive(true);
    Debug.Log("COUNTDOWN2 active");
    ValueText1.text = PersistentManagerScript.Instance.Value.ToString();
    DontDestroyOnLoad(this.gameObject);
}
public void SetGameTimeEqualThree()
{
    CountDownIn3.SetActive(true);
    Debug.Log("COUNTDOWN3 active");
    ValueText2.text = PersistentManagerScript.Instance.Value.ToString();
    DontDestroyOnLoad(this.gameObject);
}

Any suggestions will be appreciated.

1
Which part is giving you trouble? Passing the countdown duration to the second scene? The countdown timer logic? - Erik Hermansen
In addition to what Erik mentioned, could you show what you have done so far? - Kaynn
I have three countdown gameObject is my scene 1 and also in the scene 2. I want to use 'SetActive', when I click button 1, the countdown in 1 min will active. In the same way, when I click button 2, the countdown in 2 mins will active. Do you think it is a right way to implement? Problem is I am not really know how to set a gameObject active from another scene. - Nora jin

1 Answers

1
votes

There are multiple ways to pass data between scenes. The most common recommendation is to use a Singleton pattern that is consumed by other scripts in each scene. However, this can be overly complicated.

Interestingly enough, Unity's newer ScriptableObjects can be used for a similar strategy. Since ScriptableObjects are persisted at a higher scope than scenes, you can use them to hold data between scenes without having to utilize statics and singletons. Unity even markets them as more than just data containers! I prefer to pass data between objects and scenes by creating a common scriptable object, and referencing that asset in each script that needs to share data (regardless of scene).

Here's an example using your requirement:

GameData.cs

[CreateAssetMenu(fileName = "GameData", menuName = "Game Data")]
public class GameData: ScriptableObject
{
    float gameDuration; //This is where you will store and read your selected game duration
}

GameSelection.cs This script exists on Scene 1

public class GameSelection : Monobehaviour
{
    public GameData gameData; 

    public void SetDuration(float time) //Call this method from each button with a different parameter
    {
        gameData.gameDuration = time;
    }
}

Countdown.cs This script exists in Scene 2

public class Countdown: Monobehaviour
{
    public GameData gameData; 
    float countdownTimer;

    public void Start()
    {
        countdownTimer = gameData.gameDuration;
    }

    //... rest of your countdown script
}

Now you can create a GameData asset in your project folder and drag it into the inspector in Scene1, and the inspector in Scene2. If Scene1 changes the value of the timer, Scene2 will know about it. Additionally, you can set a default value for gameDuration on the GameData asset and run/test Scene2 without having to run Scene1 first!