我有用于 look , walk 和 attack 的2D动画-每个都有4个方向-总共有12个动画剪辑。动画控制器具有以下参数:
我希望一次只播放一个剪辑。它适用于 look 和 walk 动画,因为它们基于其参数是互斥的。问题是 attack 剪辑,因为它是基于触发器的。当我进入该状态时,它会与已经播放的 look 或 walk 动画融合在一起。输入 attack 动画时,我希望当前动画停止并且 attack 动画在 look 或之前运行完成步行动画再次播放。
最好,我希望通过仅使从Any State
到其他状态的转换(没有状态间转换)来做到这一点。我有许多用于不同角色和设备的动画,再加上将来除了外观/行走/攻击之外,还将有更多类型的动画,因此我想避免添加还有几十个过渡。
我曾考虑过将isAttacking
参数从触发器更改为布尔值,但这似乎是一个错误的选择,因为那样的话我将必须有代码和动画事件来跟踪我的攻击动画,并在播放完成后将isAttacking
设置为false,这似乎会增加系统的复杂性和膨胀性
答案 0 :(得分:1)
您必须将彼此之间的所有状态连接起来……就像66
过渡..没有什么乐趣..因为...现在自然地添加了一个过渡:D
我的意思是,您可以这样做,并对所有超出攻击状态的过渡使用HasExitTime = true; ExitTime = 1
,以便在过渡之前等待动画完成-对于所有其他人,请使用HasExitTime = false
等待,但是直接开始转换。
但是我强烈建议您使用一个小的脚本,并为bool
使用一个isAttacking
,这样会使您的生活更加轻松。
您可以简单地向他自己的攻击状态添加一个脚本(StateMachineBehaviour(类似于GameObjects上的组件),在脚本中等待动画完成并重置bool。然后,您可以将所有过渡保留在Any State
上,并根据需要配置它们。
在动画制作器窗口中选择一个状态时,您会注意到每个状态都有一个带有Add Behaviour
按钮的检查器,该按钮与GameObjects
非常相似:
在这里创建新的行为,然后简单地做
using UnityEngine;
public class StopAttack : StateMachineBehaviour
{
private float timePassed = 0;
// OnStateUpdate is called before OnStateUpdate is called on any state inside this state machine
//
// Unity's comment above sounds a bit confusing ... but
// simply consider this the Update method of StateMachineBehaviours ;)
public override void OnStateUpdate(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
{
timePassed += Time.deltaTime;
// while timePassed is smaller than the animation clip's length
// do nothing
if (timePassed < stateInfo.length) return;
// reset the bool
animator.SetBool("isAttacking", false);
}
}
现在进行平滑混合,只需将过渡设置为类似
FixedDuration
,则为秒,否则为%)根据此过渡持续时间等,您可能还希望攻击动画提前将isAttacking
重设,例如
if (timePassed < stateInfo.length - 0.25 * stateInfo.length) return;
答案 1 :(得分:0)