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)
最简单的方法是将当前动画状态归一化时间除以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.length
用AnimationState.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)
Dictionary
在Awake
函数中初始化:
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)