敌人的AI----1
上次两次博客把主角的移动写完了,这次根据作者的顺序会开始做敌人,需要资源的可以到作者本人的百度贴吧里面下载,由于版权问题,我这里就不提供下载了。AI一直是一个游戏的灵魂,先把简单的做好以后,之后我会好好研究一下ai的一些算法。
创建一个一个Enemy脚本
using UnityEngine;
using System.Collections;
///Author:CWH
///email:cwhisme@qq.com
///date:2014.1.17
public class Enemy : MonoBehaviour
{
#region 属性
public string m_name;//名字
public int m_level;//等级,以判断角色应当获取的经验
public int m_maxLife;//生命
public int m_currentLife;//当前生命
public int m_defense;//防御力
public int m_attack;//攻击力
public float m_speed;//速度
public int m_rotateSpeed;//旋转速度
public float m_attackRadius;//攻击半径
#endregion
#region 对象
public Transform m_transform;//自己
protected Animation m_animation;//动画组件
public Transform m_attackTarget;//攻击对象
public BattleChange m_damageTarget;//伤害对象
private BattleChange m_changeState;//战斗时改变生命等属性脚本对象
protected Rigidbody m_rigidbody;
#endregion
#region 判断
public bool m_isBoss=false;
protected bool m_isIdle=true;
protected bool m_isDead=false;
#endregion
#region 变量
protected int m_idleStat;//定义空闲状态动画的随机值
protected float m_idleTime=0;//每一个空闲状态持续时间
///声音
public AudioClip m_sound;
public AudioClip m_attackSound;
public AudioClip m_skillSound;
protected Vector3 m_forward;//敌人的前方向
protected RaycastHit m_hit;//射线碰撞
protected float m_attackDistance=8;//会攻击的视线距离
protected LayerMask m_layerMask;
protected float m_distanceToOther;//与攻击对象的距离
public Transform m_attackParticle;//普通攻击粒子效果
public Transform m_skillParticle;//技能攻击粒子效果
protected float m_attackDelay=2;//攻击延时
protected float m_skillRandom;//随机出现技能
#endregion
#region 动画状态
protected string m_animationIdle="idle1";
protected string m_animationIdle2="idle2";
protected string m_animationIdle3="idle3";
protected string m_animationWalk="walk";
protected string m_animationAttack="attack";
protected string m_animationSkill="skill";
protected string m_animationDeath="death";
#endregion
void Start () {
///加刚体设置
//m_rigidbody = (Rigidbody)m_transform.gameObject.AddComponent("Rigidbody");
///m_rigidbody.freezeRotation = true;
Init();
m_transform=this.transform;//获取自己对象
m_animation=GetComponent<Animation>();
m_layerMask=1<<LayerMask.NameToLayer("Human");
//m_layerMask=LayerMask.NameToLayer("Human");
m_changeState=GetComponent<BattleChange>();
m_changeState.m_defense=m_defense;
m_changeState.m_life=m_currentLife;
}
protected void SetAttribute(string name,int level,int Life,int defense,int attack,int speed,int rotatteSpeed,float attackRadius)
{
m_name=name;
m_level=level;
m_maxLife=Life;
m_currentLife=Life;
m_defense=defense;
m_attack=attack;
m_speed=speed;
m_rotateSpeed=rotatteSpeed;
m_attackRadius=attackRadius;
}
protected virtual void Init()
{
}
void Update () {
if(m_isIdle)
{
m_idleTime-=Time.deltaTime;
if(m_idleTime<0)///空闲随机时间到了就随机做出新动作
{
m_idleStat=Random.Range(0,11);
audio.clip=m_sound;
audio.Play();
m_idleTime=3;
}
}else if(m_isDead){
//Debug.Log("is Dead");
}else{
RotateTo();
Attack();
}
switch(m_idleStat)
{
case 1:m_animation.CrossFade(m_animationIdle);
audio.clip=m_sound;
audio.Play();
break;
case 2:m_animation.CrossFade(m_animationIdle);
m_transform.Rotate(0,m_rotateSpeed*Time.deltaTime,0);
break;
case 3:m_animation.CrossFade(m_animationIdle2);
break;
case 4:m_animation.CrossFade(m_animationIdle2);
break;
case 5:m_animation.CrossFade(m_animationWalk);
m_transform.Rotate(0,m_rotateSpeed*Time.deltaTime,0);
break;
case 6:m_animation.CrossFade(m_animationWalk);
m_transform.Rotate(0,m_rotateSpeed*Time.deltaTime,0);
break;
case 7:m_animation.CrossFade(m_animationWalk);
m_transform.Rotate(0,m_rotateSpeed*Time.deltaTime,0);
break;
case 8:m_animation.CrossFade(m_animationWalk);
m_transform.Translate(Vector3.forward*m_speed*Time.deltaTime);
break;
default:m_animation.CrossFade(m_animationIdle3);
m_transform.Translate(Vector3.forward*m_speed*Time.deltaTime);
break;
}
m_forward = m_transform.TransformDirection(Vector3.forward);
if (Physics.Raycast(m_transform.position + Vector3.up, m_forward, out m_hit, m_attackDistance, m_layerMask))
{
m_attackTarget=m_hit.collider.gameObject.transform;//如果看见任何人类对象,就获取其位置,并将Idle状态置为false
if(m_attackTarget.GetComponent<BattleChange>().m_life!=0)
{
m_isIdle=false;
}
}
GetState();
}
protected void RotateTo()
{
Vector3 m_oldAngle=m_transform.eulerAngles;//当前旋转角度
m_transform.LookAt(m_attackTarget.position);//盯着攻击对象
float m_target=m_transform.eulerAngles.y;//目标角度吧
float m_targetAngle=Mathf.MoveTowardsAngle(m_oldAngle.y,m_target,m_rotateSpeed*Time.deltaTime);//计算应转动的角度
m_transform.eulerAngles=new Vector3(0,m_targetAngle,0);//转动角度
}
protected void Attack()
{
m_distanceToOther=Vector3.Distance(m_transform.position,m_attackTarget.position);
m_attackDelay-=Time.deltaTime;
if(m_distanceToOther<m_attackRadius)///目标进入攻击半径,攻击
{
if(m_attackDelay<0)
{
m_forward=m_transform.TransformDirection(Vector3.forward);
/// if(Physics.Raycast(m_transform.position+Vector3.up,m_forward,out m_hit,m_attackRadius,m_layerMask))
/// {
/// m_animation.CrossFade(m_animationAttack);
/// Instantiate(m_attackParticle,m_hit.collider.gameObject.transform.position+Vector3.up,Quaternion.identity);//攻击,实例化一个粒子
/// m_attackDelay=2;//攻击成功,重置延时
/// }
if(Physics.Raycast(m_transform.position+Vector3.up,m_forward,out m_hit,m_attackRadius,m_layerMask))
{
m_skillRandom=Random.value;
if(m_skillRandom<0.96f)///大概有4%的几率发出技能
{
m_animation.CrossFade(m_animationAttack);
m_damageTarget=m_hit.collider.gameObject.GetComponent<BattleChange>();
StartCoroutine(WaitForAttack(0.6f,m_attackParticle,m_attackSound,m_attack));
if(m_damageTarget.m_isDead)///如果攻击目标死掉了的话,就回到Idle状态吧
{
m_isIdle=true;
}
if(m_currentLife==0){
m_isDead=true;
}
}else
{
m_animation.CrossFade(m_animationSkill);
m_damageTarget=m_hit.collider.gameObject.GetComponent<BattleChange>();
StartCoroutine(WaitForAttack(0.6f,m_attackParticle,m_attackSound,m_attack*3));
if(m_damageTarget.m_isDead)///如果攻击目标死掉了的话,就回到Idle状态吧
{
m_isIdle=true;
}
if(m_currentLife==0){
m_isDead=true;
}
}
m_attackDelay=2;
}
}
}else if(m_distanceToOther<20)///如果距离小于20,对目标进行追击
{
m_animation.CrossFade(m_animationWalk);
m_transform.Translate(Vector3.forward*m_speed*Time.deltaTime);
}else if(m_distanceToOther<90)/// 如果距离大于20,就回到Idle状态,不追目标了
{
m_isIdle=true;
}else///超过九十米的话,为了省点资源,就把这个敌人销毁罢
{
Destroy(this.gameObject);
}
}
void GetState()
{
m_currentLife=m_changeState.m_life;
}
IEnumerator WaitForAttack(float timer,Transform particle,AudioClip m_audio,int attack)
{
yield return new WaitForSeconds(timer);
Instantiate(particle ,m_damageTarget.transform.position+Vector3.up,Quaternion.identity);
audio.PlayOneShot(m_audio);//播放声音
m_damageTarget.Damage(attack);//调用对象的伤害函数
if(m_damageTarget.m_isDead)///如果攻击目标死掉了的话,就回到Idle状态吧
{
m_isIdle=true;
}
}
}
一开始代码可能比较多,所以尽量贴出代码,但是要照着做就比较麻烦了,敌人的内容会在下一节继续说下去,有看过的朋友或者做这有疑问的朋友可以留言大家一起交流