配置好我们的新动画,将其加入动画机。首先我们要将Rig中的如图所示的参数调整好了。
接下来,设置Animation页下的烘培,烘培旋转和Y轴,旋转根据Original,Y轴根据Feet。
要实现连续攻击,攻击B要连接到攻击A之后,在做攻击A动画时如果再次按下攻击键,就会从攻击A转换到攻击B,我们的转换条件是attack。
攻击A转换到攻击B要设置为优先转换。
最后,修改这个玩意(这叫什么来着?),我们不需要攻击A后面的收刀动作和攻击B前面的起刀动作,这样做就能“剪”掉这些不需要的动画了,也就是灰色部分。你也可以直接调整攻击B动画的起始位置。
和攻击B一样,配置好动画,放到动画机中就行,转换条件和之前的也是一样的。
在我们之前的设计中,你可以通过快速连按来实现连击,我们希望玩家打出连击要更难一点,玩家只能在攻击快要结束的那一段时间内再按出攻击键才能连击,而不是随随便便就能打出连击。在接下来我们要实现通过代码来重设Attack信号。确切来说,我们将通过代码,在动画播放完挥砍动作时,将之前输入的attack信号给Reset掉,我们将要通过动画事件(Animation Events)来实现以上功能。
动画事件可以在动画资源下添加,如图所示。我们给需要做上述操作的动画资源都添加了这个叫ResetTrigger的事件,我们并没有在事件名称中具体指明reset哪个trigger,原因是我们想要复用这个事件,我们可以在String参数中指明我们要reset的trigger的名字。
要让动画事件得以接收,我们需要在Animator组件的同一个游戏物体上挂载一个脚本来实现具体代码。
代码如下:
public class AnimTriggerController : MonoBehaviour
{
// 动画组件
private Animator anim;
private void Awake()
{
anim = GetComponent<Animator>();
}
// 动画事件 用于在执行时将triggerName代表的信号重置
public void ResetTrigger(string triggerName)
{
anim.ResetTrigger(triggerName);
}
}
老师在这里提到了在AnimTriggerController中处理事件的两种方案,一种是就在AnimTriggerController中拿到我们想要的动画组件对象,然后处理事件,另一种是AnimTriggerController不直接处理事件,而是将事件再SendMessage到PlayerController中进行处理。在这里我们采用第一种,因为已经有太多的SendMessage了。
关于攻击层的权重调整,有一个缺陷,因为我们是直接调整权重为1,所以你会看到攻击动画在结束时生硬的转变到Base层的Idle,要解决这个问题,我们可以对调整权重的参数进行插值。
// 攻击动画层权重的插值目标参数
private float m_attackAnimWeightLerpTarget;
// ...
// 进入Attack层的动画节点attack_oneHand_A时执行的方法
// 通过PlayerController动画机中的attack_oneHand_A节点上挂载的FSMOnEnter调用
public void OnAttack_oneHandAEnter()
{
// ...
// 修改攻击动画层权重目标值为1 具体的权重调整在OnAttack_oneHandAUpdate中执行
m_attackAnimWeightLerpTarget = 1.0f;
}
// 在Attack层的动画节点attack_oneHand_A更新时执行的方法
// 通过PlayerController动画机中的attack_oneHand_A节点上挂载的FSMOnEnter调用
public void OnAttack_oneHandAUpdate()
{
// ...
// 通过Lerp修改动画权重值
anim.SetLayerWeight(anim.GetLayerIndex("Attack"),
Mathf.Lerp(anim.GetLayerWeight(anim.GetLayerIndex("Attack")), m_attackAnimWeightLerpTarget, 0.1f));
}
// 进入Attack层的动画节点idle时执行的方法
// 通过PlayerController动画机中的idle节点上挂载的FSMOnEnter调用
public void OnAttackIdleEnter()
{
// ...
// 修改攻击动画层权重目标值为0
m_attackAnimWeightLerpTarget = 0f;
}
// 进入Attack层的动画节点idle时执行的方法
// 通过PlayerController动画机中的idle节点上挂载的FSMOnUpdate调用
public void OnAttackIdleUpdate()
{
// 通过Lerp修改动画权重值
anim.SetLayerWeight(anim.GetLayerIndex("Attack"),
Mathf.Lerp(anim.GetLayerWeight(anim.GetLayerIndex("Attack")), m_attackAnimWeightLerpTarget, 0.01f));
}
OnAttackIdleUpdate是新加入的函数,对接攻击层Idle新添的FSMOnUpdate对象,为了实现和OnAttack_oneHandAUpdate一样的效果功能。
当你想要给动画片段改名时,应该到如图所示的地方改,不能直接改动画片段的名称。