How to make fade transition when I leave a scene - c#

In my game I have LevelManager and LevelManager.cs and it's not a singleton.
I wanna make fade transition between scenes. I made animations for Fade_In and Fade_Out. And for the first it works fine but when I'd like to leave a scene, it (Fade_Out) doesn't work.
Some of LevelManager.cs:
private void Start() {
if (autoLoadNextLevelAfter != 0) {
Invoke("FadeOut", autoLoadNextLevelAfter);
}
}
public void LoadLevel(string name) {
SceneManager.LoadScene(name);
}
public void LoadNextLevel() {
SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex + 1);
}
private void FadeOut() {
animator.SetTrigger("FadeOut");
}
In the Start method I call Invoke of animation and at the end of Fade_Out I call LoadNextLevel method. In this case, Fade_Out works fine.
But If I wanna make transition with LoadLevel (it calls when I push the button) it breaks. I tried to make IEnumerator LoadLevel:
public void NewLoadLevel(string name) {
FadeOut();
StartCoroutine(CoroutLoadLevel(name));
}
private IEnumerator CoroutLoadLevel(string name) {
yield return new WaitForSeconds(1f);
SceneManager.LoadScene(name);
}
The console says: Coroutine couldn't be started because the the game object 'LevelManager' is inactive!. I guess it's because LevelManager is not a singleton.

Make sure the LevelManager is active and enabled. A coroutine needs an active object to run (because if it is not active update logic will not be called).

Related

Unity AudioManager PlayerPrefs Slider

I have the below audiomanager for my project. Whenever I run a game from the "Play" button in Unity - I can change the volume via slider and the settings are being saved and they load when I exit and play again via Unity's "Play" button.
However can you please explain to me why I cannot do this when I go to the PlayGame and then I go back to the main menu via "restart" button in my game? When I do that - the slider is 100% charged and it doesn't save/load new setings.
Any comments / feedback is much appreciated!
public static AudioManager AMInstance;
[SerializeField] Slider volumeSlider;
private void Awake()
{
if (AMInstance != null && AMInstance != this)
{
Destroy(this.gameObject);
return;
}
AMInstance = this;
DontDestroyOnLoad(this);
}
private void Start()
{
if (!PlayerPrefs.HasKey("musicVolume"))
{
PlayerPrefs.SetFloat("musicVolume", 1);
Load();
}
else
{
Load();
}
}
public void ChangeVolume()
{
AudioListener.volume = volumeSlider.value;
Save();
}
public void Save()
{
PlayerPrefs.SetFloat("musicVolume", volumeSlider.value);
}
public void Load()
{
volumeSlider.value = PlayerPrefs.GetFloat("musicVolume");
}
}
You will need to call PlayerPrefs.Save() before you navigate to another scene. It does get called by default OnApplicationQuit, but since you are just setting a the float, you might need to explicitly call the Save function.
Unity's documentation for PlayerPrefs.Save

How to repeatedly execute a method until said otherwise

I have an EventSystem for managing my turn-based game in Unity.
public class EventSystem : MonoBehaviour
{
private static List<Action> _commandsQueue = new List<Action>();
private bool _canExecuteCommand = true;
public void AddToQueue(Action command)
{
_commandsQueue.Add(command);
}
private void StartCommandExecution()
{
_commandsQueue[0]();
_canExecuteCommand = false;
}
public void CommandExecutionComplete()
{
_canExecuteCommand = true;
}
public void PlayFirstCommandFromQueue()
{
if (_commandsQueue.Any() && _canExecuteCommand)
{
StartCommandExecution();
}
else
{
Debug.LogError("No Command In Queue");
}
}
}
How do I put a method in Update() until _canExecuteCommand is true again but only for some methods?
It is quite broad what you are trying to do but in general you would use an endless loop within a Coroutine.
You can create a generic routine which invokes any Action you pass in as parameter once a frame like e.g.
private IEnumerator InvokeEveryFrame(Action action)
{
// This looks strange but is okey in a Coroutine as long as you yield somewhere within
while(true)
{
action?.Invoke();
// This tells Unity to "pause" this routine here
// render the current frame and continue from here in the next frame
yield return null;
}
}
So all that's left is starting the routine using MonoBehaviour.StartCoroutine like e.g.
Coroutine routine = StartCoroutine(SomeParameterlessMethod);
or if you need parameters
Coroutine routine = StartCoroutine(() => SomeMethod(x, y, z));
and then at some point later stop it using MonoBehaviour.StopCoroutine and the stored Coroutine reference like e.g.
StopCoroutine(routine);
how exactly you store that reference is up to you of course up to you.

I want to reset the level in Unity and don't reset the variable too

I want to reset level in Unity and don't reset the coin amount variable and the lose counter variable. I use playerprefs but it doesn't work to me the variable reset too.
public void EndGame()
{
LoseCounter++;
Invoke("Restart", restartDelay);
}
public void Restart()
{
savedata();
SceneManager.LoadScene(SceneManager.GetActiveScene().name);
loaddata();
}
public void savedata()
{
PlayerPrefs.SetInt("coinamount", ct.coinAmount);
PlayerPrefs.SetInt("losecounter", LoseCounter);
PlayerPrefs.Save();
}
public void loaddata()
{
ct.coinAmount = PlayerPrefs.GetInt("coinamount");
LoseCounter = PlayerPrefs.GetInt("losecounter");
}
script cointext
public int coinAmount;
public Text text;
void Start()
{
text = GetComponent<Text>();
}
void Update()
{
text.text = coinAmount.ToString() + " coins";
}
make sure you are calling loaddata() in the Start() method.
once you call the "Load scene" method, the lines of code under it will not be called.
so make sure you are calling loaddata() in the Start method or OnEnable.
hope that helps.
I second what Muhammad Ellawie said about loading data in the Start() method.
but as a general rule, those game data should generally not be a part of the scene, you may want to implement a singleton pattern for example so they wouldn't be part of the scene.
The easiest way is to tell unity to not destroy your game-manager: Call DontDestroyOnLoad(this.gameObject) in the Awake of the monobehaviour to keep it alive after scene reload.
https://docs.unity3d.com/ScriptReference/Object.DontDestroyOnLoad.html

Unity WebGL Gameobject disabled from somewhere

So, I have a update running on a monobehaviour script(Let's call it Script A) that's in the scene. This update fires a event, so other non-monobehaviour scripts can listen to this when they need a update for something. However, at the start of the app it runs the update on Script A for a short time, but after a while it randomly stops calling the update on Script A.
So I started to place some debugs in standard monobehaviour functions like awake, start, disable, enable etc. Turns out the object is disabled from somewhere without me using or calling it anywhere. This problem only occurs on WebGL. In the editor the OnDisable event is never called and the update keeps running fine.
I tried various fixes, like all the debugs logs everywhere, I tried debugging the stacktrace to find out what is calling this OnDisable, saidly this doesn't show in the WebGL console. It just says: StackTrace:
public class UpdateManager : MonoBehaviour
{
private static UpdateManager _instance;
public static UpdateManager Instance
{
get
{
if (_instance == null)
{
_instance = FindObjectOfType<UpdateManager>();
if (_instance == null)
{
GameObject updateManager = new GameObject("UpdateManager");
_instance = updateManager.AddComponent<UpdateManager>();
}
}
return _instance;
}
}
public delegate void OnUpdateEvent();
public event OnUpdateEvent OnUpdate;
private void Awake()
{
Debug.Log("UpdateManager: Awake!");
}
private void Start()
{
Debug.Log("UpdateManager: Start!");
}
private void OnEnable()
{
Debug.Log("UpdateManager: OnEnable!");
}
private void OnDisable()
{
Debug.Log("UpdateManager: OnDisable!, Stacktrace: " + UnityEngine.StackTraceUtility.ExtractStackTrace());
}
private void Update()
{
Debug.Log("UpdateManager: Update!");
OnUpdate?.Invoke();
}
I would like to know what is disabling this object since I have no clue. Good to note here is that it's only disabled once at the beginning, and after I enable it again it runs fine for the remaining time.
The only places I call this script is in a static class somewhere:
private static void initializeRefreshCycle(int expiresIn)
{
if (expiresIn > 0)
{
if (_refreshRoutine != null)
{
CoroutineManager.Instance.Stop(_refreshRoutine);
_refreshRoutine = null;
}
DateTime expirationDateTime = DateTime.Now;
_refreshTime = expirationDateTime.AddSeconds(expiresIn * 0.85f);
Debug.Log(string.Format("<< API TOKEN WILL BE AUTOMATICALLY REFRESHED IN {0} SECONDS >>", expiresIn * 0.85f));
UpdateManager.Instance.OnUpdate += OnUpdateEarly;
}
}
And then the function that actually listens to the call:
public static void OnUpdateEarly()
{
if (!HasAlmostExpired) return;
SSOCommunicator.RefreshToken(_refresh);
UpdateManager.Instance.OnUpdate -= OnUpdateEarly;
}
Looks like the first time it stops somewhere, and once it reached the subscribing again, it runs fine for the remaining time.
I found out it's a garbage collection issue. Since I would always call UpdateManager.Instance to call a function I never had a hard reference to that instance. So it was somehow destroyed at start only on WebGL. I solved it by keeping a hard reference in the awake of a script. So just having a simgple _updatamanager = Updatemanager.Instance solved it.

unity 5 preferbs ui not showing when click on object

i have a a problem to active UI from prefabs when click on object using OnMouseDown code
public class TreeManager : MonoBehaviour {
public GameObject FuncUI;
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
}
void OnMouseDown()
{
if (FuncUI.activeInHierarchy == false)
{
FuncUI.SetActive (true);
}
else
{
FuncUI.SetActive (false);
}
}
public void ExitOn()
{
Application.Quit ();
}
}
this OnMouseDown code is working if both object and gameobject UI is on hierarchy. but it not work if both i use from prefabs.. what i need to change so i can make it work for prefabs? my function UI is from canvas. when i click on the object, the FuncUI will appear on screen. this code i put inside the object that i want to click to appear FuncUI

Categories

Resources