Unity coroutine "WaitForSeconds" is not working - unity3d

I'm trying to create a function that after some time you go back to the menu. I'm using coroutines to do it but it isn't working
I used:
StartCoroutine(BackToMenu(3));
To invoke the following function:
IEnumerator BackToMenu(float time)
{
Debug.Log($"you are going back to the menu in {time} seconds");
yield return new WaitForSeconds(time);
Debug.Log("back to menu");
SceneManager.LoadScene("Glitch Main Menu");
}
The console is only logging the first Log, after the return it just doesn't do anything. It's my first time using coroutines so I don't know what the problem could be.

Related

unity SceneManager.sceneLoaded callBack overlay each other when sceneLoaded is finished every time?

SceneManager.sceneLoaded += jumpCallBack;
I put this in Start() and use
private void jumpCallBack(Scene scene, LoadSceneMode sceneType)
{
Debug.Log("ok");
}
as callback print, also I have a button, click and load this scene again.
The first time sceneLoaded finished , it print "ok" once, and I click button to load scene again, but this time, it print "ok" twice. Also click button and load again it print 3 times. Why ? How to make this call back just run once each time the sceneLoaded is called?
In general if you want to avoid multiple callbacks
First of all I would usually unsubscribe before subscribing. This is valid even though if the callback was never added yet but makes sure it is definitely there only once - for this object
SceneManager.sceneLoaded -= jumpCallBack;
SceneManager.sceneLoaded += jumpCallBack;
And then I think so far you were only lucky that you are only using a static method Debug.Log but nothing else in your callback. I suspect you forgot to unsubscribe when your object is destroyed
private void OnDestroy()
{
SceneManager.sceneLoaded -= jumpCallBack;
}
Beyond that it is hard to say without having more details about your project. If you are using e.g. DontDestroyOnLoad then you will want to also make sure there is only one instance of this object (Singleton Pattern).

Is there any function in Unity 2d , when I die the the game over screen comes only after death animation finishes

Any way to show Game over screen only after the death animation of player is played text
Check in update if animation is playing or not. if animaion.IsPlaying() return false means your animation is finish and then you show your game over screen.
in your player script (or whatever script tells your die animation to play), go below the line where the die animation plays, then write this line of code: StartCoroutine(ExampleCoroutine());. Make sure you replace the 'ExampleCoroutine' part with the name of the IEnumerator method (more on that in the next sentence). Next, go below the function where you typed StartCoroutine(ExampleCoroutine());. and make an IEnumerator method. Inside it type yield return new WaitForSeconds(1f);. and replace the 1 with how long it takes for the die animation to finish. Lastly, below that line, activate your game over screen. Hope this helped a bit!
If you want to attach code functions to animations, you can use animation events to call functions at very specific times during (or at the end of) animations.
If you prefer, you can also use events to transmit animation status from inside your animator controller using state machine behaviours.
You can use a variable playeranimationfinised and use an IEnumerator with WaitUntil like this
using System;
using UnityEngine;
public IEnumerator gameover()
{
//function to check animation finished
Func<bool> animationfinished = () => playeranimationover;
//wait until playeranimationover is true
yield return new WaitUntil(animationfinished);
//show gameoverscreen
}

The function Input.GetMouseButtonDown id true for two frames consecutively in Unity3D. Why

I have a code like the following:
void Update()
{
if(Input.GetMouseButtonDown(1))
{
Debug.Log("foo");
}
}
The problem is that if I click the right mouse button once the "foo" is written twice. How is it possible?
As Frohlich stated in comment, If you attach a script on more than one GameObject you will be getting Update method call per frame for each script in scene. So to check that you should use Debug.Log() method as follow:
Debug.Log("foo",gameObject);
and when you will click on log in console window, it will take you to the gameObject which is generating that log.

Unity3d Parse FindAsync method freezes UI

I'm running a simple Parse FindAsync method as show below (on Unity3d):
Task queryTask = query.FindAsync();
Debug.Log("Start");
Thread.Sleep(5000);
Debug.Log("Middle");
while (!queryTask.IsCompleted) {
Debug.Log("Waiting");
Thread.Sleep(1);
}
Debug.Log("Finished");
I'm running this method on a separate thread and I put a load circle on UI. My load freezes (+- 1 second) somewhere in the middle of the Thread.sleep method. It's look like when findAsync finishes the process it freezes the UI until it complete their job. Is there anything I could do?
Ps: This works perfectly on editor, the problem is on Android devices.
Ps2: I'm running parse 1.4.1
Ps3: I already tried the continueWith method, but the same problem happens.
IEnumerator RunSomeLongLastingTask () {
Task queryTask = query.FindAsync();
Debug.Log("Start");
//Thread.Sleep(5000); //Replace with below call
yield WaitForSeconds(5); //Try this
Debug.Log("Middle");
while (!queryTask.IsCompleted) {
Debug.Log("Waiting");
//Thread.Sleep(1);
yield WaitForSeconds(0.001f);
}
Debug.Log("Finished");
}
To call this function, use:
StartCoroutine(RunSomeLongLastingTask());
Making the thread sleep might not be a good idea, mainly because the number of threads available is different on each device.
Unity as a built-in scheduler that uses coroutines, so it is better to use it.
IEnumerator RunSomeLongLastingTask()
{
Task queryTask = query.FindAsync();
while (!queryTask.IsCompleted)
{
Debug.Log("Waiting"); // consider removing this log because it also impact performance
yield return null; // wait until next frame
}
}
Now, one possible issue is if your task take too much CPU, then the UI will still not be responsive. If possible, try to give a lower priority to this task.

Yield return in AssetBundle.CreateFromMemory

As documentation says IEnumerator methods are executed like thread, but I'm confused why
AssetBundleCreateRequest assetBundleCreateRequest = AssetBundle.CreateFromMemory(ByteArray);
yield return assetBundleCreateRequest;
freezes my game for 2 seconds. Can anybody explain?
Well it freezes for 2 seconds because that is what you are actually requesting with your yield return assetBundleCreateRequest
Asynchronous operation coroutine.
You can yield until asynchronous operation continues, or manually check whether it's done (isDone) or progress (progress). AsyncOperation
So right now you are requesting your coroutine to wait till your assetbundlecreaterequest is done.
For manually checking wheter the function is done, without having to freeze your application would be using the isdone or progress command instead
If you need further clarification feel free to comment.
Edit
Sample of using isdone
AssetBundleCreateRequest acr = AssetBundle.CreateFromMemory(decryptedData);
while (!acr.isDone)
{
yield;
}
AssetBundle bundle = acr.assetBundle;