- Home /
The question is answered, right answer was accepted
Calling a command in specific scenes
Hi everyone,
I need help with running a command in selected scenes in unity. To elaborate, say I have 10 scenes and I want to run a function that'll persist for as long as I'm in that selected scene, for instance, making a Count-up in 4 scenes only when I'm in any of those scenes and when I'm not, the count-up is disabled
Regards.
Answer by MichaI · Sep 27, 2019 at 09:00 PM
If by function you mean MonoBehaviour class, than you can for example make such class, call DontDestroyOnLoad function in Awake method and than check if current scene is the scene in which you want to execute your function (the Update function as I understand). You can do it like this:
using UnityEngine; using UnityEngine.SceneManagement;
public class ExecuteInSpecificScenes : MonoBehaviour
{
// Scenes in which you want to execute your code
public bool[] scenesMask = new bool[SceneManager.sceneCountInBuildSettings];
private bool enableScript = false;
void Awake()
{
DontDestroyOnLoad(gameObject);
}
void OnSceneLoaded(Scene scene, LoadSceneMode mode)
{
enableScript = scenesMask[scene.buildIndex];
}
void Update()
{
if (!enableScript) return;
// Your code here
}
}
But I don't quite understand why you want to do that, and I am pretty sure there is simpler way to do whatever it is that you want to achieve.
Thanks $$anonymous$$ichal, what I needed to do is far from singleton. I wanted to loop through all scenes and call a local method in only specified ones. I was hoping to use arrays or any loop statement ins$$anonymous$$d of manually checking by typing the giving scene index I want to run the method on
Thanks though for your reply, I appreciate it
If you want to iterate through scenes your method that iterates through them cannot be destroyed, so DontDestroyOnLoad is necessary. To iterate through scenes you don't need to type their index manually, I thought that you would want to manually specify on list of bools (true false) on which of them you want to run your function, but if you want to check it by some method it is even easier to do.
You can do it like this:
public class ExecuteInSpecificScenes : $$anonymous$$onoBehaviour
{
void Awake()
{
DontDestroyOnLoad(gameObject);
}
void IterateThroughScenes()
{
for(int i = 0; i < Scene$$anonymous$$anager.sceneCountInBuildSettings; ++i)
{
Scene$$anonymous$$anager.LoadScene(i, LoadScene$$anonymous$$ode.Single);
if(CheckIfYouWantToExecuteTheFunctionInThisScene())
{
FunctionToExecuteInSpecificScenes();
}
}
}
}
If you don't want to close your first opened scenes than you could next scenes open and close additive.
void IterateThroughScenes()
{
Scene firstOpenedScene = Scene$$anonymous$$anager.GetActiveScene();
for(int i = 0; i < Scene$$anonymous$$anager.sceneCountInBuildSettings; ++i)
{
if(i != firstOpenedScene.buildIndex)
{
Scene$$anonymous$$anager.LoadScene(i, LoadScene$$anonymous$$ode.Additive);
Scene$$anonymous$$anager.SetActiveScene(GetSceneByBuildIndex(i));
}
if(CheckIfYouWantToExecuteTheFunctionInThisScene())
{
FunctionToExecuteInSpecificScenes();
}
if(i != firstOpenedScene.buildIndex)
{
Scene$$anonymous$$anager.SetActiveScene(firstOpenedScene);
Scene$$anonymous$$anager.UnloadSceneAsync(i);
}
}
}
Could you describe what exactly you want to do by calling your method in specific scenes? $$anonymous$$aybe there is some simpler solution :)
Sure, I have 3 different timer that need to run in 3 different game modes and for 1 game mode, there're several scenes
First game mode has currently, 6 scenes and the 3rd has 10 scenes. I'm using 3 timers for several reasons but mainly because a player can switch between game modes and ultimately, pausing the timer of previous mode
I want these timers to record how long a player's in a specific mode. So, I need to let it know when and what scenes a specific timer should run on
for example:
void Update() { if (Scene$$anonymous$$anager.GetActiveScene().buildIndex == 0 ||Scene$$anonymous$$anager.GetActiveScene().name == "Ending Scene") return;
else if (GameType.mode == GameType.$$anonymous$$ode.Story)
{
totalStoryTime += Time.deltaTime;
}
else if (GameType.mode == GameType.$$anonymous$$ode.Challenges)
{
totalChallangeTime += Time.deltaTime;
}
}
GameType is a enum sitting in a static class in my Game manager script
As you can see here, I'm using update meaning even when I'm in any scene, it'll keep on checking the 3 if...statements for as long as the app is active
So you can simply create a script in each of your scene which loads on start supported by the scene timer, updates it while playing in the scene if current game mode is supported by the scene and saves new timer value when scene is changed, like this
:
public class Timer : $$anonymous$$onoBehaviour
{
public GameType.$$anonymous$$ode supported$$anonymous$$ode;
private float timer;
void Awake()
{
if(GameType.mode == supported$$anonymous$$ode)
{
timer = LoadTimer(supported$$anonymous$$ode);
}
}
void Uppdate()
{
if(GameType.mode == supported$$anonymous$$ode)
{
timer += Time.deltaTime;
}
}
void OnDestroy()
{
if(GameType.mode == supported$$anonymous$$ode)
{
SaveTimer(supported$$anonymous$$ode, timer);
}
}
}
To save and load your timers you can use for example PlayerPrefs.
:
float LoadTimer(GameType.$$anonymous$$ode mode)
{
return PlayerPrefs.GetFloat("timer" + mode.ToString(), 0f);
}
void SaveTimer(GameType.$$anonymous$$ode mode, float timer)
{
PlayerPrefs.SetFloat("timer" + mode.ToString(), timer);
PlayerPrefs.Save();
}
Oh God, you're so right. It's most efficiently done when after creating a script, then add it to the scenes that require its function to run. I was so engrossed with having the Game $$anonymous$$anager in sending the data rather than telling those specific scenes to send those data to the $$anonymous$$anager
Thanks once again
Follow this Question
Related Questions
Sneak in UIView 1 Answer
can i connect some few scenes? 2 Answers
Load Level Script has stopped working 1 Answer
One GameObject, two scenes 2 Answers
Question on Unity Project: Stealth - Chapter 1 - Video 2 at the beginning 2 Answers