嗨,我试图构建一个应用程序并尝试在滚动上做事。
我在 Unity 的动画控制器中有 3 个不同的层,重量均为 1。在第一层中具有加载动画,在第2层中具有滚动动画,该动画需要在第1层动画的顶部播放。
因此,为了在滚动上调用动画,我编写了一个程序,该程序在滚动的底部调用动画,因此第 2 层"take001"上的动画在滚动上播放取决于滚动发生的次数。
现在我想获取第 2 层动画的当前时间。
找到下面的代码和我在 Unity 中创建的层的屏幕截图:
[参考图片] : https://i.stack.imgur.com/1huCM.jpg
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
,并从除法中返回余数。
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
乘以AnimationState.normalizedTime
; 来检索当前时间。
为此,您必须保留对公共变量中使用的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");
将每个动画状态哈希与其动画剪辑链接的字典:
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;
}
最后,一个获取当前动画师时间的函数:
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);
}