using UnityEngine;
using System.Collections;
public class NPCControler : MonoBehaviour {
private FSMSystem fsmSystem;
public Transform[] wayPoints;
// Use this for initialization
void Start () {
InitState();
}
public void InitState(){
GameObject player = GameObject.FindGameObjectWithTag("Player");
fsmSystem = new FSMSystem();
PatrolState patrolState = new PatrolState(wayPoints, gameObject, player);
fsmSystem.AddState(patrolState);
patrolState.AddTransition(Transition.SeePlayer, StateID.Patrol); //此处对应设置有问题,着重理解思想
ChaseState chaseState = new ChaseState(gameObject, player);
fsmSystem.AddState(chaseState);
chaseState.AddTransition(Transition.LostPlayer, StateID.Chase);
fsmSystem.FSMSystemStart(StateID.Patrol);
}
void Update()
{
fsmSystem.CurrentState.DoUpdate();
}
}
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class FSMSystem{
//已存在的状态
private Dictionary<StateID, FSMState> states;
//当前状态
private FSMState currentState;
public FSMState CurrentState
{
get
{
return currentState;
}
}
public FSMSystem()
{
states = new Dictionary<StateID,FSMState>();
}
public void AddState(FSMState state){
if(state == null){
Debug.LogError("The State is null");
return;
}
if(states.ContainsValue(state) == true)
{
Debug.LogError("The state is exit");
return;
}
state.fsmSystem = this;
states.Add(state.ID, state);
}
public void DeleteState(FSMState state)
{
if(states.ContainsValue(state) == false)
{
Debug.LogError("The state is not exit");
return;
}
states.Remove(state.ID);
}
//状态间的转换
public void PerformTransation(Transition trans)
{
if(trans == null)
{
Debug.LogError("The trans is null");
return;
}
if(trans == Transition.NullTransition)
{
Debug.LogError("Bull transition is not allowed");
return;
}
StateID id = currentState.GetOutputState(trans);
if(id == StateID.NullState)
{
Debug.LogError("The NullStateID id not allowed");
return;
}
Debug.Log("change State");
FSMState state;
states.TryGetValue(id, out state);
currentState = state;
currentState.DoBeforeEntering();
// currentState.DoAfterLeaving();
}
public void FSMSystemStart(StateID id)
{
FSMState state;
if (states.TryGetValue(id, out state))
{
currentState = state;
currentState.DoBeforeEntering();
}
else
{
Debug.LogError("The state id is not exit");
}
}
}
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
//状态转换的条件
public enum Transition
{
NullTransition = 0,
SeePlayer,
LostPlayer
}
//每个状态的ID
public enum StateID
{
NullState = 0,
Chase,
Patrol
}
public abstract class FSMState
{
protected StateID stateID;
public Dictionary<Transition, StateID> map = new Dictionary<Transition,StateID>();
public FSMSystem fsmSystem;
public StateID ID
{
get
{
return stateID;
}
}
public void AddTransition(Transition trans, StateID stateId)
{
//添加为空
if(trans == Transition.NullTransition || stateID == StateID.NullState)
{
Debug.Log("Transition or stateID is null");
return;
}
//已存在
if(map.ContainsKey(trans))
{
Debug.LogError("The " +trans + "is exit!" );
return;
}
map.Add(trans, stateID);
}
public void DeleteTransition(Transition trans)
{
if(map.ContainsKey(trans) == false)
{
Debug.LogError("The " + trans + "is not exit");
return;
}
map.Remove(trans);
}
//判断能否进行转换
public StateID GetOutputState(Transition trans)
{
if(map.ContainsKey(trans))
{
return map[trans];
}
return StateID.NullState;
}
//进入状态之前和之后的操作
public virtual void DoBeforeEntering() { }
public virtual void DoAfterLeaving(){}
public abstract void DoUpdate();
}
using UnityEngine;
using System.Collections;
public class PatrolState : FSMState{
private Transform[] wayPoints;
private GameObject npcGo;
private Rigidbody rigidebodyNPC;
private int waypointIndex = 0;
private GameObject player;
public PatrolState(Transform[] waypPoints, GameObject npcGo, GameObject player)
{
stateID = StateID.Patrol;
this.wayPoints = waypPoints;
this.npcGo = npcGo;
this.rigidebodyNPC = npcGo.GetComponent<Rigidbody>();
this.player = player;
}
public override void DoBeforeEntering()
{
Debug.Log("DoBeforeEntering");
}
public override void DoAfterLeaving()
{
Debug.Log("DeAfterLeaving");
}
public override void DoUpdate()
{
Patrol();
CheckTranslate();
}
void Patrol(){
//进行移动处理
rigidebodyNPC.velocity = npcGo.transform.forward * 3;
npcGo.transform.LookAt(wayPoints[waypointIndex]);
//Vector3 position = waypPoints[waypointIndex].transform.position;
//position.y = waypPoints[waypointIndex].transform.position.y;
//npcGo.transform.position = position;
if ((npcGo.transform.position - wayPoints[waypointIndex].transform.position).magnitude < 1f)
{
Debug.Log(waypointIndex);
waypointIndex++;
waypointIndex = waypointIndex % wayPoints.Length;
}
}
void CheckTranslate(){
//根据距离判断,转换状态
if(Vector3.Distance(npcGo.transform.position, player.transform.position) < 5)
{
Debug.Log("Transition.SeePlayer");
fsmSystem.PerformTransation(Transition.SeePlayer);
}
}
}
using UnityEngine;
using System.Collections;
public class ChaseState : FSMState {
private GameObject player;
private GameObject npc;
private Rigidbody rigidbodNPC;
public ChaseState(GameObject npc, GameObject player)
{
stateID = StateID.Chase;
this.player = player;
this.npc = npc;
rigidbodNPC = npc.GetComponent<Rigidbody>();
}
public override void DoUpdate()
{
//throw new System.NotImplementedException();
Debug.Log("Chase");
Move();
CheckTranslate();
}
public void Move(){
rigidbodNPC.velocity = npc.transform.forward * 3;
Vector3 position = player.transform.position;
npc.transform.LookAt(player.transform.position);
}
void CheckTranslate(){
//根据距离判断,转换状态
if(Vector3.Distance(npc.transform.position, player.transform.position) > 8)
{
Debug.Log("Transition.SeePlayer");
fsmSystem.PerformTransation(Transition.LostPlayer);
}
}
}