简体   繁体   中英

Unity calculate total animator to complete then change scene

Im trying to show an exit animation from a scene and, at the same time, load a new scene using LoadSceneAsync, keep the scene on memory until the animation ends, then change to the new scene like this question already solved

The catch is i have several animations running on layers all fired by the same trigger, right now all my animations are 1 seg on length, but some starts at 0 and some at 0.5 seg

How can i calculate the total time that will take the animation to complete, asynchronously load the new scene, then, either wait for the animation time to complete or, the loading of the new scene to finish (the one that takes longer), and finally change scene?

I was thinking of using 2 coroutines running simultaneously and wait for the longest to finish, but I'm not sure if this can be done (I'm pretty new to C# Programming), any ideas?

Right now I'm waiting a fixed time of 1.6 Seg because my animations are equal in time, but that can change and that's the only way i could think of...

public void GotoScene(string scene)
{
    // Start exit animations and wait
    CanvasAnimation.SetBool("hide", true);
    StartCoroutine(ChangeScene(1.6f, scene));
}

IEnumerator ChangeScene(float time, string goToScene)
{
    //Set the current Scene to be able to unload it later
    Scene currentScene = SceneManager.GetActiveScene();

    // Wait for exit animation to finish
    yield return new WaitForSeconds(time);

    // The Application loads the Scene in the background at the same time as the current Scene.
    AsyncOperation asyncLoad = SceneManager.LoadSceneAsync(goToScene, LoadSceneMode.Additive);

    //Wait until the last operation fully loads to return anything
    while (!asyncLoad.isDone)
    {
        yield return null;
    }

    //Move the GameObject (you attach this in the Inspector) to the newly loaded Scene
    SceneManager.MoveGameObjectToScene(WireRoomObj, SceneManager.GetSceneByName(goToScene));

    //Unload the previous Scene
    SceneManager.UnloadSceneAsync(currentScene);
}

You could probably check animation state from AnimatorStateInfo.normalizedTime and then wait in coroutine while normalizedTime of current animations are below 1. For example:

using System;
using System.Linq;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class WaitUntilComplete : MonoBehaviour {

    // Use this for initialization
    void Start () {
        StartCoroutine(WaitUntilAllAnimationsCompleted());
    }

    IEnumerator WaitUntilAllAnimationsCompleted() {
        print("waiting started " + Time.time);
        yield return new WaitWhile(() => GetAllAnimationStates().Any(state => state.normalizedTime < 1f));
        print("waiting ended " + Time.time);
    }

    List<AnimatorStateInfo> GetAllAnimationStates() {
        List<AnimatorStateInfo> states = new List<AnimatorStateInfo>();
        var animatorList = GetComponentsInChildren<Animator>();
        foreach (var anim in animatorList) {
            for (int i = 0; i < anim.layerCount; ++i) {
                states.Add(anim.GetCurrentAnimatorStateInfo(i));
            }
        }
        return states;
    }

}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM