制作游戏,需要带给玩家一种体验和挑战,那必不可少的就是电脑AI喽,
电脑AI也就是我们要书写的程序代码,用来告诉电脑,应该执行什么动作!
今天我给大家分享一下,我在这几天制作的一个简单的状态机,希望给大家一些启发! 希望大家可以写出更好的有限状态机!
感谢 softimagewht 的文章帮助 http://www.cnblogs.com/softimagewht/
以下代码为讲解!打包了Unity3D资源包,在我的资源里 15M,如有需要请自行下载!
有限状态机的执行顺序是
当前状态 -> 规则(用于判断到另一个状态的限制) -> 事件(另一个状态的需要干什么) -> 另一个状态激活
如此循环运作,由当前状态到另一个状态的控制,并且不会冲突
一,最简单的状态机就是通过if和switch...case判断,写入条件,到达某种状态,你需要各种各样的bool类型的开关来控制怪物的攻击,移动,巡逻,追逐,死亡...... 想必大家都有过这样的体验,最后,弄的26个字母全部用在写bool类型的开关上了,好不容易编辑完逻辑和代码,还要判断某个状态是否会和其他状态同时执行,还需要添加新的bool类型的开关,烦都烦死了.
二,今天给大家介绍的有限制状态机,应该是最常用到的一种写电脑AI的方法,因为,有限状态机的调理很清晰,可以很好的控制各个状态之间的转换,而且不用写那些繁琐的bool类型的开关字段,相信大家如果理解了我有限状态机,也一定会想我一样爱上他的,哈哈哈! 废话不多说了,还是让我们进入,有限状态机的世界吧!
①首先我们书写一个所有电脑AI怪物的有限状态机的根基脚本,用于其他状态的继承使用,在这里添加可以转换的规则和执行的事件(这里不是Unity的event哦,不要理解错了)
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
/// <summary>
/// 功能:所有电脑AI怪物的有限状态机根级
/// 创建者: VioletTD
/// 修改时间: 2015年11月13日 9:37
/// 感谢: Me 加油!
/// </summary>
public enum AIMonsterRule//*************************** 用于记录规则(用于转换)的状态(需要什么条件来触发怪物行动(下面的事件Event)) 枚举 ***************************
{
NullAIMonsterRule = 0,//*************************** 没有规则,表示不执行任何规则 ***************************
AIMonsterFindTargetRule,//*************************** 电脑AI怪物发现了目标的规则 ***************************
AIMonsterLostTargetRule,//*************************** 电脑AI怪物失去了目标的规则 ***************************
AIMonsterATKRangeRule,//*************************** 电脑AI怪物进入了攻击范围的规则 ***************************
AIMonsterMPEnoughRule,//*************************** 电脑AI怪物魔法充足释放技能的规则 ***************************
AIMonsterMPLackRule,//*************************** 电脑AI怪物魔法不足变回攻击状态的规则 ***************************
AIMonsterXPEnoughRule,//*************************** 电脑AI怪物特殊技能值充足时释放特殊技能的规则 ***************************
AIMonsterXPLackRule,//*************************** 电脑AI怪物特殊技能值不足变回攻击状态的规则 ***************************
AIMonsterBeatBackRule,//*************************** 电脑AI怪物被攻击后找到玩家的规则 ***************************
AIMonsterHPLackRule,//*************************** 电脑AI怪物血量不足 逃跑的规则 ***************************
AIMonsterHPEnoughRule,//*************************** 电脑AI怪物血量充足的规则 ***************************
AIMonsterHPZeroRule//*************************** 电脑AI怪物血量为零的规则 ***************************
}
public enum AIMonsterEvent//*************************** 用于记录达到某规则的状态下,怪物执行对应的事件(用于执行)Event ***************************
{
NullAIMonsterEvent = 0,//*************************** 没有事件,表示怪物不执行任何事件 ***************************
AIMonsterChaseEvent,//*************************** 电脑AI怪物追逐玩家怪物事件 ***************************
AIMonsterPatrolEvent,//*************************** 电脑AI怪物巡逻的事件 ***************************
AIMonsterATKEvent,//*************************** 电脑AI怪物攻击的事件 ***************************
AIMonsterSkillEvent,//*************************** 电脑AI怪物释放技能的事件 ***************************
AIMonsterXPSkillEvent,//*************************** 电脑AI怪物释放特殊技能的事件 ***************************
AIMonsterEscapeEvent,//*************************** 电脑AI怪物逃跑的事件 ***************************
AIMonsterDeadEvent//*************************** 电脑AI怪物死亡的事件 ***************************
}
public abstract class AIMonsterFSM {//*************************** 定义抽象类,其他脚本必须继承他才能实现里面的方法 ***************************
protected Dictionary<AIMonsterRule, AIMonsterEvent> AIMonster_RE_FSM = new Dictionary<AIMonsterRule, AIMonsterEvent>();//*************************** 定义保护性的字典用于存储电脑AI怪物的规则与事件的键值对 ***************************
protected AIMonsterEvent aiMonsterEvent;//*************************** 定义保护类型的电脑AI怪物事件的枚举 ***************************
public AIMonsterEvent MonsterEvent { get { return aiMonsterEvent; } }//*************************** 定义公有只读的电脑AI怪物事件(Event)的枚举 ***************************
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 电脑AI怪物的有限状态机模块 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//-------------------------------------------------------------------------------------------- 添加键值对规则(用于转换),事件(用于执行)方法作用 --------------------------------------------------------------------------------------------
#region 添加键值对规则(用于转换),事件(用于执行)方法作用
/// <summary>
/// 添加键值对规则(用于转换),事件(用于执行)方法作用
/// </summary>
/// <param name="AMR">AM.</param>
/// <param name="AME">AM.</param>
public void AddAIMonsterRuleAndEvent(AIMonsterRule AMR, AIMonsterEvent AME)////*************************** 添加键值对规则(用于转换),事件(用于执行)方法作用 ***************************
{
if (AMR == AIMonsterRule.NullAIMonsterRule)//@@@@@@@@@ 如果增加的转换规则是个NullAIMonsterRule(空转换规则),直接Debug.LogError,然后返回 @@@@@@@@@
{
Debug.LogError("AIMonsterFSM ERROR: NullAIMonsterRule is not allowed for a real AIMonsterRule");//*************************** 警告传入的转换规则为空转换规则 ***************************
return;//######### 跳过继续执行下面代码 #########
}
if (AME == AIMonsterEvent.NullAIMonsterEvent)//@@@@@@@@@ 如果AIMonsterEvent执行事件是NullAIMonsterEvent(空执行事件),Debug.LoError,然后返回 @@@@@@@@@
{
Debug.LogError("AIMonsterFSM ERROR: NullAIMonsterEvent is not allowed for a real AIMonsterEvent");//*************************** 警告传入的执行事件为空执行事件 ***************************
return;//######### 跳过继续执行下面代码 #########
}
if (AIMonster_RE_FSM.ContainsKey(AMR))//@@@@@@@@@ 如果将要增加的关联对是之前就存在与关联容器中,也照样Debug.LogError,之后返回被调用处 @@@@@@@@@
{
Debug.LogError("AIMonsterFSM ERROR: States " + aiMonsterEvent.ToString() + " already has AIMonsterRule " + AMR.ToString() +
"Impossible to assign to another state");//*************************** 当前的状态机已经分配了另一个状态 ***************************
return;//######### 跳过继续执行下面代码 #########
}
AIMonster_RE_FSM.Add(AMR, AME);//冲破了这些阻碍的话,终归可以添加此关联对了,下面的DeleteTransition函数就不用我写注释了吧!
}
#endregion
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 电脑AI怪物的有限状态机模块 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//-------------------------------------------------------------------------------------------- 删除键值对函数方法作用 --------------------------------------------------------------------------------------------
#region 删除键值对函数,前提是里面要有这个键值对啊
/// <summary>
/// 删除键值对函数,前提是里面要有这个键值对啊
/// </summary>
/// <param name="AMR">AM.</param>
public void DeleteTransition(AIMonsterRule AMR)//@@@@@@@@@ 删除键值对函数,前提是里面要有这个键值对啊 @@@@@@@@@
{
if (AMR == AIMonsterRule.NullAIMonsterRule)//@@@@@@@@@ 如果要删除的转换规则是空 @@@@@@@@@
{
Debug.LogError("AIMonsterFSM ERROR: NullAIMonsterRule is not allowed");//*************************** 该转换规则不允许被删除 ***************************
return;//######### 跳过继续执行下面代码 #########
}
if (AIMonster_RE_FSM.ContainsKey(AMR))//@@@@@@@@@ 如果键值对中包含要删除的键 @@@@@@@@@
{
AIMonster_RE_FSM.Remove(AMR);//*************************** 移除键值对 ***************************
return;//######### 跳过继续执行下面代码 #########
}
Debug.LogError("AIMonsterFSM ERROR: AIMonsterRule " + AMR.ToString() + " passed to " + aiMonsterEvent.ToString() +
" was not on the state's AIMonsterRule list");//*************************** 提示该转换规则已经在枚举列表中被移除 ***************************
}
#endregion
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 电脑AI怪物的有限状态机模块 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//-------------------------------------------------------------------------------------------- 此函数由下面这个脚本AIMonsterFSM.cs中的PerformTransition函数调用。是用来检索状态的方法作用 --------------------------------------------------------------------------------------------
#region 此函数由下面这个脚本AIMonsterFSM.cs中的PerformTransition函数调用。是用来检索状态的
/// <summary>
/// 此函数由下面这个脚本AIMonsterFSM.cs中的PerformTransition函数调用。是用来检索状态的
/// </summary>
/// <returns>The output state.</returns>
/// <param name="AMR">AM.</param>
public AIMonsterEvent GetOutputState(AIMonsterRule AMR)//*************************** 此函数由下面这个脚本AIMonsterFSM.cs中的PerformTransition函数调用。是用来检索状态的 ***************************
{
if (AIMonster_RE_FSM.ContainsKey(AMR))//@@@@@@@@@ 如果键值对中包含该转换规则@@@@@@@@@
{
return AIMonster_RE_FSM[AMR];//*************************** 就返回该转换规则的值(执行事件) ***************************
}
else//@@@@@@@@@ 不包含该转换规则 @@@@@@@@@
{
return AIMonsterEvent.NullAIMonsterEvent;//*************************** 返回执行事件为空 ***************************
}
}
#endregion
public virtual void DoBeforeEntering() { }//*************************** 在转换状态之前 ***************************
public virtual void DoBeforeLeaving() { }//*************************** 在转换状态之后 ***************************
public abstract void Change_Rule(GameObject player, GameObject AIMonster);//*************************** 该方法用于设置规则的转换,可传入多个参数 ***************************
public abstract void Execute_Event(GameObject player, GameObject AIMonster);//*************************** 该方法用于在不同的规则下对应执行的事件 ***************************
}
②再写一个电脑AI怪物的管理状态机的系统脚本
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
/// <summary>
/// 功能:电脑AI怪物的有限状态机的管理系统
/// 创建者: VioletTD
/// 修改时间: 2015年11月13日 14:19
/// 感谢: Me 加油!
/// </summary>
public class AIMonsterFSMSystem {//*************************** 定义一个系统控制类 ***************************
private List<AIMonsterFSM> states;//*************************** 定义一个电脑AI怪物的状态机的数组 ***************************
private AIMonsterEvent currentAIMonsterEvent ;//*************************** 定义一个私有的用于记录电脑AI怪物的当前的执行事件,不要直接修改电脑AI怪物的执行事件 ***************************
public AIMonsterEvent CurrentAIMonsterEvent { get { return currentAIMonsterEvent;} }//*************************** 该属性记录当前怪物的执行事件,用于其他脚本的调用 ***************************
private AIMonsterFSM currentAIMonsterFSM;//*************************** 定义一个私有的用于记录电脑AI怪物的当前的转换规则,不要直接修改电脑AI怪物的转换规则 ***************************
public AIMonsterFSM CurrentAIMonsterFSM{ get { return currentAIMonsterFSM;} }//同上
public AIMonsterFSMSystem()//*************************** 因为该类不继承MonoBehaviour,所以该类只能用构造方法来初始化 ***************************
{
states = new List<AIMonsterFSM>();//*************************** 实例化电脑AI怪物的状态机数组 ***************************
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 电脑AI怪物的有限状态机管理系统模块 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//-------------------------------------------------------------------------------------------- 增加状态转换电脑AI怪物的有限状态机方法作用 --------------------------------------------------------------------------------------------
#region 增加状态转换电脑AI怪物的有限状态机方法作用
/// <summary>
/// 增加状态转换电脑AI怪物的有限状态机方法作用
/// </summary>
/// <param name="AMF">AM.</param>
public void AddState(AIMonsterFSM AMF)//增加状态转换电脑AI怪物的有限状态机
{
if (AMF == null)//@@@@@@@@@ 如果电脑AI怪物的状态机为空 @@@@@@@@@
{
Debug.LogError("AIMonsterFSMSystem ERROR: Null reference is not allowed");//*************************** 输出警告电脑AI怪物的状态为空 ***************************
}
if (states.Count == 0)//@@@@@@@@@ 如果电脑AI怪物的状态机数组的个数为零 @@@@@@@@@
/*第一次添加时必定执行这块代码,因为一开始states是空的,并且这块代码设置了第一次添加的状态是默认的当前状态。这一点读者一定要理解,不然对于后面的东西读者会非常困惑的,因为其他地方没有地方设置运行后默认的当前状态。*/
{
states.Add(AMF);//*************************** 添加当前的电脑AI怪物的状态为当前传入的状态 ***************************
currentAIMonsterFSM = AMF;//*************************** 电脑AI怪物的当前状态为传入的状态 ***************************
currentAIMonsterEvent = AMF.MonsterEvent;//*************************** 实例化当前怪物执行的事件 ***************************
return;//######### 跳出当前的执行,继续运行下面的代码 #########
}
foreach (AIMonsterFSM state in states)//*************************** 遍历排除相同的状态 ***************************
{
if (state.MonsterEvent == AMF.MonsterEvent)//@@@@@@@@@ 如果参数的Foreach执行事件等于传入的电脑AI怪物的执行事件 @@@@@@@@@
{
Debug.LogError("AIMonsterFSMSystem ERROR: Impossible to add state " + AMF.MonsterEvent.ToString() +
" because state has already been added");//*************************** 输出没有添加当前的状态,因为该状态已经被添加过 ***************************
return;//######### 跳出当前的执行,继续运行下面的代码 #########
}
}
states.Add(AMF);//*************************** 这一句代码第一次不执行,因为第一次states是空的,执行到上面的if里面后立即返回了 ***************************
}
#endregion
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 电脑AI怪物有限状态机管理系统模块 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//-------------------------------------------------------------------------------------------- 跟据怪物执行事件MonsterEvent来从容器states中定向移除电脑AI怪物的有限状态机AIMonsterFSM实例方法作用 --------------------------------------------------------------------------------------------
#region 跟据怪物执行事件MonsterEvent来从容器states中定向移除电脑AI怪物的有限状态机AIMonsterFSM实例方法作用
/// <summary>
/// 跟据怪物执行事件MonsterEvent来从容器states中定向移除电脑AI怪物的有限状态机AIMonsterFSM实例方法作用
/// </summary>
/// <param name="AME">AM.</param>
public void DeleteState(AIMonsterEvent AME)//*************************** 跟据怪物执行事件MonsterEvent来从容器states中定向移除电脑AI怪物的有限状态机AIMonsterFSM实例方法作用 ***************************
{
if (AME == AIMonsterEvent.NullAIMonsterEvent)//@@@@@@@@@ 如果传入的当期怪物的执行事件等空 @@@@@@@@@
{
Debug.LogError("AIMonsterFSMSystem ERROR: NullAIMonsterEvent is not allowed for a real state");//*************************** 输出空的执行事件是不被允许的 ***************************
return;//######### 跳出当前的执行,继续运行下面的代码 #########
}
foreach (AIMonsterFSM state in states)//*************************** 遍历当前的电脑AI怪物的有限状态机数组 ***************************
{
if (state.MonsterEvent == AME)//@@@@@@@@@ 如果电脑AI怪物的有限状态机数组中的某一执行事件与当前传入的当期事件相同 @@@@@@@@@
{
states.Remove(state);//*************************** 电脑AI怪物的有限状态机数组移除当前的有限状态机 ***************************
return;//######### 跳出当前的执行,继续运行下面的代码 #########
}
}
Debug.LogError("AIMonsterFSMSystem ERROR: Impossible to delete state " + AME.ToString() + ". It was not on the list of states");//*************************** 不能执行移除,因为当前数组中没有当前的状态 ***************************
}
#endregion
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 电脑AI怪物有限状态机管理系统模块 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//-------------------------------------------------------------------------------------------- 执行规则转换的方法作用 --------------------------------------------------------------------------------------------
public void PerformAIMonsterRule(AIMonsterRule AMR)//
{
if (AMR == AIMonsterRule.NullAIMonsterRule)//@@@@@@@@@ 如果传入的当期怪物的规则等空 @@@@@@@@@
{
Debug.LogError("AIMonsterFSMSystem ERROR: NullAIMonsterRule is not allowed for a real AIMonsterRule");//*************************** 输出空的规则是不被允许作为规则来进行转换的 ***************************
}
AIMonsterEvent aiMonsterEvent = currentAIMonsterFSM.GetOutputState(AMR);////*************************** 如果检索不出来就返回NullAIMonsterEvent,执行下面的If语句 ***************************
if (aiMonsterEvent == AIMonsterEvent.NullAIMonsterEvent)//@@@@@@@@@ 如果电脑AI怪物的执行事件为空事件 @@@@@@@@@
{
Debug.LogError("AIMonsterFSMSystem ERROR: State " + currentAIMonsterEvent.ToString() + " does not have a target state " +
" for AIMonsterRule " + AMR.ToString());//*************************** 状态中的执行事件没有对应的目标规则 ***************************
return;//######### 跳出当前的执行,继续运行下面的代码 #########
}
currentAIMonsterEvent = aiMonsterEvent;//*************************** 如果查到了有这个状态,那么我们就将其赋值给成员变量currentStateID ***************************
foreach (AIMonsterFSM state in states)//*************************** 遍历此状态容器 ***************************
{
if (state.MonsterEvent == currentAIMonsterEvent)//*************************** 如果当前电脑AI怪物有限状态机数组中的某一执行事件与当前电脑AI怪物执行的事件相同 ***************************
{
currentAIMonsterFSM.DoBeforeLeaving();//*************************** 我们在转换之前或许要做点什么吧!,所以我们如有需要,得在AIMonsterFSM实现类中覆写一下这个方法 ***************************
currentAIMonsterFSM = state;////*************************** 电脑AI怪物当前执行的状态机为当前执行的有限状态机的数组中的状态机 ***************************
currentAIMonsterFSM.DoBeforeEntering();//*************************** 状态转换完成之后,有可能得先为新状态做点事吧,那么我们也得DoBeforeEntering函数 ***************************
break;//######### 循环中使用break,跳出当前的执行 #########
}
}
}
}
可以结合这个图来看状态的转换
③这是电脑AI石头怪物控制脚本, 里面最主要的是制作一个状态机那部分
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
/// <summary>
/// 功能:电脑AI石头怪物的控制脚本
/// 创建者: VioletTD
/// 修改时间: 2015年11月13日 21:59
/// 感谢: Me 加油!
/// </summary>
public class AIStoneMonsterController : AIMonsterTools {
#region AIStoneMonsterController的单例
private static AIStoneMonsterController _instance;//*************************** 定义静态的泛型<T>的类型的变量 _instance ***************************
private static object _lock = new object();//*************************** 定义一个静态的objec类型的_lock并实例化 ***************************
private static bool applicationIsQuitting = false;//*************************** 定义bool类型的变量applicationIsQuitting 判断程序是否关闭 ***************************
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 单例模块 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//-------------------------------------------------------------------------------------------- 定义静态的类型的属性 --------------------------------------------------------------------------------------------
public static AIStoneMonsterController Instance
{
get//@@@@@@@@@ get方法 @@@@@@@@@
{
if(applicationIsQuitting)//@@@@@@@@@ 如果applicationIsQuitting为真 则返回null 以下的代码不执行 @@@@@@@@@
{
return null;
}
lock(_lock)//@@@@@@@@@ lock 关键字可以用来确保代码块完成运行,而不会被其他线程中断 @@@@@@@@@
{
if(null == _instance)//@@@@@@@@@ 如果_instance等于空 执行一下代码 @@@@@@@@@
{
_instance = (AIStoneMonsterController)FindObjectOfType (typeof(AIStoneMonsterController));//*************************** _instance找到类型为泛型<T>(也就是想要定义为单例的脚本) ***************************
if (FindObjectsOfType (typeof(AIStoneMonsterController)).Length > 1) //@@@@@@@@@ 如果_instance找到的长度大于 @@@@@@@@@
{
return _instance;//######### 返回_instance 保证单例的唯一性 #########
}
if(null == _instance) //@@@@@@@@@ 如果_instance等于空 @@@@@@@@@
{
GameObject singleton = new GameObject ();//*************************** 实例化出一个GameObject类型的singleton(单例) ***************************
_instance = singleton.AddComponent<AIStoneMonsterController>();//*************************** 把GameObject类型的对象singleton添加上泛型<T>(想要定义为单例的脚本)组件(脚本) ***************************
singleton.name = "(singleton)" + typeof(AIStoneMonsterController).ToString ();//*************************** 名字为...... ***************************
DontDestroyOnLoad (singleton);//*************************** 切换场景后保留singleton 保持单例在场景中的传递,用于存储一些小型的数据 ***************************
}
}
return _instance;//######### 返回出_instance单例 #########
}
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 单例模块 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//-------------------------------------------------------------------------------------------- 回调方法OnDestroy 用于清除定义的单例 --------------------------------------------------------------------------------------------
public void OnDestroy()
{
applicationIsQuitting = true;//*************************** 设置applicationIsQuitting 为真 ***************************
}
#endregion
[HideInInspector]
public Animator aiStoneMonster_Animator;//*************************** 新动画的管理器 用于获取电脑AI石头的新动画组件 ***************************
public AIStoneMonsterModel aiStoneMonster_Model;//*************************** 电脑AI石头怪物的Model类 ***************************
public Transform aiStoneMonster_Slider_Position;//*************************** 头顶的点,血条的位置,这个点,可以是空物体,也可以通过计算得到 ***************************
private GameObject aiStoneMonster_Slider_Prefab;//*************************** 电脑AI石头怪物的血条预制体 ***************************
public GameObject AIStoneMonster_Weapon;//*************************** 电脑AI石头怪物的武器 ***************************
private bool didSliderNeedShow;//*************************** 血条是否需要显示 ***************************
private float distance;//*************************** 用于滑动器缩放的距离计算 ***************************
private float scale;//*************************** 用于计算滑动器缩放的比例 ***************************
private float timerSceond;//*************************** 一秒的计时 ***************************
public GameObject player;//*************************** 用于找到主角的预制体 ***************************
public Transform[] paths;//*************************** 用于多个巡逻的路点 ***************************
private AIMonsterFSMSystem aiMonsterFSMSystem;//*************************** 自己编写的电脑AI石头怪物的有限状态机的管理系统 ***************************
void Awake()
{
_instance = this;//*************************** 单例的调用 ***************************
aiStoneMonster_Model.AIStoneMonster_Attribute_Model = All_Attribute.Earth;//*************************** 电脑AI石头怪物的属性为地属性 ***************************
aiStoneMonster_Model.AIStoneMonster_Character_Type_Model = Character_Type.Strength;//*************************** 电脑AI石头怪物为力量型 ***************************
aiStoneMonster_Model.AIStoneMonster_SortGrade_Model = Monster_SortGrade.primary;//*************************** 电脑AI石头怪物的世界等级为初级的 ***************************
AIStoneMonster_Grade_Controller();//*************************** 调用本类电脑AI石头怪物不同等级的属性的变化的方法,初始化属性 ***************************
aiStoneMonster_Model.AIStoneMonster_AttackRange_Model = 0.2f;//*************************** 电脑AI石头怪物的攻击距离 ***************************
aiStoneMonster_Model.AIStoneMonster_XP_Model = 100f;//*************************** 电脑AI石头怪物的最满XP为一百 ***************************
aiStoneMonster_Model.AIStoneMonster_CurrentXP_Model = 0f;//*************************** 初始化电脑AI石头怪物的当前XP为零 ***************************
timerSceond = 1f;//*************************** 初始化每秒的计时 ***************************
didSliderNeedShow = true;//*************************** 血条初始需要显示 ***************************
aiStoneMonster_Slider_Prefab = Instantiate(Resources.Load ("SliderPrefabs/AIMonsterSliderPrefabs")) as GameObject;//*************************** 用资源查找的方法找到电脑AI石头怪物的血条预制体 ***************************
distance = Vector3.Distance (aiStoneMonster_Slider_Position.position,Camera.main.transform.position);//*************************** 记录初始的距离为电脑AI石头怪物头顶血条位置到摄像机的位置 ***************************
aiStoneMonster_Animator = GetComponent<Animator>();//*************************** 获取电脑AI怪物的动画组件 ***************************
}
void Start()
{
MakeFSM();//*************************** 首先初始化状态机,执行MakeFSM函数 ***************************
EventDelegate.Add (aiStoneMonster_Slider_Prefab.transform.GetChild(0).gameObject.GetComponent<UISlider>().onChange,AIStoneMonster_HPChange_Controller);//*************************** NGUI委托事件添加血条改变的方法 ***************************
EventDelegate.Add (aiStoneMonster_Slider_Prefab.transform.GetChild(1).gameObject.GetComponent<UISlider>().onChange,AIStoneMonster_MPChange_Controller);//*************************** NGUI委托事件添加魔法条改变的方法 ***************************
EventDelegate.Add (aiStoneMonster_Slider_Prefab.transform.GetChild(2).gameObject.GetComponent<UISlider>().onChange,AIStoneMonster_XPChange_Controller);//*************************** NGUI委托事件添加特殊技能条改变的方法 ***************************
}
void FixedUpdate()//*************************** 作为驱动源 ***************************
{
aiMonsterFSMSystem.CurrentAIMonsterFSM.Change_Rule(player, gameObject);//*************************** 定期用以检测外界环境是否发生变化,根据发生的事情转换规则来执行某些事件 ***************************
aiMonsterFSMSystem.CurrentAIMonsterFSM.Execute_Event(player, gameObject);//*************************** 定期执行当前状态下的某些事件 ***************************
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 电脑AI石头石头怪物规矩模块 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//-------------------------------------------------------------------------------------------- 制作一个状态机方法作用 --------------------------------------------------------------------------------------------
#region 制作一个状态机方法作用
/// <summary>
/// 制作一个状态机方法作用
/// </summary>
private void MakeFSM()
{
AIMonsterPatrolState aiMonsterPatrolState = new AIMonsterPatrolState(paths);//*************************** 定义并实例化巡逻状态 ***************************
aiMonsterPatrolState.AddAIMonsterRuleAndEvent(AIMonsterRule.AIMonsterFindTargetRule, AIMonsterEvent.AIMonsterChaseEvent);//*************************** (可以转换的状态)向其添加转换对,找到目标(规则),追逐事件(事件) ***************************
aiMonsterPatrolState.AddAIMonsterRuleAndEvent (AIMonsterRule.AIMonsterHPLackRule,AIMonsterEvent.AIMonsterEscapeEvent);//*************************** (可以转换的状态)向其添加转换对,血量缺少(规则),逃跑事件(事件) ***************************
aiMonsterPatrolState.AddAIMonsterRuleAndEvent (AIMonsterRule.AIMonsterATKRangeRule,AIMonsterEvent.AIMonsterATKEvent);//*************************** (可以转换的状态)向其添加转换对,在攻击距离(规则),攻击事件(事件) ***************************
AIMonsterChaseState aiMonsterChaseState = new AIMonsterChaseState();//*************************** 定义并实例化追逐状态 ***************************
aiMonsterChaseState.AddAIMonsterRuleAndEvent(AIMonsterRule.AIMonsterLostTargetRule,AIMonsterEvent.AIMonsterPatrolEvent);//*************************** (可以转换的状态)向其添加转换对,失去目标(规则),巡逻事件(事件) ***************************
aiMonsterChaseState.AddAIMonsterRuleAndEvent (AIMonsterRule.AIMonsterHPLackRule,AIMonsterEvent.AIMonsterEscapeEvent);//*************************** (可以转换的状态)向其添加转换对,血量缺少(规则),逃跑事件(事件) ***************************
aiMonsterChaseState.AddAIMonsterRuleAndEvent (AIMonsterRule.AIMonsterATKRangeRule,AIMonsterEvent.AIMonsterATKEvent);//*************************** (可以转换的状态)向其添加转换对,在攻击距离(规则),攻击事件(事件) ***************************
AIMonsterEscapeState aiMonsterEscapeState = new AIMonsterEscapeState();//*************************** 定义并实例化逃跑状态 ***************************
aiMonsterEscapeState.AddAIMonsterRuleAndEvent (AIMonsterRule.AIMonsterHPEnoughRule,AIMonsterEvent.AIMonsterPatrolEvent);//*************************** (可以转换的状态)向其添加转换对,血量充足(规则),追逐事件(事件) ***************************
AIMonsterAttackState aiMonsterAttackState = new AIMonsterAttackState();//*************************** 定义并实例化攻击状态 ***************************
aiMonsterAttackState.AddAIMonsterRuleAndEvent (AIMonsterRule.AIMonsterFindTargetRule,AIMonsterEvent.AIMonsterChaseEvent);//*************************** (可以转换的状态)向其添加转换对,找到目标(规则),追逐事件(事件) ***************************
aiMonsterAttackState.AddAIMonsterRuleAndEvent(AIMonsterRule.AIMonsterHPLackRule,AIMonsterEvent.AIMonsterEscapeEvent);//*************************** (可以转换的状态)向其添加转换对,血量缺少(规则),逃跑事件(事件) ***************************
aiMonsterAttackState.AddAIMonsterRuleAndEvent (AIMonsterRule.AIMonsterMPEnoughRule,AIMonsterEvent.AIMonsterSkillEvent);//*************************** (可以转换的状态)向其添加转换对,魔法充足(规则),释放魔法事件(事件) ***************************
aiMonsterAttackState.AddAIMonsterRuleAndEvent (AIMonsterRule.AIMonsterXPEnoughRule,AIMonsterEvent.AIMonsterXPSkillEvent);//*************************** (可以转换的状态)向其添加转换对,特殊技能值充足(规则),释放特殊技能事件(事件) ***************************
AIMonsterReleaseMPSkillState aiMonsterReleaseMPSkillState = new AIMonsterReleaseMPSkillState();//*************************** 定义并实例化释放魔法状态 ***************************
aiMonsterReleaseMPSkillState.AddAIMonsterRuleAndEvent(AIMonsterRule.AIMonsterMPLackRule,AIMonsterEvent.AIMonsterATKEvent);//*************************** (可以转换的状态)向其添加转换对,魔法不足(规则),攻击事件(事件) ***************************
AIMonsterReleaseXPSkillState aiMonsterReleaseXPSkillState = new AIMonsterReleaseXPSkillState();//*************************** 定义并实例化释放特殊技能状态 ***************************
aiMonsterReleaseXPSkillState.AddAIMonsterRuleAndEvent (AIMonsterRule.AIMonsterXPLackRule,AIMonsterEvent.AIMonsterATKEvent);//*************************** (可以转换的状态)向其添加转换对,特殊技能值不足(规则),攻击事件(事件) ***************************
aiMonsterFSMSystem = new AIMonsterFSMSystem();//*************************** 实例化有限状态机的管理系统 ***************************
aiMonsterFSMSystem.AddState(aiMonsterPatrolState);//将巡逻状态装载到有限状态机的管理系统中
aiMonsterFSMSystem.AddState(aiMonsterChaseState);//将追逐状态装载到有限状态机的管理系统中
aiMonsterFSMSystem.AddState (aiMonsterEscapeState);//将逃跑状态装载到有限状态机的管理系统中
aiMonsterFSMSystem.AddState (aiMonsterAttackState);//将攻击状态装载到有限状态机的管理系统中
aiMonsterFSMSystem.AddState(aiMonsterReleaseMPSkillState);//将释放魔法状态装载到有限状态机的管理系统中
aiMonsterFSMSystem.AddState (aiMonsterReleaseXPSkillState);//将释放特殊技能状态装载到有限状态机的管理系统中
}
#endregion
void Update()
{
base.AIMonster_HPShow_Tools(scale,distance,aiStoneMonster_Slider_Position,aiStoneMonster_Slider_Prefab.transform,didSliderNeedShow);//*************************** 调用父级的血条显示和跟随的方法 ***************************
AIStoneMonster_HPChange_Controller();//*************************** 调用本身的血条改变显示方法 ***************************
AIStoneMonster_MPChange_Controller();//*************************** 调用本身的魔法条改变显示方法 ***************************
AIStoneMonster_XPChange_Controller();//*************************** 调用本身的特殊技能条改变显示方法 ***************************
AIStoneMonster_Destroy_Controller ();//*************************** 调用本身的死亡归零方法 ***************************
if (timerSceond >= 0) //@@@@@@@@@ 如果计时大于等于零 @@@@@@@@@
{
timerSceond -= Time.deltaTime;//*************************** 计时持续减去每帧的时间 ***************************
}
else//@@@@@@@@@ 如果计时小于零 @@@@@@@@@
{
aiStoneMonster_Model.Monster_CurrentMP_Model += 0.3f;//*************************** 电脑AI石头怪物的当前魔法值每秒增长二 ***************************
aiStoneMonster_Model.AIStoneMonster_CurrentXP_Model += 1f;//*************************** 电脑AI石头怪物的当期特殊技能值每秒增长一 ***************************
timerSceond = 1f;//*************************** 计时归零 ***************************
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 电脑AI石头怪物的血量模块 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//-------------------------------------------------------------------------------------------- 电脑AI石头怪物的血量改变显示方法作用 --------------------------------------------------------------------------------------------
void AIStoneMonster_HPChange_Controller()
{
aiStoneMonster_Slider_Prefab.transform.GetChild(0).gameObject.GetComponent<UISlider>().value =
aiStoneMonster_Model.Monster_CurrentHP_Model/aiStoneMonster_Model.Monster_HP_Model;//*************************** 电脑AI石头怪物的血条显示等于当前血量比上总血量 ***************************
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 电脑AI石头怪物的魔法量模块 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//-------------------------------------------------------------------------------------------- 电脑AI石头怪物的魔法量改变显示方法作用 --------------------------------------------------------------------------------------------
void AIStoneMonster_MPChange_Controller()
{
aiStoneMonster_Slider_Prefab.transform.GetChild(1).gameObject.GetComponent<UISlider>().value =
aiStoneMonster_Model.Monster_CurrentMP_Model/aiStoneMonster_Model.Monster_MP_Model;//*************************** 电脑AI石头怪物的血条显示等于当前血量比上总血量 ***************************
if (aiStoneMonster_Model.Monster_CurrentMP_Model >= aiStoneMonster_Model.Monster_MP_Model) //@@@@@@@@@ 如果电脑AI怪物的当前魔法值大于等于总魔法值 @@@@@@@@@
{
aiStoneMonster_Model.Monster_CurrentMP_Model = aiStoneMonster_Model.Monster_MP_Model;//*************************** 电脑AI怪物的当前魔法值等于总魔法值 ***************************
}
if (aiStoneMonster_Model.Monster_CurrentMP_Model <= 0) {//@@@@@@@@@ 当前魔法值小于等于零 @@@@@@@@@
aiStoneMonster_Model.Monster_CurrentMP_Model = 0;//*************************** 当前魔法值等于零 ***************************
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 电脑AI石头怪物的特殊技能值模块 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//-------------------------------------------------------------------------------------------- 电脑AI石头怪物的特殊技能值改变显示方法作用 --------------------------------------------------------------------------------------------
void AIStoneMonster_XPChange_Controller()
{
aiStoneMonster_Slider_Prefab.transform.GetChild(2).gameObject.GetComponent<UISlider>().value =
aiStoneMonster_Model.AIStoneMonster_CurrentXP_Model/aiStoneMonster_Model.AIStoneMonster_XP_Model;//*************************** 电脑AI石头怪物的血条显示等于当前血量比上总血量 ***************************
if (aiStoneMonster_Model.AIStoneMonster_CurrentXP_Model >= aiStoneMonster_Model.AIStoneMonster_XP_Model) //@@@@@@@@@ 如果电脑AI怪物的当前特殊技能值大于等于总魔法值 @@@@@@@@@
{
aiStoneMonster_Model.AIStoneMonster_CurrentXP_Model = aiStoneMonster_Model.AIStoneMonster_XP_Model;//*************************** 电脑AI怪物的当前特殊技能值等于总魔法值 ***************************
}
if (aiStoneMonster_Model.AIStoneMonster_CurrentXP_Model <= 0) {//@@@@@@@@@ 当前特殊技能值小于等于零 @@@@@@@@@
aiStoneMonster_Model.AIStoneMonster_CurrentXP_Model = 0;//*************************** 当前特殊技能值等于零 ***************************
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 电脑AI石头怪物规矩模块 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//-------------------------------------------------------------------------------------------- 执行转换电脑AI石头石头怪物的执行规则转换方法作用 --------------------------------------------------------------------------------------------
#region 执行转换电脑AI石头怪物的执行规则转换方法作用
/// <summary>
/// 执行转换电脑AI石头怪物的执行规则转换方法作用
/// </summary>
/// <param name="AMR">AM.</param>
public void AIMonster_SetAIMonsterRule_Controller(AIMonsterRule AMR) //执行规则转换状态
{
aiMonsterFSMSystem.PerformAIMonsterRule(AMR);//*************************** 调用电脑AI石头怪物的有限状态机的管理系统传入转换规则 ***************************
}
#endregion
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 近战对象的攻击模块 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//-------------------------------------------------------------------------------------------- 在动画时间中某一帧调用设置触发组件开启方法作用 --------------------------------------------------------------------------------------------
void AIStoneMonster_WeaponTrue_Controller(Object w)
{
AIStoneMonster_Weapon.GetComponent<BoxCollider>().enabled =true;//*************************** 最开始是关闭的状态,设置触发组件开启 ***************************
w = AIStoneMonster_Weapon;//*************************** 用外部Object接收GameObject类型的游戏对象,内外的双传递(即在外部选中,go查找的游戏对象) ***************************
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 近战对象的攻击模块 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//-------------------------------------------------------------------------------------------- 在动画时间中某一帧调用设置触发组件关闭方法作用 --------------------------------------------------------------------------------------------
void AIStoneMonster_WeaponFalse_Controller(Object b)
{
AIStoneMonster_Weapon.GetComponent<BoxCollider>().enabled = false;//*************************** 最开始是关闭的状态,设置触发组件开启 ***************************
b = AIStoneMonster_Weapon;//*************************** 用外部Object接收GameObject类型的游戏对象,内外的双传递(即在外部选中,go查找的游戏对象) ***************************
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 释放魔法模块 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//-------------------------------------------------------------------------------------------- 释放魔法的方法作用 --------------------------------------------------------------------------------------------
public void AIStoneMonster_Skill_Controller()
{
aiStoneMonster_Model.Monster_CurrentMP_Model -= 10f;//*************************** 电脑AI石头怪物魔法值消耗十 ***************************
aiStoneMonster_Model.Monster_DEF_Model = aiStoneMonster_Model.Monster_STR_Model *1.2f;//*************************** 电脑AI石头怪物防御力加倍 ***************************
print ("电脑AI石头怪物的防御力:" + aiStoneMonster_Model.Monster_DEF_Model);//*************************** 用于检测输出当前的防御力 ***************************
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 释放特殊技能模块 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//-------------------------------------------------------------------------------------------- 释放特殊技能的方法作用 --------------------------------------------------------------------------------------------
public void AIStoneMonster_XPSkill_Controller()
{
aiStoneMonster_Model.AIStoneMonster_CurrentXP_Model -= 100f;//*************************** 电脑AI石头怪物魔法值消耗十 ***************************
aiStoneMonster_Model.Monster_ATK_Model = (aiStoneMonster_Model.Monster_STR_Model * 1.7f + aiStoneMonster_Model.Monster_SPD_Model * 0.5f) * 1.5f;//*************************** 电脑AI石头怪物攻击加一点五倍 ***************************
print ("电脑AI石头怪物的攻击力:" + aiStoneMonster_Model.Monster_ATK_Model);//*************************** 用于检测输出当前的防御力 ***************************
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 电脑AI石头怪物的死亡模块 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//-------------------------------------------------------------------------------------------- 电脑AI石头怪物死亡后的归零方法作用 --------------------------------------------------------------------------------------------
public void AIStoneMonster_Destroy_Controller()
{
if (aiStoneMonster_Model.Monster_CurrentHP_Model <= 0) //@@@@@@@@@ 如果电脑AI石头怪物的当前血量小于等于零 @@@@@@@@@
{
aiStoneMonster_Model.Monster_CurrentHP_Model = 0;//*************************** 电脑AI石头怪物的当前血量为零 ***************************
Destroy (gameObject);//*************************** 销毁自己 ***************************
Destroy(aiStoneMonster_Slider_Prefab);//*************************** 销毁自己血条 ***************************
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 电脑AI石头怪物的等级提升模块 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//-------------------------------------------------------------------------------------------- 电脑AI石头怪物不同等级的属性的变化的方法 --------------------------------------------------------------------------------------------
void AIStoneMonster_Grade_Controller()
{
switch (AIStoneMonsterModel.AIStoneMonster_Grade_Model) {//@@@@@@@@@ 判断全局的怪物二的等级 @@@@@@@@@
case MonsterGrade.Zero://@@@@@@@@@ 如果是零级 @@@@@@@@@
{
aiStoneMonster_Model.Monster_STR_Model = 23.5f;//*************************** 电脑AI石头怪物的力量为二十 ***************************
aiStoneMonster_Model.Monster_HP_Model =
aiStoneMonster_Model.Monster_STR_Model * 10f + aiStoneMonster_Model.Monster_SPD_Model * 2f + aiStoneMonster_Model.Monster_VIS_Model * 1f;//*************************** 电脑AI石头怪物的血量等于力量乘十加敏捷乘二加智力乘一 ***************************
aiStoneMonster_Model.Monster_CurrentHP_Model =aiStoneMonster_Model.Monster_HP_Model;//*************************** 电脑AI石头怪物的当前血量 ***************************
aiStoneMonster_Model.Monster_ATK_Model = aiStoneMonster_Model.Monster_STR_Model * 1.7f + aiStoneMonster_Model.Monster_SPD_Model * 0.5f;//*************************** 电脑AI石头怪物的攻击力力量乘一点七加敏捷乘零点五 ***************************
aiStoneMonster_Model.Monster_DEF_Model = aiStoneMonster_Model.Monster_STR_Model * 0.8f;//*************************** 电脑AI石头怪物的防御力等于力量乘二 ***************************
aiStoneMonster_Model.Monster_DEX_Model = 13f;//*************************** 电脑AI石头怪物的敏捷为十三 ***************************
aiStoneMonster_Model.Monster_SPD_Model = aiStoneMonster_Model.Monster_DEX_Model * 0.1f - aiStoneMonster_Model.Monster_STR_Model * 0.05f;//*************************** 电脑AI石头怪物的速度为敏捷乘零点一减去力量乘零点零三 ***************************
aiStoneMonster_Model.Monster_CRT_Model = (aiStoneMonster_Model.Monster_DEX_Model + aiStoneMonster_Model.Monster_STR_Model * 0.4f) * 0.01f;//*************************** 电脑AI石头怪物的暴击为敏捷加上力量乘零点四的和换算为百分比 ***************************
aiStoneMonster_Model.Monster_ASD_Model = aiStoneMonster_Model.Monster_DEX_Model * 0.05f + aiStoneMonster_Model.Monster_STR_Model * 0.02f;//*************************** 电脑AI石头怪物的攻速为敏捷乘零点五加上力量乘零点二的和 ***************************
aiStoneMonster_Model.Monster_VIS_Model = 5f;//*************************** 电脑AI石头怪物的智力为五 ***************************
aiStoneMonster_Model.Monster_MP_Model =aiStoneMonster_Model.Monster_VIS_Model * 4f;//*************************** 电脑AI石头怪物的魔法值为智力乘四 ***************************
aiStoneMonster_Model.Monster_CurrentMP_Model = 0;//*************************** 电脑AI石头怪物的当前魔法值 ***************************
aiStoneMonster_Model.Monster_INT_Model = aiStoneMonster_Model.Monster_VIS_Model * 0.6f;//*************************** 电脑AI石头怪物的魔法攻击力为智力乘以零点六 ***************************
aiStoneMonster_Model.Monster_FCR_Model = 1/aiStoneMonster_Model.Monster_VIS_Model * 0.2f;//*************************** 电脑AI石头怪物的施法时间魔法值乘0.2取反 ******************
aiStoneMonster_Model.Monster_FCRTimer_Model = aiStoneMonster_Model.Monster_FCR_Model;//*************************** 电脑AI石头怪物的当前施法时间的计时器 ******************
aiStoneMonster_Model.Monster_NeedAP_Model = 50f;//*************************** 强化电脑AI石头怪物所需的强化值为五十 ******************
aiStoneMonster_Model.Monster_APNeedTime_Model = 10f;//*************************** 强化电脑AI石头怪物所需的时间为十 ******************
GetComponent<NavMeshAgent>().speed = aiStoneMonster_Model.Monster_SPD_Model;//*************************** 设置寻路组件的速度为电脑AI石头怪物的速度值 ***************************
break;
}
case MonsterGrade.Primary://@@@@@@@@@ 如果是初级 @@@@@@@@@
{
aiStoneMonster_Model.Monster_STR_Model = 32f;//*************************** 电脑AI石头怪物的力量为二十 ***************************
aiStoneMonster_Model.Monster_HP_Model =
aiStoneMonster_Model.Monster_STR_Model * 10f + aiStoneMonster_Model.Monster_SPD_Model * 2f + aiStoneMonster_Model.Monster_VIS_Model * 1f;//*************************** 电脑AI石头怪物的血量等于力量乘十加敏捷乘二加智力乘一 ***************************
aiStoneMonster_Model.Monster_CurrentHP_Model =aiStoneMonster_Model.Monster_HP_Model;//*************************** 电脑AI石头怪物的当前血量 ***************************
aiStoneMonster_Model.Monster_ATK_Model = aiStoneMonster_Model.Monster_STR_Model * 1.7f + aiStoneMonster_Model.Monster_SPD_Model * 0.5f;//*************************** 电脑AI石头怪物的攻击力力量乘一点七加敏捷乘零点五 ***************************
aiStoneMonster_Model.Monster_DEF_Model = aiStoneMonster_Model.Monster_STR_Model * 0.9f;//*************************** 电脑AI石头怪物的防御力等于力量乘二 ***************************
aiStoneMonster_Model.Monster_DEX_Model = 20f;//*************************** 电脑AI石头怪物的敏捷为十三 ***************************
aiStoneMonster_Model.Monster_SPD_Model = aiStoneMonster_Model.Monster_DEX_Model * 0.1f - aiStoneMonster_Model.Monster_STR_Model * 0.05f;//*************************** 电脑AI石头怪物的速度为敏捷乘零点一减去力量乘零点零三 ***************************
aiStoneMonster_Model.Monster_CRT_Model = (aiStoneMonster_Model.Monster_DEX_Model + aiStoneMonster_Model.Monster_STR_Model * 0.4f) * 0.01f;//*************************** 电脑AI石头怪物的暴击为敏捷加上力量乘零点四的和换算为百分比 ***************************
aiStoneMonster_Model.Monster_ASD_Model = aiStoneMonster_Model.Monster_DEX_Model * 0.05f + aiStoneMonster_Model.Monster_STR_Model * 0.02f;//*************************** 电脑AI石头怪物的攻速为敏捷乘零点五加上力量乘零点二的和 ***************************
aiStoneMonster_Model.Monster_VIS_Model = 8f;//*************************** 电脑AI石头怪物的智力为五 ***************************
aiStoneMonster_Model.Monster_MP_Model =aiStoneMonster_Model.Monster_VIS_Model * 4f;//*************************** 电脑AI石头怪物的魔法值为智力乘四 ***************************
aiStoneMonster_Model.Monster_INT_Model = aiStoneMonster_Model.Monster_VIS_Model * 0.6f;//*************************** 电脑AI石头怪物的魔法攻击力为智力乘以零点六 ***************************
aiStoneMonster_Model.Monster_FCR_Model = 1/aiStoneMonster_Model.Monster_VIS_Model * 0.2f;//*************************** 电脑AI石头怪物的施法时间魔法值乘0.2取反 ******************
aiStoneMonster_Model.Monster_FCRTimer_Model = aiStoneMonster_Model.Monster_FCR_Model;//*************************** 电脑AI石头怪物的当前施法时间的计时器 ******************
aiStoneMonster_Model.Monster_NeedAP_Model = 60f;//*************************** 强化电脑AI石头怪物所需的强化值为六十 ******************
aiStoneMonster_Model.Monster_APNeedTime_Model = 12f;//*************************** 强化电脑AI石头怪物所需的时间为十二 ******************
GetComponent<NavMeshAgent>().speed = aiStoneMonster_Model.Monster_SPD_Model;//*************************** 设置寻路组件的速度为电脑AI石头怪物的速度值 ***************************
break;
}
case MonsterGrade.Middle://@@@@@@@@@ 如果是中级 @@@@@@@@@
{
aiStoneMonster_Model.Monster_STR_Model = 45f;//*************************** 电脑AI石头怪物的力量为二十 ***************************
aiStoneMonster_Model.Monster_HP_Model =
aiStoneMonster_Model.Monster_STR_Model * 10f + aiStoneMonster_Model.Monster_SPD_Model * 2f + aiStoneMonster_Model.Monster_VIS_Model * 1f;//*************************** 电脑AI石头怪物的血量等于力量乘十加敏捷乘二加智力乘一 ***************************
aiStoneMonster_Model.Monster_CurrentHP_Model =aiStoneMonster_Model.Monster_HP_Model;//*************************** 电脑AI石头怪物的当前血量 ***************************
aiStoneMonster_Model.Monster_ATK_Model = aiStoneMonster_Model.Monster_STR_Model * 1.7f + aiStoneMonster_Model.Monster_SPD_Model * 0.5f;//*************************** 电脑AI石头怪物的攻击力力量乘一点七加敏捷乘零点五 ***************************
aiStoneMonster_Model.Monster_DEF_Model = aiStoneMonster_Model.Monster_STR_Model * 1f;//*************************** 电脑AI石头怪物的防御力等于力量乘二 ***************************
aiStoneMonster_Model.Monster_DEX_Model = 26f;//*************************** 电脑AI石头怪物的敏捷为十三 ***************************
aiStoneMonster_Model.Monster_SPD_Model = aiStoneMonster_Model.Monster_DEX_Model * 0.1f - aiStoneMonster_Model.Monster_STR_Model * 0.05f;//*************************** 电脑AI石头怪物的速度为敏捷乘零点一减去力量乘零点零三 ***************************
aiStoneMonster_Model.Monster_CRT_Model = (aiStoneMonster_Model.Monster_DEX_Model + aiStoneMonster_Model.Monster_STR_Model * 0.4f) * 0.01f;//*************************** 电脑AI石头怪物的暴击为敏捷加上力量乘零点四的和换算为百分比 ***************************
aiStoneMonster_Model.Monster_ASD_Model = aiStoneMonster_Model.Monster_DEX_Model * 0.05f + aiStoneMonster_Model.Monster_STR_Model * 0.02f;//*************************** 电脑AI石头怪物的攻速为敏捷乘零点五加上力量乘零点二的和 ***************************
aiStoneMonster_Model.Monster_VIS_Model = 17f;//*************************** 电脑AI石头怪物的智力为五 ***************************
aiStoneMonster_Model.Monster_MP_Model =aiStoneMonster_Model.Monster_VIS_Model * 4f;//*************************** 电脑AI石头怪物的魔法值为智力乘四 ***************************
aiStoneMonster_Model.Monster_INT_Model = aiStoneMonster_Model.Monster_VIS_Model * 0.6f;//*************************** 电脑AI石头怪物的魔法攻击力为智力乘以零点六 ***************************
aiStoneMonster_Model.Monster_FCR_Model = 1/aiStoneMonster_Model.Monster_VIS_Model * 0.2f;//*************************** 电脑AI石头怪物的施法时间魔法值乘0.2取反 ******************
aiStoneMonster_Model.Monster_FCRTimer_Model = aiStoneMonster_Model.Monster_FCR_Model;//*************************** 电脑AI石头怪物的当前施法时间的计时器 ******************
aiStoneMonster_Model.Monster_NeedAP_Model = 70f;//*************************** 强化电脑AI石头怪物所需的强化值为七十 ******************
aiStoneMonster_Model.Monster_APNeedTime_Model = 15f;//*************************** 强化电脑AI石头怪物所需的时间为十五 ******************
GetComponent<NavMeshAgent>().speed = aiStoneMonster_Model.Monster_SPD_Model;//*************************** 设置寻路组件的速度为电脑AI石头怪物的速度值 ***************************
break;
}
case MonsterGrade.advance://@@@@@@@@@ 如果是高级 @@@@@@@@@
{
aiStoneMonster_Model.Monster_STR_Model = 56f;//*************************** 电脑AI石头怪物的力量为二十 ***************************
aiStoneMonster_Model.Monster_HP_Model =
aiStoneMonster_Model.Monster_STR_Model * 10f + aiStoneMonster_Model.Monster_SPD_Model * 2f + aiStoneMonster_Model.Monster_VIS_Model * 1f;//*************************** 电脑AI石头怪物的血量等于力量乘十加敏捷乘二加智力乘一 ***************************
aiStoneMonster_Model.Monster_CurrentHP_Model =aiStoneMonster_Model.Monster_HP_Model;//*************************** 电脑AI石头怪物的当前血量 ***************************
aiStoneMonster_Model.Monster_ATK_Model = aiStoneMonster_Model.Monster_STR_Model * 1.7f + aiStoneMonster_Model.Monster_SPD_Model * 0.5f;//*************************** 电脑AI石头怪物的攻击力力量乘一点七加敏捷乘零点五 ***************************
aiStoneMonster_Model.Monster_DEF_Model = aiStoneMonster_Model.Monster_STR_Model * 1.2f;//*************************** 电脑AI石头怪物的防御力等于力量乘二 ***************************
aiStoneMonster_Model.Monster_DEX_Model = 30f;//*************************** 电脑AI石头怪物的敏捷为十三 ***************************
aiStoneMonster_Model.Monster_SPD_Model = aiStoneMonster_Model.Monster_DEX_Model * 0.1f - aiStoneMonster_Model.Monster_STR_Model * 0.05f;//*************************** 电脑AI石头怪物的速度为敏捷乘零点一减去力量乘零点零三 ***************************
aiStoneMonster_Model.Monster_CRT_Model = (aiStoneMonster_Model.Monster_DEX_Model + aiStoneMonster_Model.Monster_STR_Model * 0.4f) * 0.01f;//*************************** 电脑AI石头怪物的暴击为敏捷加上力量乘零点四的和换算为百分比 ***************************
aiStoneMonster_Model.Monster_ASD_Model = aiStoneMonster_Model.Monster_DEX_Model * 0.05f + aiStoneMonster_Model.Monster_STR_Model * 0.02f;//*************************** 电脑AI石头怪物的攻速为敏捷乘零点五加上力量乘零点二的和 ***************************
aiStoneMonster_Model.Monster_VIS_Model = 20f;//*************************** 电脑AI石头怪物的智力为五 ***************************
aiStoneMonster_Model.Monster_MP_Model =aiStoneMonster_Model.Monster_VIS_Model * 4f;//*************************** 电脑AI石头怪物的魔法值为智力乘四 ***************************
aiStoneMonster_Model.Monster_INT_Model = aiStoneMonster_Model.Monster_VIS_Model * 0.6f;//*************************** 电脑AI石头怪物的魔法攻击力为智力乘以零点六 ***************************
aiStoneMonster_Model.Monster_FCR_Model = 1/aiStoneMonster_Model.Monster_VIS_Model * 0.2f;//*************************** 电脑AI石头怪物的施法时间魔法值乘0.2取反 ******************
aiStoneMonster_Model.Monster_FCRTimer_Model = aiStoneMonster_Model.Monster_FCR_Model;//*************************** 电脑AI石头怪物的当前施法时间的计时器 ******************
aiStoneMonster_Model.Monster_NeedAP_Model = 80f;//*************************** 强化电脑AI石头怪物所需的强化值为八十 ******************
aiStoneMonster_Model.Monster_APNeedTime_Model = 20f;//*************************** 强化电脑AI石头怪物所需的时间为二十 ******************
GetComponent<NavMeshAgent>().speed = aiStoneMonster_Model.Monster_SPD_Model;//*************************** 设置寻路组件的速度为电脑AI石头怪物的速度值 ***************************
break;
}
}
}
}
④下面是我写的6个状态脚本,巡逻,追逐,攻击,释放魔法,释放特殊技能,逃跑六个
巡逻
using UnityEngine;
using System.Collections;
/// <summary>
/// 功能:所有电脑AI怪物的巡逻状态
/// 创建者: VioletTD
/// 修改时间: 2015年11月13日 16:53
/// 感谢: Me 加油!
/// </summary>
public class AIMonsterPatrolState : AIMonsterFSM {//*************************** 电脑AI怪物的巡逻状态 ***************************
private int currentWayPoint;
private Transform[] wayPoints;
public AIMonsterPatrolState(Transform[] Points)//*************************** 电脑AI怪物的巡逻状态带参数的构造方法 ***************************
{
wayPoints = Points;
aiMonsterEvent = AIMonsterEvent.AIMonsterPatrolEvent;//*************************** 当前的执行事件为巡逻 ***************************
}
public override void Change_Rule (GameObject player,GameObject AIMonster)//*************************** 重写转换规则的方法 ***************************
{
//*************************** 这里写的是你在本脚本状态下可以转换到那个状态下的规则,是要和电脑AI石头怪物控制脚本的制作一个状态机中的添加规则一一对应的 ***************************
switch(AIMonster.name)//@@@@@@@@@ 判断电脑AI怪物的名字 @@@@@@@@@
{
case "AIStoneMonster"://@@@@@@@@@ 如果名字是电脑AI石头怪物 @@@@@@@@@
{
RaycastHit hit;//*************************** 设置射中的命中点的射线 ***************************
if (Physics.SphereCast(AIMonster.transform.position,1f,AIMonster.transform.forward,out hit))//@@@@@@@@@ 如果从怪物的中心点到怪物前方二米的距离发射的射线射中的命中点 @@@@@@@@@
{
if (hit.transform.gameObject.tag == "Player" || hit.transform.gameObject.tag =="Monster")//@@@@@@@@@ 如果射中的是玩家 @@@@@@@@@
{
AIStoneMonsterController.Instance.AIMonster_SetAIMonsterRule_Controller(AIMonsterRule.AIMonsterFindTargetRule);//*************************** 获取脚本组件发生规则转换到找到玩家 ***************************
}
}
if (AIStoneMonsterController.Instance.aiStoneMonster_Model.Monster_CurrentHP_Model <= 40f) //@@@@@@@@@ 如果电脑AI石头怪物的当前血量小于等于一百 @@@@@@@@@
{
AIStoneMonsterController.Instance.AIMonster_SetAIMonsterRule_Controller (AIMonsterRule.AIMonsterHPLackRule);//*************************** 调用电脑AI石头怪物的控制脚本,转换规则为缺少血量 ***************************
}
if(Vector3.Distance (player.transform.position,AIMonster.transform.position) <= AIStoneMonsterController.Instance.aiStoneMonster_Model.AIStoneMonster_AttackRange_Model)//@@@@@@@@@ 如果电脑AI怪物距离目标的距离小于等于攻击距离 @@@@@@@@@
{
AIStoneMonsterController.Instance.AIMonster_SetAIMonsterRule_Controller (AIMonsterRule.AIMonsterATKRangeRule);//*************************** 调用电脑AI石头怪物的控制脚本,转换规则为攻击 ***************************
}
break;//######### 跳出判断 #########
}
}
}
public override void Execute_Event (GameObject player,GameObject AIMonster)//*************************** 重新父级里的执行事件的抽象方法 ***************************
{
Debug.Log("没有目标开始巡逻!");
AIMonster.GetComponent<Animator>().SetFloat ("Walk",0.2f);
Vector3 AIMonsterVelocity = AIMonster.GetComponent<Rigidbody>().velocity;//*************************** 电脑AI怪物的添加刚体的速率 ***************************
Vector3 moveTarget = wayPoints[currentWayPoint].position - AIMonster.transform.position;//*************************** 电脑AI怪物行走的位置向量 ***************************
if (moveTarget.magnitude < 1)//@@@@@@@@@ 如果向量的矢量小于一 @@@@@@@@@
{
currentWayPoint++;//*************************** 转换行走的路点数组的序列号加一(切换到下一个路点) ***************************
if (currentWayPoint >= wayPoints.Length)//@@@@@@@@@ 如果路点的序列化大于传入的路点数组的长度 @@@@@@@@@
{
currentWayPoint = 0;//*************************** 数组的序列化变为零(如此循环) ***************************
}
}
else
{
switch (AIMonster.name) //@@@@@@@@@ 判断电脑AI怪物的名字 @@@@@@@@@
{
case "AIStoneMonster"://@@@@@@@@@ 如果名字是电脑AI石头怪物 @@@@@@@@@
{
AIMonsterVelocity = moveTarget.normalized * AIStoneMonsterController.Instance
.aiStoneMonster_Model.Monster_SPD_Model;//*************************** 电脑AI怪物的添加刚体的速率等于,电脑AI怪物的向量(带方向)的单位向量乘以电脑AI怪物的速度 ***************************
break;//######### 跳出循环 #########
}
}
AIMonster.transform.rotation = Quaternion.Slerp(AIMonster.transform.rotation,Quaternion.LookRotation(moveTarget),Time.deltaTime * 2);//*************************** 电脑AI怪物的平滑旋转 ***************************
AIMonster.transform.eulerAngles = new Vector3(0, AIMonster.transform.eulerAngles.y, 0);//*************************** 保持电脑AI怪物只沿着Y轴旋转 ***************************
}
AIMonster.GetComponent<Rigidbody>().velocity = AIMonsterVelocity;//*************************** 电脑AI怪物接收这个速率(带方向),保持移动 ***************************
}
}
追逐
using UnityEngine;
using System.Collections;
/// <summary>
/// 功能:所有电脑AI怪物的追逐状态
/// 创建者: VioletTD
/// 修改时间: 2015年11月13日 17:37
/// 感谢: Me 加油!
/// </summary>
public class AIMonsterChaseState : AIMonsterFSM {//*************************** 所有电脑AI怪物的追逐状态 ***************************
public AIMonsterChaseState()//*************************** 电脑AI怪物的追逐状态下的无参的构造方法 ***************************
{
aiMonsterEvent = AIMonsterEvent.AIMonsterChaseEvent;//*************************** 初始为执行追逐的事件 ***************************
}
public override void Change_Rule (GameObject player, GameObject AIMonster)//*************************** 重写转换规则的方法 ***************************
{
//*************************** 这里写的是你在本脚本状态下可以转换到那个状态下的规则,是要和电脑AI石头怪物控制脚本的制作一个状态机中的添加规则一一对应的 ***************************
switch(AIMonster.name)//@@@@@@@@@ 判断电脑AI怪物的名字 @@@@@@@@@
{
case "AIStoneMonster"://@@@@@@@@@ 如果名字是电脑AI石头怪物 @@@@@@@@@
{
if (Vector3.Distance(AIMonster.transform.position, player.transform.position) >= 1f)//*************************** 如果电脑AI怪物到玩家的距离大于等于一 ***************************
{
AIStoneMonsterController.Instance.AIMonster_SetAIMonsterRule_Controller(AIMonsterRule.AIMonsterLostTargetRule);//*************************** 获取脚本组件发生规则转换到失去玩家 ***************************
}
if (AIStoneMonsterController.Instance.aiStoneMonster_Model.Monster_CurrentHP_Model <= 40f) //@@@@@@@@@ 如果电脑AI石头怪物的当前血量小于等于一百 @@@@@@@@@
{
AIStoneMonsterController.Instance.AIMonster_SetAIMonsterRule_Controller (AIMonsterRule.AIMonsterHPLackRule);//*************************** 调用电脑AI石头怪物的控制脚本,转换规则为缺少血量 ***************************
}
if(Vector3.Distance (player.transform.position,AIMonster.transform.position) <= AIStoneMonsterController.Instance.aiStoneMonster_Model.AIStoneMonster_AttackRange_Model)//@@@@@@@@@ 如果电脑AI怪物距离目标的距离小于等于攻击距离 @@@@@@@@@
{
AIStoneMonsterController.Instance.AIMonster_SetAIMonsterRule_Controller (AIMonsterRule.AIMonsterATKRangeRule);//*************************** 调用电脑AI石头怪物的控制脚本,转换规则为攻击 ***************************
}
break;//######### 跳出判断 #########
}
}
}
public override void Execute_Event (GameObject player, GameObject AIMonster)//*************************** 重新父级里的执行事件的抽象方法 ***************************
{
Debug.Log("发现目标开始追逐!");
switch (AIMonster.name) //@@@@@@@@@ 判断电脑AI怪物的名字 @@@@@@@@@
{
case "AIStoneMonster"://@@@@@@@@@ 如果名字是电脑AI石头怪物 @@@@@@@@@
{
AIMonster.GetComponent<Animator>().SetLayerWeight(0,1);//*************************** 设置第一层的权重值为一 ***************************
AIMonster.GetComponent<Animator>().SetFloat ("Walk",0.2f);//*************************** 设置开始行走 ***************************
AIMonster.GetComponent<Animator>().SetLayerWeight (1,0);//*************************** 设置第二层的权重值为零 ***************************
AIMonster.GetComponent<Animator>().SetBool ("Attack",false);//*************************** 设置停止攻击 ***************************
Vector3 AIMonsterVelocity = AIMonster.GetComponent<Rigidbody>().velocity;//*************************** 三维变量电脑AI怪物速率存储电脑AI怪物添加刚体组件的速率 ***************************
Vector3 moveTarget = player.transform.position - AIMonster.transform.position;//*************************** 电脑AI怪物朝向玩家位置移动 ***************************
AIMonsterVelocity = moveTarget.normalized * 0.1f;//*************************** 电脑AI怪物的移动速率等于目标点的向量乘以二 ***************************
AIMonster.transform.rotation = Quaternion.Slerp(AIMonster.transform.rotation,Quaternion.LookRotation(moveTarget),Time.deltaTime);//*************************** 电脑AI怪物的平滑转向 ***************************
AIMonster.transform.eulerAngles = new Vector3(0, AIMonster.transform.eulerAngles.y, 0);//*************************** 只让电脑AI怪物沿着Y轴旋转其他轴不会偏转 ***************************
AIMonster.GetComponent<Rigidbody>().velocity = AIMonsterVelocity;//*************************** 电脑AI怪物添加刚体组件后的速率等于电脑AI怪物的带方向的移动速率 ***************************
break;//######### 跳出判断 #########
}
}
}
}
攻击
using UnityEngine;
using System.Collections;
/// <summary>
/// 功能:所有电脑AI石头怪物的攻击状态脚本
/// 创建者: VioletTD
/// 修改时间: 2015年11月14日 11:38
/// 感谢: Me 加油!
/// </summary>
public class AIMonsterAttackState : AIMonsterFSM {//*************************** 攻击状态脚本 ***************************
public AIMonsterAttackState()//*************************** 电脑AI怪物的攻击状态脚本的构造方法 ***************************
{
aiMonsterEvent = AIMonsterEvent.AIMonsterATKEvent;//*************************** 初始化当期执行事件为攻击 ***************************
}
public override void Change_Rule (GameObject player, GameObject AIMonster)//*************************** 重写父级里的改变规则的抽象方法 ***************************
{
//*************************** 这里写的是你在本脚本状态下可以转换到那个状态下的规则,是要和电脑AI石头怪物控制脚本的制作一个状态机中的添加规则一一对应的 ***************************
switch(AIMonster.name)//@@@@@@@@@ 判断电脑AI怪物的名字 @@@@@@@@@
{
case "AIStoneMonster"://@@@@@@@@@ 如果名字是电脑AI石头怪物 @@@@@@@@@
{
if(Vector3.Distance (player.transform.position,AIMonster.transform.position) > AIStoneMonsterController.Instance.aiStoneMonster_Model.AIStoneMonster_AttackRange_Model)//@@@@@@@@@ 如果电脑AI怪物距离目标的距离大于攻击距离 @@@@@@@@@
{
AIStoneMonsterController.Instance.AIMonster_SetAIMonsterRule_Controller (AIMonsterRule.AIMonsterFindTargetRule);//*************************** 电脑AI石头怪物转换规则为发现目标 ***************************
}
if (AIStoneMonsterController.Instance.aiStoneMonster_Model.Monster_CurrentHP_Model <= 40f) //@@@@@@@@@ 如果电脑AI石头怪物的当前血量小于等于一百 @@@@@@@@@
{
AIStoneMonsterController.Instance.AIMonster_SetAIMonsterRule_Controller (AIMonsterRule.AIMonsterHPLackRule);//*************************** 调用电脑AI石头怪物的控制脚本,转换规则为缺少血量 ***************************
}
if (AIStoneMonsterController.Instance.aiStoneMonster_Model.Monster_CurrentMP_Model >= 10) //*************************** 如果电脑AI石头怪物的当前魔法值大于等于十 ***************************
{
AIStoneMonsterController.Instance.AIMonster_SetAIMonsterRule_Controller (AIMonsterRule.AIMonsterMPEnoughRule);//*************************** 调用电脑AI石头怪物的控制脚本,转换规则为魔法值充足 ***************************
}
if (AIStoneMonsterController.Instance.aiStoneMonster_Model.AIStoneMonster_CurrentXP_Model >= 100) //*************************** 如果电脑AI石头怪物的当前特殊技能值大于等于一百 ***************************
{
AIStoneMonsterController.Instance.AIMonster_SetAIMonsterRule_Controller (AIMonsterRule.AIMonsterXPEnoughRule);//*************************** 调用电脑AI石头怪物的控制脚本,转换规则为特殊技能值充足 ***************************
}
break;//@@@@@@@@@ 跳出判断 @@@@@@@@@
}
}
}
public override void Execute_Event (GameObject player, GameObject AIMonster)//*************************** 重新父级里的执行事件的抽象方法 ***************************
{
Debug.Log("在攻击范围开始攻击!");
switch (AIMonster.name) //@@@@@@@@@ 判断电脑AI怪物的名字 @@@@@@@@@
{
case "AIStoneMonster"://@@@@@@@@@ 如果名字是电脑AI石头怪物 @@@@@@@@@
{
Vector3 moveTarget = player.transform.position - AIMonster.transform.position;//*************************** 电脑AI怪物朝向玩家位置移动 ***************************
AIMonster.transform.rotation = Quaternion.Slerp(AIMonster.transform.rotation,Quaternion.LookRotation(moveTarget),Time.deltaTime * 4f);//*************************** 电脑AI怪物的平滑转向 ***************************
AIMonster.transform.eulerAngles = new Vector3(0, AIMonster.transform.eulerAngles.y, 0);//*************************** 只让电脑AI怪物沿着Y轴旋转其他轴不会偏转 ***************************
AIMonster.GetComponent<Animator>().SetLayerWeight (1,1);//*************************** 设置第二层的权重值为一 ***************************
AIMonster.GetComponent<Animator>().SetBool ("Attack",true);//*************************** 设置开始攻击 ***************************
AIMonster.GetComponent<Animator>().SetLayerWeight(0,0);//*************************** 设置第一层的权重值为零 ***************************
AIMonster.GetComponent<Animator>().SetFloat ("Walk",0f);//*************************** 设置停止行走 ***************************
break;;//@@@@@@@@@ 跳出判断 @@@@@@@@@
}
}
}
}
释放魔法
using UnityEngine;
using System.Collections;
/// <summary>
/// 功能:所有电脑AI怪物的释放魔法的状态
/// 创建者: VioletTD
/// 修改时间: 2015年11月4日 9:16
/// 感谢: Me 加油!
/// </summary>
public class AIMonsterReleaseMPSkillState : AIMonsterFSM {//*************************** 释放魔法的状态 ***************************
public AIMonsterReleaseMPSkillState()//*************************** 释放魔法的构造方法 ***************************
{
aiMonsterEvent = AIMonsterEvent.AIMonsterSkillEvent;//*************************** 初始化执行事件为释放魔法 ***************************
}
public override void Change_Rule (GameObject player, GameObject AIMonster)//*************************** 重写转换规则的方法 ***************************
{
//*************************** 这里写的是你在本脚本状态下可以转换到那个状态下的规则,是要和电脑AI石头怪物控制脚本的制作一个状态机中的添加规则一一对应的 ***************************
switch (AIMonster.name) //@@@@@@@@@ 判断怪物的名字 @@@@@@@@@
{
case "AIStoneMonster"://@@@@@@@@@ 如果名字是电脑AI怪物 @@@@@@@@@
{
if (AIStoneMonsterController.Instance.aiStoneMonster_Model.Monster_CurrentMP_Model <= 10f) //*************************** 如果电脑AI石头怪物的当前魔法值小于十 ***************************
{
AIStoneMonsterController.Instance.AIMonster_SetAIMonsterRule_Controller (AIMonsterRule.AIMonsterMPLackRule);//*************************** 电脑AI石头怪物转换规则为魔法不足 ***************************
}
break;//######### 跳出判断 #########
}
}
}
public override void Execute_Event (GameObject player, GameObject AIMonster)//*************************** 重新父级里的执行事件的抽象方法 ***************************
{
Debug.Log("魔法充足释放魔法<防御力提高>!");
switch (AIMonster.name) //@@@@@@@@@ 判断怪物的名字 @@@@@@@@@
{
case "AIStoneMonster"://@@@@@@@@@ 如果名字是电脑AI怪物 @@@@@@@@@
{
AIStoneMonsterController.Instance.AIStoneMonster_Skill_Controller ();//*************************** 调用方法释放魔法 ***************************
break;//######### 跳出判断 #########
}
}
}
}
释放特殊技能
using UnityEngine;
using System.Collections;
/// <summary>
/// 功能:所有电脑AI怪物的释放特殊技能的状态
/// 创建者: VioletTD
/// 修改时间: 2015年11月14日 16:34
/// 感谢: Me 加油!
/// </summary>
public class AIMonsterReleaseXPSkillState : AIMonsterFSM {//*************************** 释放特殊技能的状态 ***************************
public AIMonsterReleaseXPSkillState()//*************************** 释放特殊技能状态的构造方法 ***************************
{
aiMonsterEvent = AIMonsterEvent.AIMonsterXPSkillEvent;//*************************** 初始化执行事件为释放特殊技能 ***************************
}
public override void Change_Rule (GameObject player, GameObject AIMonster)//*************************** 重写转换规则的方法 ***************************
{
//*************************** 这里写的是你在本脚本状态下可以转换到那个状态下的规则,是要和电脑AI石头怪物控制脚本的制作一个状态机中的添加规则一一对应的 ***************************
switch (AIMonster.name) //@@@@@@@@@ 判断怪物的名字 @@@@@@@@@
{
case "AIStoneMonster"://@@@@@@@@@ 如果名字是电脑AI怪物 @@@@@@@@@
{
if (AIStoneMonsterController.Instance.aiStoneMonster_Model.AIStoneMonster_CurrentXP_Model < 40f) //*************************** 如果电脑AI石头怪物的当前特殊技能值小于一百 ***************************
{
AIStoneMonsterController.Instance.AIMonster_SetAIMonsterRule_Controller (AIMonsterRule.AIMonsterXPLackRule);//*************************** 电脑AI石头怪物转换规则为特殊技能不足 ***************************
}
break;//######### 跳出判断 #########
}
}
}
public override void Execute_Event (GameObject player, GameObject AIMonster)//*************************** 重新父级里的执行事件的抽象方法 ***************************
{
Debug.Log("特殊技能值充足释放特殊技能<攻击力提高>!");
switch (AIMonster.name) //@@@@@@@@@ 判断怪物的名字 @@@@@@@@@
{
case "AIStoneMonster"://@@@@@@@@@ 如果名字是电脑AI怪物 @@@@@@@@@
{
AIStoneMonsterController.Instance.AIStoneMonster_XPSkill_Controller ();//*************************** 调用方法释放特殊技能 ***************************
break;//######### 跳出判断 #########
}
}
}
}
逃跑
using UnityEngine;
using System.Collections;
/// <summary>
/// 功能:所有电脑AI石头怪物的逃跑状态脚本
/// 创建者: VioletTD
/// 修改时间: 2015年11月14日 11:38
/// 感谢: Me 加油!
/// </summary>
public class AIMonsterEscapeState : AIMonsterFSM {//*************************** 逃跑状态脚本 ***************************
private float timer;//*************************** 私有的计时 ***************************
public AIMonsterEscapeState()//*************************** 因为没有继承MonoBehaviour,只能用构造方法初始化 ***************************
{
aiMonsterEvent = AIMonsterEvent.AIMonsterEscapeEvent;//*************************** 初始化当前的执行事件为逃跑 ***************************
timer = 3f;//*************************** 初始化计时为三秒 ***************************
}
public override void Change_Rule (GameObject player, GameObject AIMonster)//*************************** 重写父类的转变规则的方法 ***************************
{
//*************************** 这里写的是你在本脚本状态下可以转换到那个状态下的规则,是要和电脑AI石头怪物控制脚本的制作一个状态机中的添加规则一一对应的 ***************************
switch(AIMonster.name)//@@@@@@@@@ 判断电脑AI怪物的名字 @@@@@@@@@
{
case "AIStoneMonster"://@@@@@@@@@ 如果名字是电脑AI石头怪物 @@@@@@@@@
{
if (AIStoneMonsterController.Instance.aiStoneMonster_Model.Monster_CurrentHP_Model >= 100f) //@@@@@@@@@ 如果电脑AI石头怪物的当前血量小于等于一百 @@@@@@@@@
{
AIStoneMonsterController.Instance.AIMonster_SetAIMonsterRule_Controller (AIMonsterRule.AIMonsterHPEnoughRule);//*************************** 调用电脑AI石头怪物的控制脚本,转换规则为缺少血量 ***************************
}
break;//######### 跳出判断 #########
}
}
}
public override void Execute_Event (GameObject player, GameObject AIMonster)//*************************** 重新父级里的执行事件的抽象方法 ***************************
{
Debug.Log("好怕怕啊,我要回家啊啊啊啊啊啊啊,别追我!");
switch (AIMonster.name) //@@@@@@@@@ 判断电脑AI怪物的名字 @@@@@@@@@
{
case "AIStoneMonster"://@@@@@@@@@ 如果名字是电脑AI石头怪物 @@@@@@@@@
{
AIMonster.GetComponent<Animator>().SetLayerWeight(0,1);//*************************** 设置第一层的权重值为一 ***************************
AIMonster.GetComponent<Animator>().SetFloat ("Walk",0.2f);//*************************** 设置开始行走 ***************************
AIMonster.GetComponent<Animator>().SetLayerWeight (1,0);//*************************** 设置第二层的权重值为零 ***************************
AIMonster.GetComponent<Animator>().SetBool ("Attack",false);//*************************** 设置停止攻击 ***************************
Vector3 AIMonsterVelocity = AIMonster.GetComponent<Rigidbody>().velocity;//*************************** 三维变量电脑AI怪物速率存储电脑AI怪物添加刚体组件的速率 ***************************
Vector3 moveTarget = AIMonster.transform.position - player.transform.position ;//*************************** 电脑AI怪物远离玩家位置移动 ***************************
AIMonsterVelocity = moveTarget.normalized * 0.1f;//*************************** 电脑AI怪物的移动速率等于目标点的向量乘以二 ***************************
AIMonster.transform.rotation = Quaternion.Slerp(AIMonster.transform.rotation,Quaternion.LookRotation(moveTarget),Time.deltaTime);//*************************** 电脑AI怪物的平滑转向 ***************************
AIMonster.transform.eulerAngles = new Vector3(0, AIMonster.transform.eulerAngles.y, 0);//*************************** 只让电脑AI怪物沿着Y轴旋转其他轴不会偏转 ***************************
AIMonster.GetComponent<Rigidbody>().velocity = AIMonsterVelocity;//*************************** 电脑AI怪物添加刚体组件后的速率等于电脑AI怪物的带方向的移动速率 ***************************
break;//######### 跳出判断 #########
}
}
}
}
以上是重点的代码部分,相比看到了这里也很累了把,但是,你收货到知识的喜悦远远大于你的疲惫之感! 谢谢你可以一直认真的看到最后!
谢谢大家的支持,我会继续努力,写出更多有意义的文章! 如果你还有什么不懂的,可以联系我哦!
不要忘记,Unity3D的 有限状态机的资源包,在我的资源里15M,可以免费下载哦!希望可以给大家帮助!
本文介绍了如何使用有限状态机(FSM)来创建Unity3D游戏中的AI。通过FSM,可以清晰地控制角色状态转换,避免复杂的bool开关,简化代码逻辑。文中分享了基础的FSM脚本编写,包括状态转换规则和事件处理,并提供了6个具体状态(巡逻、追逐、攻击等)的示例。此外,作者提供了相关资源包供读者下载学习。
3519

被折叠的 条评论
为什么被折叠?



