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. 用户向导页面实现左右滑动的ImageSwitcher

    当你第一次打开app时刻,通常有使用向导现在演示APK基本功能和用法,该向导是非常重要的,用户可以知道并调整到速度app如何. 实现此使用向导有非常多种方法,比方用ImageSwitcher.View ...

  2. iOS ARC注释和错误的解决方法在使用

    1.一个错误The current deployment target does not support automated __weak references 这个错误被所述支持iOS版本号不支持相 ...

  3. AfxBeginThread的介绍/基本用法

    AfxBeginThread    用户界面线程和工作者线程都是由AfxBeginThread创建的.现在,考察该函数:MFC提供了两个重载版的AfxBeginThread,一个用于用户界面线程,另一 ...

  4. Xcode5和6上新建工程如何本地化启动页面

    建议阅读本篇文章前先具备iOS本地化的基本知识,Google中搜索“iOS本地化”,有成片的教程~~ 最近有个app需要支持英语.简体中文.繁体中文,由于启动页面上有文字,所以也不得不做下本地化处理. ...

  5. linux下使用非root账号安装zabbix-client

    linux下使用非root账号安装zabbix-client使用非root账号rusky登录:[rusky@testServer]#tar zxvf zabbix-2.4.5.tar.gz #cd z ...

  6. 用cflow工具生成代码函数调用关系

    1. 安装 sudo apt-get install cflow 2.使用 cflow [options...] [file]... 例: cflow main.c 生成main.c文件例的函数调用关 ...

  7. GDI+创建Graphics对象的2种方式

      1.this.CreateGraphics()     // 调用控件的CreateGraphics()方法 2.在OnPaint事件中,PaintEventArgs类型的参数e对象的Graphi ...

  8. Javascript的事件委托

    在谈js的事件委托之前,先来简单说说js事件的一些基础知识吧. 什么是事件?Javascipt与HTML之间的交互是通过事件实现的.事件,就是文档或浏览器中发生的一些特定的交互瞬间. 什么是事件流?事 ...

  9. 从一道面试题谈linux下fork的运行机制

    http://www.cnblogs.com/leoo2sk/archive/2009/12/11/talk-about-fork-in-linux.html

  10. 找不到Qt5Cored.dll(Release和Debug版连接了不同的库)

    Qt5Cored.dll和Qt5Core.dll文件分别用于Qt软件的Debug版和Release版. 通常会有两个Qt5Core.dll文件,分别位于Qti安装目录下的“Qt5.1.0\5.1.0\ ...