【问题标题】:Unity3D get animator controller current Animation timeunity3D 获取动画控制器当前动画时间
【发布时间】:2018-10-09 22:51:05
【问题描述】:

大家好,我正在尝试构建一个应用程序并尝试在滚动条上做事。

我在 Unity 的 Animator Controller 中有 3 个不同的层,所有的权重都为 1。第一层有加载动画,第 2 层有滚动动画,需要在层的顶部播放1个动画。

为了在滚动上调用动画,我编写了一个程序,该程序在滚动的基础上调用动画,因此第 2 层“take001”上的动画在滚动上播放取决于发生了多少滚动。

现在我想获取第 2 层动画的当前时间。

找到下面的代码和我在 Unity 中创建的图层的屏幕截图:

[参考图片]:https://imgur.com/j4Up4OE

using UnityEngine;
using System.Collections;
public class MouseMovementScript : MonoBehaviour {
Animator anim;
AnimatorStateInfo stateInfo;
AnimatorClipInfo[] myAnimatorClip;
double speedBase = 1;
void Start () {
     anim = GetComponent<Animator>();
     stateInfo = anim.GetCurrentAnimatorStateInfo(1);
    //Output the name of the starting clip

}

// Update is called once per frame
void Update () {

    var d = Input.GetAxis("Mouse ScrollWheel");

    if (d > 0f)
    {

        Time.timeScale = 1;
        anim.SetFloat("Direction", 1.0f);
        anim.Play("take001");
        StartCoroutine(TestCoroutine(d));

        anim.Play("BoxAnimation001");
    }
    else if (d < 0f)
    {
        Time.timeScale = 1;
        anim.SetFloat("Direction", -1.0f);
    }

     // Cursor
    Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
    RaycastHit hit;

    if(Physics.Raycast (ray, out hit))
    {
        if (Input.GetMouseButtonDown(0)){
            if(hit.transform.tag == "Popup_1")
            {
                Application.ExternalCall("OpenPopup", 0);
            } 
            else if(hit.transform.tag == "Popup_2")
            {
                Application.ExternalCall("OpenPopup", 1);
            } 
            else if(hit.transform.tag == "Popup_3")
            {
                Application.ExternalCall("OpenPopup", 2);
            } 
            else if(hit.transform.tag == "Popup_4")
            {
                Application.ExternalCall("OpenPopup", 3);
            } 
        }
    }
}


IEnumerator TestCoroutine(float d){
 yield return new WaitForSeconds(d);
 Time.timeScale = 0; } }

【问题讨论】:

    标签: c# unity3d


    【解决方案1】:

    最简单的方法是将当前动画状态归一化时间除以1,然后返回除法的余数。

    public float GetCurrentAnimatorTime(Animator targetAnim, int layer = 0)
    {
        AnimatorStateInfo animState = targetAnim.GetCurrentAnimatorStateInfo(layer);
        float currentTime = animState.normalizedTime % 1;
        return currentTime;
    }
    

    这在大多数情况下都有效,但我见过一些地方没有按预期工作


    执行此操作的正确方法有点复杂,因为 Unity 不会让您访问 Animator 使用的 AnimationClip,您需要 AnimationClip 通过将 AnimationClip.length 与 @ 相乘来检索当前时间987654329@;.

    为此,您必须保留在公共变量中使用的AnimationClip 的引用。创建一个使用Animator.StringToHash 作为键和对应的AnimationClip 作为值的字典。要获取当前的AnimationClip,请将Animator.GetCurrentAnimatorStateInfo.fullPathHash 传递给字典,它将为您提供正确的AnimationClip。您可以使用此剪辑通过将其长度乘以 AnimationState.normalizedTime 来获取当前时间。


    您的AnimationClip 参考资料:

    public AnimationClip jumpClip;
    public AnimationClip moveClip;
    public AnimationClip lookClip;
    

    获取每个动画状态的动画状态哈希:

    const string animBaseLayer = "Base Layer";
    int jumpAnimHash = Animator.StringToHash(animBaseLayer + ".Jump");
    int moveAnimHash = Animator.StringToHash(animBaseLayer + ".Move");
    int lookAnimHash = Animator.StringToHash(animBaseLayer + ".Look");
    

    将每个动画状态哈希与其 AnimationClip 链接的字典:

    Dictionary<int, AnimationClip> hashToClip = new Dictionary<int, AnimationClip>();
    

    Awake函数中初始化Dictionary

    void Awake()
    {
        hashToClip.Add(jumpAnimHash, jumpClip);
        hashToClip.Add(moveAnimHash, moveClip);
        hashToClip.Add(lookAnimHash, lookClip);
    }
    

    从动画状态哈希中获取AnimationClip的函数:

    AnimationClip GetClipFromHash(int hash)
    {
        AnimationClip clip;
        if (hashToClip.TryGetValue(hash, out clip))
            return clip;
        else
            return null;
    }
    

    最后是一个获取当前Animator时间的函数:

    public float GetCurrentAnimatorTime(Animator targetAnim, int layer = 0)
    {
        AnimatorStateInfo animState = targetAnim.GetCurrentAnimatorStateInfo(layer);
        //Get the current animation hash
        int currentAnimHash = animState.fullPathHash;
    
        //Convert the animation hash to animation clip
        AnimationClip clip = GetClipFromHash(currentAnimHash);
    
        //Get the current time
        float currentTime = clip.length * animState.normalizedTime;
        return currentTime;
    }
    

    用法

    public Animator anim;
    
    void Update()
    {
        float time = GetCurrentAnimatorTime(anim, 0);
        Debug.Log(time);
    }
    

    【讨论】:

    • Programmer感谢您的评论。我正在尝试“animState.normalizedTime”,但在我的情况下它总是返回 0。此外,我在动画师的 3 个不同层上有多个动画,如 3 个统一的 .anim 文件。在那种情况下,我将如何获得第二层动画时间。抱歉,我对 Unity 有点陌生,所以可能对您没有任何意义。
    • 谢谢Programmer 这非常有帮助并且工作正常。谢谢
    • 不客气。看到您的评论,但不知道该告诉您什么,因为这对我有用并且是我一直在使用的。顺便说一句,您可以在我的回答中将图层传递给GetCurrentAnimatorTime 函数的第二个参数。该层从 0 开始,如数组。下一层是 1,下一层是 2。在我的示例中,我将 0 传递给它,因为这是第一层。您可以将图层传递给它。另外,在我有const string animBaseLayer = "Base Layer"; 的地方,您必须将"Base Layer" 替换为您的图层名称。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-09-02
    • 2019-06-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多