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. Linux正則表達式-反复出现的字符

    星号(*)元字符表示它前面的正則表達式能够出现零次或多次.也就是说,假设它改动了单个字符.那么该字符能够在那里也能够不在那里,而且假设它在那里,那可能会不止出现一个.能够使用星号元字符匹配出如今引號中 ...

  2. Android应用程序线程消息循环模型分析

    文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/6905587 我们知道,Android应用程序是 ...

  3. [HeadFirst-HTMLCSS入门][第十一章布局排版]

    流 浮动布局 冻结布局 凝胶布局 绝对布局 表格显示布局 postion 绝对 静态 固定 相对 浮动元素 必须指明宽度 解决重合 中缝 设置外边距留中缝,好看一点 clear标签 不准左右有浮动元素 ...

  4. 解决数据库Operation not allowed when innodb_forced_recovery > 0

    解决数据库Operation not allowed when innodb_forced_recovery > 0 请修改my.cnf innodb_force_recovery = 1 修改 ...

  5. NET中级课--文件,流,序列化2

    1.流的类型体系: 基础流    装饰器流    包装器类    帮助类 2.               stream file~     memory~     network~ stream是个 ...

  6. bower安装使用以及git安装

    bower需要:node 和 git node安装包下载:http://blog.csdn.net/myan/article/details/2028545 Git安装: 选择第二项:Use Git ...

  7. 使用bootstrapvalidator的remote验证经验

    这里需要说一下,bootstrapvalidator的帮助文档写的比较简单,对于remote验证器的说明更是如此,在经历多方测试之后才明白如何使用这个验证器. 一个典型的ajax验证代码如下: 服务端 ...

  8. asp.net同时调用JS和后台的无效的解决

    如果js是个定时器,那么就不走后台 <asp:Button runat="server" type="button" Text="重新发送邮件& ...

  9. Struts2学习笔记 国际化(Internationalization)

    概述 国际化(Internationalization),通途的讲,就是让软件实现对多种语言的支持.可以通过简单的设置就可以从一种语言切换到另一种语言.用的最多的地方就是在应用程序的界面表示上.我们经 ...

  10. CDZSC_2015寒假新人(1)——基础 i

    Description “Point, point, life of student!” This is a ballad(歌谣)well known in colleges, and you mus ...