using UnityEngine;
using System.Collections; public class AttackState : FSMState
{
public AttackState()
{
stateID = FSMStateID.Attacking;
} public override void Reason(Transform player, Transform npc)
{
if (npc.GetComponent<AIController>().stateInfo.normalizedTime >= 1.0f && npc.GetComponent<AIController>().stateInfo.IsName("Attack"))
npc.GetComponent<AIController>().SetTransition(Transition.AttackOver);
} public override void Act(Transform player, Transform npc)
{
}
}
 using UnityEngine;
using System.Collections; public class DeadState : FSMState
{
public DeadState()
{
stateID = FSMStateID.Dead;
} public override void Reason(Transform player, Transform npc)
{ } public override void Act(Transform player, Transform npc)
{
Animation animComponent = npc.GetComponent<Animation>();
//animComponent.CrossFade("death");
}
}
 using UnityEngine;
using System.Collections; public class MoveState : FSMState
{
float rotateTime;
float curSpeed;
public MoveState()
{
stateID = FSMStateID.Move; curSpeed = 1.0f;
rotateTime = 0f;
} public override void Reason(Transform player, Transform npc)
{
float distance = Vector3.Distance(player.position, npc.position);
if (distance <= )
{
if (npc.GetComponent<AIController>().attackCd == 0f)
{
npc.GetComponent<AIController>().SetTransition(Transition.ReachPlayer);
npc.GetComponent<AIController>().attackCd = 5.0f;
}
}
} public override void Act(Transform player, Transform npc)
{
rotateTime -= Time.deltaTime;
if (rotateTime <= )
{
rotateTime = 3.0f;
Vector3 toTargetV3 = (player.position - npc.position).normalized;
float direction = Vector3.Dot(toTargetV3, npc.forward);
Vector3 u = Vector3.Cross(toTargetV3, npc.forward);
if (direction > ) { direction = 1f; }
if (direction < -) { direction = -1f; }
if (Mathf.Abs(direction) == 1f)
return;
direction = Mathf.Acos(direction) * Mathf.Rad2Deg;
npc.rotation = npc.rotation * Quaternion.Euler(new Vector3(, direction * (u.y >= ? - : ), ));
} float distance = Vector3.Distance(player.position, npc.position);
if (distance >= )
{
npc.GetComponent<AIController>().animator.SetFloat("Blend", 1f);
curSpeed = 2f;
}
else if (distance < && distance >= )
{
npc.GetComponent<AIController>().animator.SetFloat("Blend", 0.5f);
curSpeed = 1f;
}
else
{
npc.GetComponent<AIController>().animator.SetFloat("Blend", 0f);
curSpeed = ;
}
npc.Translate(npc.transform.forward * Time.deltaTime * curSpeed, Space.World);
}
}
 using UnityEngine;
using System.Collections;
using System.Collections.Generic; /// <summary>
/// This class is adapted and modified from the FSM implementation class available on UnifyCommunity website
/// The license for the code is Creative Commons Attribution Share Alike.
/// It's originally the port of C++ FSM implementation mentioned in Chapter01 of Game Programming Gems 1
/// You're free to use, modify and distribute the code in any projects including commercial ones.
/// Please read the link to know more about CCA license @http://creativecommons.org/licenses/by-sa/3.0/
/// </summary> //定义枚举,为可能的转换分配编号
public enum Transition
{
SawPlayer = , //看到玩家
ReachPlayer, //接近玩家
LostPlayer, //玩家离开视线
NoHealth, //死亡
AttackOver, //结束攻击
} /// <summary>
/// 定义枚举,为可能的状态分配编号ID
/// </summary>
public enum FSMStateID
{
Move = ,
Attacking, //攻击编号
Patrolling , //巡逻编号
Chasing, //追逐编号
Dead, //死亡编号
} public class AdvancedFSM : FSM
{
//FSM中的所有状态组成的列表
private List<FSMState> fsmStates;
//当前状态的编号
//The fsmStates are not changing directly but updated by using transitions
private FSMStateID currentStateID;
public FSMStateID CurrentStateID { get { return currentStateID; } }
//当前状态
private FSMState currentState;
public FSMState CurrentState { get { return currentState; } } public AdvancedFSM()
{
//新建一个空的状态列表
fsmStates = new List<FSMState>();
} /// <summary>
///向状态列表中加入一个新的状态
/// </summary>
public void AddFSMState(FSMState fsmState)
{
//检查要加入的新状态是否为空,如果空就报错
if (fsmState == null)
{
Debug.LogError("FSM ERROR: Null reference is not allowed");
} // First State inserted is also the Initial state
// the state the machine is in when the simulation begins
//如果插入的这个状态时,列表还是空的,那么将它加入列表并返回
if (fsmStates.Count == )
{
fsmStates.Add(fsmState);
currentState = fsmState;
currentStateID = fsmState.ID;
return;
} // 检查要加入的状态是否已经在列表里,如果是,报错返回
foreach (FSMState state in fsmStates)
{
if (state.ID == fsmState.ID)
{
Debug.LogError("FSM ERROR: Trying to add a state that was already inside the list");
return;
}
}
//如果要加入的状态不在列表中,将它加入列表
fsmStates.Add(fsmState);
} //从状态中删除一个状态
public void DeleteState(FSMStateID fsmState)
{
// 搜索整个状态列表,如果要删除的状态在列表中,那么将它移除,否则报错
foreach (FSMState state in fsmStates)
{
if (state.ID == fsmState)
{
fsmStates.Remove(state);
return;
}
}
Debug.LogError("FSM ERROR: The state passed was not on the list. Impossible to delete it");
} /// <summary>
/// 根据当前状态,和参数中传递的转换,转换到新状态
/// </summary>
public void PerformTransition(Transition trans)
{
// 根绝当前的状态类,以Trans为参数调用它的GetOutputState方法
//确定转换后的新状态
FSMStateID id = currentState.GetOutputState(trans); // 将当前状态编号设置为刚刚返回的新状态编号
currentStateID = id; //根绝状态编号查找状态列表,将当前状态设置为查找到的状态
foreach (FSMState state in fsmStates)
{
if (state.ID == currentStateID)
{
currentState = state;
break;
}
}
}
}
 using UnityEngine;
using System.Collections; public class FSM : MonoBehaviour
{
//玩家位置
protected Transform playerTransform; //下一个巡逻点
protected Vector3 destPos; //巡逻点表单
protected GameObject[] pointList; //子弹信息
protected float shootRate;
protected float elapsedTime; protected virtual void Initialize() {}
protected virtual void FSMUpdate() {}
protected virtual void FSMFixedUpdate() {} //初始化信息
void Start()
{
Initialize();
} // 循环执行子类FSMUpdate方法
void Update ()
{
FSMUpdate();
} void FixedUpdate()
{
FSMFixedUpdate();
}
}
 using UnityEngine;
using System.Collections;
using System.Collections.Generic; /// <summary>
/// This class is adapted and modified from the FSM implementation class available on UnifyCommunity website
/// The license for the code is Creative Commons Attribution Share Alike.
/// It's originally the port of C++ FSM implementation mentioned in Chapter01 of Game Programming Gems 1
/// You're free to use, modify and distribute the code in any projects including commercial ones.
/// Please read the link to know more about CCA license @http://creativecommons.org/licenses/by-sa/3.0/ /// This class represents the States in the Finite State System.
/// Each state has a Dictionary with pairs (transition-state) showing
/// which state the FSM should be if a transition is fired while this state
/// is the current state.
/// Reason method is used to determine which transition should be fired .
/// Act method has the code to perform the actions the NPC is supposed to do if it磗 on this state.
/// </summary>
public abstract class FSMState
{
//字典,字典中每一项都记录了一个“转换-状态”对 的信息
protected Dictionary<Transition, FSMStateID> map = new Dictionary<Transition, FSMStateID>();
//状态编号ID
protected FSMStateID stateID;
public FSMStateID ID { get { return stateID; } } /// <summary>
/// 向字典添加项,每项是一个"转换--状态"对
/// </summary>
/// <param name="transition"></param>
/// <param name="id"></param>
public void AddTransition(Transition transition, FSMStateID id)
{
//检查这个转换(可以看做是字典的关键字)是否在字典里
if (map.ContainsKey(transition))
{
//一个转换只能对应一个新状态
Debug.LogWarning("FSMState ERROR: transition is already inside the map");
return;
}
//如果不在字典,那么将这个转换和转换后的状态作为一个新的字典项,加入字典
map.Add(transition, id);
} /// <summary>
/// 从字典中删除项
/// </summary>
/// <param name="trans"></param>
public void DeleteTransition(Transition trans)
{
// 检查是否在字典中,如果在,移除
if (map.ContainsKey(trans))
{
map.Remove(trans);
return;
}
//如果要删除的项不在字典中,报告错误
Debug.LogError("FSMState ERROR: Transition passed was not on this State List");
} /// <summary>
/// 通过查询字典,确定在当前状态下,发生trans转换时,应该转换到新的状态编号并返回
/// </summary>
/// <param name="trans"></param>
/// <returns></returns>
public FSMStateID GetOutputState(Transition trans)
{
return map[trans];
} /// <summary>
/// 用来确定是否需要转换到其他状态,应该发生哪个转换
/// </summary>
/// <param name="player"></param>
/// <param name="npc"></param>
public abstract void Reason(Transform player, Transform npc); /// <summary>
/// 定义了在本状态的角色行为,移动,动画等
/// </summary>
/// <param name="player"></param>
/// <param name="npc"></param>
public abstract void Act(Transform player, Transform npc);
}
 using UnityEngine;
using System.Collections; public class AIController : AdvancedFSM
{
private int health;
public Animator animator;
public AnimatorStateInfo stateInfo;
public float attackCd;
//Initialize the Finite state machine for the NPC tank
protected override void Initialize()
{
health = ; elapsedTime = 0.0f;
shootRate = 0.5f;
attackCd = 0f; //Get the target enemy(Player)
GameObject objPlayer = GameObject.FindGameObjectWithTag("Player");
playerTransform = objPlayer.transform; if (!playerTransform)
print("Player doesn't exist.. Please add one with Tag named 'Player'");
animator = this.GetComponentInChildren<Animator>();
//Start Doing the Finite State Machine
ConstructFSM();
} //Update each frame
protected override void FSMUpdate()
{
//Check for health
elapsedTime += Time.deltaTime;
if (attackCd > )
{
attackCd -= Time.deltaTime;
if (attackCd <= )
attackCd = ;
}
} protected override void FSMFixedUpdate()
{
stateInfo = animator.GetCurrentAnimatorStateInfo();
CurrentState.Reason(playerTransform, transform);
CurrentState.Act(playerTransform, transform);
} public void SetTransition(Transition t)
{
PerformTransition(t);
animator.SetInteger("StateI", (int)CurrentStateID);
} private void ConstructFSM()
{
//Get the list of points
pointList = GameObject.FindGameObjectsWithTag("PatrolPoint"); Transform[] waypoints = new Transform[pointList.Length];
int i = ;
foreach(GameObject obj in pointList)
{
waypoints = obj.transform;
i++;
} MoveState move = new MoveState();
move.AddTransition(Transition.ReachPlayer,FSMStateID.Attacking); AttackState attack = new AttackState();
attack.AddTransition(Transition.AttackOver,FSMStateID.Move); AddFSMState(move);
AddFSMState(attack);
} /// <summary>
/// Check the collision with the bullet
/// </summary>
/// <param name="collision"></param>
void OnCollisionEnter(Collision collision)
{
//Reduce health
if (collision.gameObject.tag == "Bullet")
{
health -= ; if (health <= )
{
Debug.Log("Switch to Dead State");
SetTransition(Transition.NoHealth);
}
}
} // Shoot the bullet
public void ShootBullet()
{
if (elapsedTime >= shootRate)
{
elapsedTime = 0.0f;
}
}
}
 using UnityEngine;
using System.Collections; public class CameraFollow : MonoBehaviour
{
public Transform target;
public Vector3 offest; void LateUpdate()
{
transform.position = target.position + offest;
}
}

使用有限状态机(FSM)编写的敌人AI的更多相关文章

  1. Atitit. 有限状态机 fsm 状态模式

    Atitit. 有限状态机 fsm 状态模式 1. 有限状态机 1 2. "状态表"和"状态轮换表" 1 3. 有限状态机概念(状态(State)事件(Even ...

  2. 【转】利用Behavior Designer制作敌人AI

    http://www.unity.5helpyou.com/3112.html 本篇unity3d教程,我们来学习下利用Behavior Designer行为树插件来制作敌人AI,下面开始! Beha ...

  3. Unity3D 敌人AI 和 动画( Animator )系统的实例讲解

    在这个实例中,我们要做一些敌人AI的简单实现,其中自动跟随和动画是重点,我们要达到的目标如下: 1.敌人能够自动跟随主角 2.敌人模型一共有四个动作:Idle(空闲) Run(奔跑) Attack(攻 ...

  4. 有限状态机FSM(自动售报机Verilog实现)

    有限状态机FSM(自动售报机Verilog实现) FSM 状态机就是一种能够描述具有逻辑顺序和时序顺序事件的方法. 状态机有两大类:Mealy型和Moore型. Moore型状态机的输出只与当前状态有 ...

  5. cocos2d-x 游戏开发之有限状态机(FSM) (四)

    cocos2d-x 游戏开发之有限状态机(FSM) (四) 虽然我们了解了FSM,并且可以写自己的FSM,但是有更好的工具帮我们完成这个繁琐的工作.SMC(http://smc.sourceforge ...

  6. cocos2d-x 游戏开发之有限状态机(FSM) (三)

    cocos2d-x 游戏开发之有限状态机(FSM) (三) 有限状态机简称FSM,现在我们创建一个专门的FSM类,负责管理对象(Monkey)的状态.然后Monkey类就实现了行为与状态分离.Monk ...

  7. cocos2d-x 游戏开发之有限状态机(FSM) (一)

    cocos2d-x 游戏开发之有限状态机(FSM) (一) 参考:http://blog.csdn.net/mgphuang/article/details/5845252<Cocos2d-x游 ...

  8. cocos2d-x 游戏开发之有限状态机(FSM) (二)

    cocos2d-x 游戏开发之有限状态机(FSM)  (二) 1 状态模式

  9. 有限状态机FSM

    有限状态机(Finite-state machine)又称有限状态自动机,是表示有限个状态以及在这些状态之间的转移和动作等行为的数学模型.常用与:正则表达式引擎,编译器的词法和语法分析,游戏设计,网络 ...

随机推荐

  1. Oracle字符集查看

    Oracle字符集是一个字节数据的解释的符号集合,有大小之分,有相互的包容关系.ORACLE 支持国家语言的体系结构允许你使用本地化语言来存储,处理,检索数据.它使数据库工具,错误消息,排序次序,日期 ...

  2. Android学习笔记--服务(Service)

    1.服务概述 1.服务是Android四大组件之一,在使用上可以分为本地服务和远程服务,本地服务是指在不影响用户操作的情况下在后台默默的执行一个耗时操作,例如下载,音频播放等.远程服务是指可以供其他应 ...

  3. jQuery中的trigger和triggerhandler区别

    $("form :input").blur(function(){ // }).keyup(function(){ $(this).triggerHandler("blu ...

  4. html5前端开发笔记-个人中心

    简单的css自适应 PC端 *** 移动端 *** ) *** 一开始的想法就是模仿手机APP 的页面进行布局,首先得有个头部,然后是主题部分,然后加上2个按钮,分别是编辑和退出登录.先布出基本结构. ...

  5. Android Lambda

    到目前为止 android 本身不支持lambda语法, 但Java的JDK1.8+支持lambda,故我们可以稍做修改,让android支持lambda,以AS为例 1. 确保你的JDK是1.8及以 ...

  6. 关于asp:login控件和验证码的问题?(转)

    1.验证码页面添加.2.将这验证码页面添加到login控件中:拖曳一Login控件,将之切换到模式下,在Html源文件中在表格中密码那行后添加: <tr>    <td style= ...

  7. C#中string.Empty和""、null的区别

    string.Empty是string类的一个静态常量,而""则表示一个空字符串. string是一种特殊的引用类型,它的null值则表示没有分配内存. 使用ILSpy反编译Str ...

  8. 公司项目笔记-导出excel

    一.asp.net中导出Excel的方法: 在asp.net中导出Excel有两种方法,一种是将导出的文件存放在服务器某个文件夹下面,然后将文件地址输出在浏览器上:一种是将文件直接将文件输出流写给浏览 ...

  9. Entity Framework Code First主外键关系映射约定

    本篇随笔目录: 1.外键列名默认约定 2.一对多关系 3.一对一关系 4.多对多关系 5.一对多自反关系 6.多对多自反关系 在关系数据库中,不同表之间往往不是全部都单独存在,而是相互存在关联的.两个 ...

  10. OpenCV——分水岭算法

    分水岭算法,是一种基于拓扑理论的数学形态学的分割方法,其基本思想是把图像看作是测地学上的拓扑地貌,图像中每一点像素的灰度值表示该点的海拔高度,每一个局部极小值及其影响区域称为集水盆,而集水盆的边界则形 ...