首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >播放并等待Animation/Animator播放完毕

播放并等待Animation/Animator播放完毕
EN

Stack Overflow用户
提问于 2016-11-14 18:54:33
回答 2查看 16K关注 0票数 6

在我的脚本中,我这样做了,当玩家在平台顶部时,将其向上移动。它运行良好。但现在我想让它在它起来后播放剪辑"Down“。

代码语言:javascript
复制
using UnityEngine;
using System.Collections;
using System.Reflection;

public class DetectPlayer : MonoBehaviour {

    GameObject target;

    public void ClearLog()
    {
        var assembly = Assembly.GetAssembly(typeof(UnityEditor.ActiveEditorTracker));
        var type = assembly.GetType("UnityEditorInternal.LogEntries");
        var method = type.GetMethod("Clear");
        method.Invoke(new object(), null);
    }

    void OnCollisionEnter(Collision collision)
    {
        if (collision.gameObject.name == "Platform")
        {
            Debug.Log("Touching Platform");
        }

    }

    void OnTriggerEnter(Collider other)
    {
        if (other.gameObject.name == "OnTop Detector")
        {
            Debug.Log("On Top of Platform");
            GameObject findGo = GameObject.Find("ThirdPersonController");
            GameObject findGo1 = GameObject.Find("Elevator");
            findGo.transform.parent = findGo1.transform;
            target = GameObject.Find("Elevator");
            target.GetComponent<Animation>().Play("Up");
        }
    }
}

在这行之后

代码语言:javascript
复制
target.GetComponent<Animation>().Play("Up");

我想在它播放完后播放下面的内容:

代码语言:javascript
复制
target.GetComponent<Animation>().Play("Down");
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2016-11-14 19:09:58

虽然这两个答案都应该有效,但使用协程和IsPlaying函数来实现这一点的另一种方法。如果您还想在动画之后执行其他任务,则可以使用协程解决方案。

适用于 system

旧的Unity动画回放系统。这应该在你的新项目中使用而不是,除非你还在使用旧的Unity版本。

代码语言:javascript
复制
IEnumerator playAndWaitForAnim(GameObject target, string clipName)
{
    Animation anim = target.GetComponent<Animation>();
    anim.Play(clipName);

    //Wait until Animation is done Playing
    while (anim.IsPlaying(clipName))
    {
        yield return null;
    }

    //Done playing. Do something below!
    Debug.Log("Done Playing");
}

适用于 system

这是新的Unity动画回放系统。此应该在新项目中使用,而不是Animation接口。在性能方面,最好使用Animator.StringToHash并通过哈希数比较当前状态,而不是使用IsName函数来比较字符串,因为哈希值为faster

假设您有名为JumpMoveLook的州名称。你可以像下面这样得到他们的散列,然后使用下面的函数来播放和等待他们:

代码语言:javascript
复制
const string animBaseLayer = "Base Layer";
int jumpAnimHash = Animator.StringToHash(animBaseLayer + ".Jump");
int moveAnimHash = Animator.StringToHash(animBaseLayer + ".Move");
int lookAnimHash = Animator.StringToHash(animBaseLayer + ".Look");

public IEnumerator PlayAndWaitForAnim(Animator targetAnim, string stateName)
{
    //Get hash of animation
    int animHash = 0;
    if (stateName == "Jump")
        animHash = jumpAnimHash;
    else if (stateName == "Move")
        animHash = moveAnimHash;
    else if (stateName == "Look")
        animHash = lookAnimHash;

    //targetAnim.Play(stateName);
    targetAnim.CrossFadeInFixedTime(stateName, 0.6f);

    //Wait until we enter the current state
    while (targetAnim.GetCurrentAnimatorStateInfo(0).fullPathHash != animHash)
    {
        yield return null;
    }

    float counter = 0;
    float waitTime = targetAnim.GetCurrentAnimatorStateInfo(0).length;

    //Now, Wait until the current state is done playing
    while (counter < (waitTime))
    {
        counter += Time.deltaTime;
        yield return null;
    }

    //Done playing. Do something below!
    Debug.Log("Done Playing");

}

对于专门针对冲突回调函数(OnTriggerEnter)的特定问题的解决方案,有两种可能的方法:

1.Start在触发检测后播放动画的协程函数:

代码语言:javascript
复制
void OnTriggerEnter(Collider other)
{
    if (other.gameObject.name == "OnTop Detector")
    {
        Debug.Log("On Top of Platform");
        GameObject findGo = GameObject.Find("ThirdPersonController");
        GameObject findGo1 = GameObject.Find("Elevator");
        findGo.transform.parent = findGo1.transform;
        target = GameObject.Find("Elevator");
        StartCoroutine(playAnim(target));
    }
}

IEnumerator playAnim(GameObject target)
{
    Animation anim = target.GetComponent<Animation>();
    anim.Play("Up");

    //Wait until Up is done Playing the play down
    while (anim.IsPlaying("Up"))
    {
        yield return null;
    }

    //Now Play Down
    anim.Play("Down");
}

2.Make OnTriggerEnter函数a协程(IEnumerator)而不是void函数:

代码语言:javascript
复制
IEnumerator OnTriggerEnter(Collider other)
{
    if (other.gameObject.name == "OnTop Detector")
    {
        Debug.Log("On Top of Platform");
        GameObject findGo = GameObject.Find("ThirdPersonController");
        GameObject findGo1 = GameObject.Find("Elevator");
        findGo.transform.parent = findGo1.transform;
        target = GameObject.Find("Elevator");
        Animation anim = target.GetComponent<Animation>();
        anim.Play("Up");

        //Wait until Up is done Playing the play down
        while (anim.IsPlaying("Up"))
        {
            yield return null;
        }

        //Now Play Down
        anim.Play("Down");
    }
}
票数 13
EN

Stack Overflow用户

发布于 2016-11-14 18:57:11

一种不需要手动检查的方法是使用排队

代码语言:javascript
复制
target.GetComponent<Animation>().PlayQueued("Down", QueueMode.CompleteOthers);

此代码将等待当前正在对象上播放的任何其他动画完成,然后再播放排队的动画。

The Unity API page regarding this topic

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/40587030

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档