文章目录
制作敌人的动画优先考虑动画机可以应用在所有敌人的身上。
1. Animator窗口设置
1.1 从idle切换到run
从idle状态到run状态,敌人需要先在原地执行一次idle的动画,执行结束后,就执行run移动的动画,走到每一个目标点的时候切换到idle状态短暂停留,然后再进行移动。
所以代表着cucumber的动画除了run动画需要循环播放以外,其他都是单次执行的。
- 逐一取消除run以外动画的loop
- idle创建Transition
- 条件是需要播放完整个动画,将ExitTime的百分比为修改为1
- 取消勾选FixedDuration,并且将其设置为0
这样的话idle动画播放完以后会马上切换到run动画
1.2 从run切换回idle
当enemy移动到对应位置的时候,就把动画切换回idle,即每当移动到左右A,B两个目标点的时候,就把动画从run改回到idle状态。
- run创建Transition
- 创建一个整型的变量state对应各种状态,默认的初始值设置0,移动过程中再次回到idle的状态设置为state-Equals-0
- 不需要退出时间和持续时间,取消勾选HasExitTime和FixedDuration并设置为0
2.代码实现动画效果
需要在Enemy实现的动画状态,添加控制动画状态机的变量,并初始化组件,初始化组件在独立的虚方法Init()方法中,并在Awake中调用。
public Animator anim;
// 初始化 方便子类进行修改
public virtual void Init()
{
anim = GetComponent<Animator>();
}
// 确保游戏一开始变量有值,优先State执行
private void Awake()
{
Init();
}
创建动画的参数来调用Animator中的Parameter
public int animState;
修改巡逻状态中的代码逻辑,
using UnityEngine;
public class PatrolState : EnemyBaseState
{
public override void EnterState(Enemy enemy)
{
// 一进入游戏数值为0,表示从idle动画状态开始
enemy.animState = 0;
// 一进入状态找到巡逻的目标点
enemy.SwitchPoint();
}
public override void OnUpdate(Enemy enemy)
{
// !如果正在播放的动画 (动画的层级).IsName("状态的名称")
if (!enemy.anim.GetCurrentAnimatorStateInfo(0).IsName("idle"))
{
enemy.animState = 1;
enemy.MoveToTarget();
}
// 每一帧把不断的循环 无限趋近于目标点 当前敌人的坐标以及当前敌人的目标点
if (Mathf.Abs(enemy.transform.position.x - enemy.targetPonit.position.x) < 0.01f)
{
// 切换点以外,也同时切换回idle的状态
// (这里的逻辑是,一切换到巡逻的状态先运行进入状态EnterState方法,进入anim初始化为0,再次执行idle的动画状态)
enemy.TransitionToState(enemy.patrolState);
}
// 如果攻击列表内有物体,敌人就进行攻击 (巡逻模式切换到攻击状态)
if (enemy.attackList.Count > 0)
enemy.TransitionToState(enemy.attackState);
}
}