使用有限状态机(FSM)编写的敌人AI
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的更多相关文章
- Atitit. 有限状态机 fsm 状态模式
Atitit. 有限状态机 fsm 状态模式 1. 有限状态机 1 2. "状态表"和"状态轮换表" 1 3. 有限状态机概念(状态(State)事件(Even ...
- 【转】利用Behavior Designer制作敌人AI
http://www.unity.5helpyou.com/3112.html 本篇unity3d教程,我们来学习下利用Behavior Designer行为树插件来制作敌人AI,下面开始! Beha ...
- Unity3D 敌人AI 和 动画( Animator )系统的实例讲解
在这个实例中,我们要做一些敌人AI的简单实现,其中自动跟随和动画是重点,我们要达到的目标如下: 1.敌人能够自动跟随主角 2.敌人模型一共有四个动作:Idle(空闲) Run(奔跑) Attack(攻 ...
- 有限状态机FSM(自动售报机Verilog实现)
有限状态机FSM(自动售报机Verilog实现) FSM 状态机就是一种能够描述具有逻辑顺序和时序顺序事件的方法. 状态机有两大类:Mealy型和Moore型. Moore型状态机的输出只与当前状态有 ...
- cocos2d-x 游戏开发之有限状态机(FSM) (四)
cocos2d-x 游戏开发之有限状态机(FSM) (四) 虽然我们了解了FSM,并且可以写自己的FSM,但是有更好的工具帮我们完成这个繁琐的工作.SMC(http://smc.sourceforge ...
- cocos2d-x 游戏开发之有限状态机(FSM) (三)
cocos2d-x 游戏开发之有限状态机(FSM) (三) 有限状态机简称FSM,现在我们创建一个专门的FSM类,负责管理对象(Monkey)的状态.然后Monkey类就实现了行为与状态分离.Monk ...
- cocos2d-x 游戏开发之有限状态机(FSM) (一)
cocos2d-x 游戏开发之有限状态机(FSM) (一) 参考:http://blog.csdn.net/mgphuang/article/details/5845252<Cocos2d-x游 ...
- cocos2d-x 游戏开发之有限状态机(FSM) (二)
cocos2d-x 游戏开发之有限状态机(FSM) (二) 1 状态模式
- 有限状态机FSM
有限状态机(Finite-state machine)又称有限状态自动机,是表示有限个状态以及在这些状态之间的转移和动作等行为的数学模型.常用与:正则表达式引擎,编译器的词法和语法分析,游戏设计,网络 ...
随机推荐
- 包含深度学习常用框架的Docker环境
相关的代码都在Github上,请参见我的Github,https://github.com/lijingpeng/deep-learning-notes 敬请多多关注哈~~~ All in one d ...
- 关于Http协议(2)--转载
原文链接:http://www.cnblogs.com/mcad/ HTTP工作原理图 请求报文 1.请求报文长什么样? Chrome核心的请求报文 2.报文结构 3.报文头部每个字段的意义 //从 ...
- css3 在线编辑工具 连兼容都写好了
http://www.css3maker.com/index.html
- JS操作URL
function getQueStr(url, ref) //取获参数值 { ); ) { var arr = str.split('&'); for (i in arr) { ] == re ...
- SqlServer存储过程传入Table参数
今天是周日,刚好有空闲时间整理一下这些天工作业务中遇到的问题. 有时候我们有这样一个需求,就是在后台中传过来一个IList<类>的泛型集合数据,该集合是某个类的实例集合体,然后将该集合中的 ...
- Centos6架设GIT服务,windows客户端使用TortoiseGit加载KEYGEN连接GIT服务器
前几天得空,想起前一阵学了GIT还没好好实践,就在虚拟机中安装测试了一下,并简单记录了CENTOS6中GIT安装,ssh-keygen生成,客户端使用TortoiseGit加载KEYGEN连接GIT服 ...
- application windows are expected to have a root view controller错误
产生这个提示的操作:在xcode4.6中创建一个名字为appTest空工程,create一个ios-application-empty application,直接编译运行 错误提示:虽然编译通过,也 ...
- $.getJson()和$.ajax()同步处理
一.前言 为什么需要用到同步,因为有时候我们给一个提交按钮注册提交表单数据的时候,在提交动作之前会进行一系列的异步ajax请求操作,但是页面js代码会按顺序从上往下面执行,如果你在这过程中进行了异步操 ...
- git删除分支
git branch -d branchname删除一个分支需要具备的条件: 1 如果待删除的分支没有upstream branch,那么待删除的分支需要合并到HEAD上,否则需要使用-D强制删除 2 ...
- 【solr基础教程之一】Solr相关知识点串讲
Solr是Apache Lucene的一个子项目.Lucene为全文搜索功能提供了完备的API,但它只作为一个API库存在,而不能直接用于搜索.因此,Solr基于Lucene构建了一个完 ...