Unity3D获取动画师控制器当前动画时间

时间:2018-10-09 13:25:30

标签: c# unity3d

大家好,我试图构建一个应用程序,并尝试在滚动中执行操作。

我在Unity的Animator控制器中具有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; } }

1 个答案:

答案 0 :(得分:2)

最简单的方法是用1划分当前动画状态归一化时间,然后从该划分中返回余数。

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

大多数情况下都可以使用,但是我见过一些无法正常工作的地方


执行此操作的正确方法有点复杂,因为Unity不允许您访问AnimationClip使用的Animator,并且您需要AnimationClip才能通过将AnimationClip.lengthAnimationState.normalizedTime;相乘。

为此,您必须保留对公共变量中使用的AnimationClip的引用。创建一个使用Animator.StringToHash作为键并使用相应的AnimationClip作为值的字典。要获取当前的AnimationClip,请将Animator.GetCurrentAnimatorStateInfo.fullPathHash传递给Dictionary,它将为您提供适当的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>();

Dictionary函数中初始化Awake

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);
}