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

Dhe*_*gra 3 c# unity-game-engine

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

我在 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; } }
Run Code Online (Sandbox Code Playgroud)

Pro*_*mer 6

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

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

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


要做到这一点,正确的方法是有点复杂,因为统一不给你访问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;
Run Code Online (Sandbox Code Playgroud)

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

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

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

Dictionary<int, AnimationClip> hashToClip = new Dictionary<int, AnimationClip>();
Run Code Online (Sandbox Code Playgroud)

DictionaryAwake函数中初始化:

void Awake()
{
    hashToClip.Add(jumpAnimHash, jumpClip);
    hashToClip.Add(moveAnimHash, moveClip);
    hashToClip.Add(lookAnimHash, lookClip);
}
Run Code Online (Sandbox Code Playgroud)

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

AnimationClip GetClipFromHash(int hash)
{
    AnimationClip clip;
    if (hashToClip.TryGetValue(hash, out clip))
        return clip;
    else
        return null;
}
Run Code Online (Sandbox Code Playgroud)

最后,一个获取当前 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;
}
Run Code Online (Sandbox Code Playgroud)

用法

public Animator anim;

void Update()
{
    float time = GetCurrentAnimatorTime(anim, 0);
    Debug.Log(time);
}
Run Code Online (Sandbox Code Playgroud)