敌人状态:
1、待机状态,idle原地
2、搜寻玩家状态,walk前进
3、追击玩家,run前进
4、攻击玩家,atk!
5、收到伤害,onhit
6、死亡状态,延迟销毁。
——————————————————————————
目前实现:待机、搜寻、追击、攻击四个状态切换。
Animator中参数 如下:状态切换注意Exit time 取消勾选,切换变为立即切换.
人物模型设置:两层Ykn ,Yknsprite.
第一层控制移动受力,碰撞检测。
第二层控制动画切换,和朝向切换。
代码部分:AI Enemy(C#):因为数据以后为代码传入,在此设为共有方便调试。
代码注意点:
1、FixedUpdate()是 固定的时间间隔执行,不受游戏帧率(fps)的影响, 防止动画发生抽搐。
2、锁定RigidbodyConstraints2D.FreezeRotation。防止人物扑街倒地。
3、状态转换通过检测和玩家距离实现切换。
using UnityEngine;
using System.Collections;
public class AIEnemy : MonoBehaviour
{
private bool IsWalk;
private bool IsRun;
private bool IsDead;
private bool IsOnhit;
private bool IsAtk;
public Animator enemy_ani;
public Transform player;
public GameObject enemyOBG;
public float finddistance = 10;
public float chargedistance = 5;
public float atkdistance = 2f;
public float walkspeed = 2500;
public float runspeed = 3500;
private bool IsLookRight;
private Vector3 SpriteOriginalScale;
private Vector3 direction;
void Start()
{
IsWalk = false;
IsRun = false;
IsDead = false;
IsAtk = false;
IsOnhit = false;
SpriteOriginalScale = enemyOBG.transform.localScale;
this.GetComponent<Rigidbody2D>().constraints = RigidbodyConstraints2D.FreezeRotation;
}
void FixedUpdate()
{
direction = player.position - this.transform.position;
Lookplayer(direction);
CanWalk(direction);
CanRun(direction);
CanAtk(direction);
//动画设置
enemy_ani.SetBool("IsRun", IsRun);
enemy_ani.SetBool("IsWalk", IsWalk);
enemy_ani.SetBool("IsDead", IsDead);
enemy_ani.SetBool("IsAtk", IsAtk);
enemy_ani.SetBool("IsOnhit", IsOnhit);
}
void Lookplayer(Vector3 direction)
{
if (direction.x > 0)
{
IsLookRight = true;
enemyOBG.transform.localScale = SpriteOriginalScale;
//collider错位补正
this.GetComponent<Collider2D>().offset = new Vector2(-0.5f, -0.12f);
}
else if (direction.x < 0)
{
IsLookRight = false;
enemyOBG.transform.localScale = new Vector3(-SpriteOriginalScale.x, SpriteOriginalScale.y, SpriteOriginalScale.z);
//collider错位补正
this.GetComponent<Collider2D>().offset = new Vector2(0.5f, -0.12f);
}
}
void CanWalk(Vector3 direction)
{
if (Mathf.Abs(direction.x) <= finddistance && Mathf.Abs(direction.x) >= chargedistance)
{
IsWalk = true;
//向玩家移动
Vector3 forcedirect = Vector3.Normalize(direction);
this.transform.GetComponent<Rigidbody2D>().AddForce(forcedirect * walkspeed * Time.deltaTime);
}
else
{
IsWalk = false;
}
}
void CanRun(Vector3 direction)
{
if(Mathf.Abs(direction.x) <= chargedistance && Mathf.Abs(direction.x) >= atkdistance)
{
IsRun = true;
//向玩家追击
Vector3 forcedirect = Vector3.Normalize(direction);
this.transform.GetComponent<Rigidbody2D>().AddForce(forcedirect * runspeed * Time.deltaTime);
}
else
{
IsRun = false;
}
}
void CanAtk(Vector3 direction)
{
if (Mathf.Abs(direction.x) <= atkdistance && Mathf.Abs(direction.x) >= 0)
{
IsAtk = true;
//向玩家攻击
}
else
{
IsAtk = false;
}
}
}
最终效果图: