首页 > 编程知识 正文

unity动画不能循环是怎么回事,unity3d设置角色方向

时间:2023-05-06 04:10:46 阅读:242515 作者:2040

先给出素材:
Tip Panel:

动画状态机:
用于控制Tip Panel的动画,通过将Exit变量设置为True时执行Tip Panel的退出动画。

ClosePanel()代码:
某用于统一管理Panel的管理类中统一关闭Panel的方法。通过传入参数name(要关闭的Panel的名字),先调用对应panel的OnClosing方法执行一些逻辑后才Destroy掉panel的实例。

/// <summary>/// close a panel./// </summary>/// <param name="name">type string name, panel's name.</param>public void ClosePanel(string name){ //... panel.OnClosing (); GameObject.Destroy (panel.gameObject); }

OnClosing()代码:
panel关闭前执行的逻辑在这里实现。
其中,exit2Hash是状态Exit变量的hash值。

public void OnClosing (){ animator.SetBool (exit2Hash, true); Debug.Log (animator.GetBool (exit2Hash).ToString ()); Debug.Log (animator.GetCurrentAnimatorClipInfo (0) [0].clip.name);}

OK按钮的点击事件是动态添加的:

okBtn.onClick.AddListener (OnOKButtonClick);

OnOKButtonClick()代码:
注意,ClosePanel方法和其他方法(如OnClosing、OnOKButtonClick以及ok安寝的动态添加点击事件都在同一个Panel类中)不在同一个类中。

void OnOKButtonClick(){ XXX.ClosePanel(gameObject.name);}

在实现如下流程时,碰到了问题:
 点击ok按钮 -> 执行Panel关闭动画 -> Destroy Panel对象

问题1:
 动画还未执行完毕,Panel便被Destroy掉了。
解决方案一:
 通过给tippanel_exit_clip动画添加事件,在tippanel_exit_clip动画播放解释后,触发指定事件Destroy掉panel实例,但这样显然就破坏掉了ClosePanel本身的意义。
解决方案二:
 在ClosePanel方法中的Destroy方法添加延迟参数,等待一段时间再Destroy掉panel实例。

GameObject.Destroy (panel.gameObject, 1f);

 缺点在于不能够根据动画具体结束时间再去Destroy,如果panel的Exit动画的执行时间超过1f,仍然会出现动画未执行完毕便被Destroy的现象。

尝试:
 判断tippanel_exit_clip是否播放完毕,播放完毕后再执行后续代码。
 有问题!animator.SetBool(exit2Hash, true)执行后,状态变量Exit的值的确是变为了True,但是实际上,animator并没有转换到tippanel_exit_clip,animator此时的clip仍然是tippanel_enter_clip。这就很迷了。。。
 
修改OnClosing代码如下:

public void OnClosing (){ base.OnClosing (); animator.SetBool (exit2Hash, true); Debug.Log (animator.GetBool (exit2Hash).ToString ()); Debug.Log (animator.GetCurrentAnimatorClipInfo (0) [0].clip.name);}

得到的结果为:

这里显现出一个问题,动画过渡。
Unity3d中Animator进行动画切换时会有一个过渡阶段,也就是Transition,在完成Transition之前,状态机的State会一直保持原State不变直到完成Transition后才会改变State,这也就是为什么我们看到Exit的值改变后,状态机对应的State并没有转换到对应State的原因了。
解决这个问题,我选择通过设置Transition的Transition Duration来处理。
参考文章hongfei233: Unity3D——Mecanim动画 AnimatorTransitionInfo和AnimatorStateInfo 在角色移动和待机平滑切换中的应用

问题:
 即使把Transition Duration的值设置为0,调试结果仍然为
 
 嗯。。。很迷。。。虽然修改了TransitionDuration的值,点击按钮后,响应tippanel_exit_clip动画执行的速度变快了,但是debug的值仍然没有变,这样便不能通过检测animator当前的状态来实现等待动画执行完毕再执行Destroy方法了。。。

 听说使用animator.Play()可以立即切换clip,兴奋的我赶紧去试了一下结果…
 
 Debug:
 
 说明一下:exit2Hash = Animator.StringToHash(“tippanel_exit_clip”);
 。。没错,视觉上动画的确转换了,然而为何debug出来的信息仍然显示为tippanel_enter_clip。。。。。(被困扰的第二天)

 结果:
 Unity3d在状态切换时,会进行两个状态的融合也就是动画过渡,而Transition就是这个混合过程,只有当Transition完成混合后,才会真正的切换到另一个状态。即使Animator.Play可以忽略混合过程直接切换状态,但事实上,当前帧是检测不出来的,只有在下一帧才能检测到状态切换为另一个状态。
 最后选择的处理方法:设置一个bool变量来标记状态,使用协程判断当前的动画是否为tippanel_exit_cip且播放完毕,达到条件则改变标记状态。在Update中检测标记变量的值来决定下一步是做其他还是Destroy掉Panel。
 代码如下:

// XXX CLASS public void ClosePanel(string name){ //... panel.OnClosing (); GameObject.Destroy (panel.gameObject); }//======================================private int exit2Hash = Animator.StringToHash("tippanel_exit_clip");private bool isFinished = false;//...void Update(){ if(isFinished) { XXX.ClosePanel(); }}public void OnClosing (){ animator.SetBool (exit2Hash, true); StartCoroutine (PlayExitAnimation ());}void OnOKButtonClick(){ OnClosing();}IEnumerator PlayExitAnimation(){ while (true) { AnimatorStateInfo stateInfo = animator.GetCurrentAnimatorStateInfo (0); if (stateInfo.IsName ("tippanel_exit_clip") && stateInfo.normalizedTime >= 1.0f) { break; } yield return null; } isFinished = true;}

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。