0
\$\begingroup\$

I have a button I got from google material design asset pack which has a ripple animation when pressed. I'm using the button's click option in the inspector that calls a method that switches scenes. But when I tap the button it switches the scene immediately and feels unnatural since the animation hasn't finished the button ripples animation.

I tried using co-routines. Made the button call a method in which I call a IEnumerator method (since the button can't directly call a co-routine) and then switch the scene. But that doesn't work since it starts the co-routine and switches the scene, the co-routine never pauses the code and never finishes (probably because I loaded a new scene and the object that carries the script isn't transferred).

Code example:

The method that gets called when I tap a button:

 public void OnButtonTap()
 {
     StartCoroutine(Wait(0.2f));
     SceneManager.LoadScene("OnePlayerGameIntro");
 }

The wait coroutine:

 public IEnumerator Wait(float seconds)
 {
     yield return new WaitForSeconds(seconds);
 }
\$\endgroup\$
1
\$\begingroup\$

Here is the method with the coroutines.

 public void OnButtonTap()
 {
     StartCoroutine(LoadSceneAfterDelay("OnePlayerGameIntro", 0.2f));
 }


 public IEnumerator LoadSceneAfterDelay(string sceneName, float seconds)
 {
     yield return new WaitForSeconds(seconds);
     SceneManager.LoadScene(sceneName);
 }

Coroutines can't pause the "main thread" of Unity. A coroutine is a parallel execution of a piece of code and runs "independently" of the main thread.

\$\endgroup\$
  • \$\begingroup\$ I used invoke and it worked, I'm probably going to use this since I can use the method and don't have to create 2 methods for every scene change. \$\endgroup\$ – Leon Laci Dec 30 '16 at 13:46
  • \$\begingroup\$ Yes you have, one to call Invoke, the other to call the SceneManager. Anyway, it's up to you ;) \$\endgroup\$ – Hellium Dec 30 '16 at 14:04
  • \$\begingroup\$ But when I want to load a scene in an another place I need to write it just once and call the method to load. Could write a singleton to access the method from the main script. \$\endgroup\$ – Leon Laci Dec 30 '16 at 16:09
0
\$\begingroup\$

Use the Invoke method. Invoke is used to trigger another method, but it allows us to pass a float value, representing a "wait" before the method runs.

Note that Invoke takes a string for the method name. Simple type out the name of the method with no enclosing brackets inside double quotation marks, as shown, in the example. Also note that you can not call methods that take parameters, in this way.


///<summary>Opens the scene immediately.</summary>
public void OpenScene
{
    // put your logic to open the scene here
}

///<summary>Opens the scene after a 0.3 second delay.</summary>
public void OpenSceneWithWait()
{
    Invoke("OpenScene", 0.3f);
}
\$\endgroup\$
0
\$\begingroup\$

If you're using Unity animations you could take advantage of Animation Events. This will allow you to trigger code at a specific point in an animation. This should allow you to be more accurate than using a co-routine or invoke method.

https://docs.unity3d.com/Manual/animeditor-AnimationEvents.html

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.