Unity3d实现有限状态机系统
来源:互联网 发布:java 方法名 编辑:程序博客网 时间:2024/06/01 08:24
原文地址:blog.liujunliang.com.cn
在之前有过介绍一个可视化有限状态机编辑器插件PlayerMaker
在这里也可以在我们的代码中实现一个状态机
本文源码地址:点击打开链接
首先创建一个脚本,来管理我们的各个状态
using System.Collections;using System.Collections.Generic;using UnityEngine;using System.Linq;/// <summary>/// 状态ID/// </summary>public enum FSMStateID{ NullFSMStateID, PatrolFSMStateID,//巡逻状态 ChaseFSMStateID,//追逐状态}/// <summary>/// 状态转化条件/// </summary>public enum FSMTransition{ SeePlayer,//看到主角(目标) LeavePlayer,//远离敌人(目标)}public class FSMSystem{ private FSMStateID mCurrentStateID; private FSMBaseState mCurrentState; private Dictionary<FSMStateID, FSMBaseState> mFSMStateDic = new Dictionary<FSMStateID, FSMBaseState>(); public void AddFSMSate(FSMBaseState state) { if (state == null) { Debug.Log("角色状态为空,无法添加"); return; } if (mCurrentState == null) { //第一个添加的状态被作为系统首个运行的状态 mCurrentStateID = state.mStateID; mCurrentState = state; mCurrentState.StateStart(); } if (mFSMStateDic.ContainsValue(state)) { Debug.Log("容器内存在该状态"); return; } mFSMStateDic.Add(state.mStateID, state); } public void DeleteFSMSate(FSMBaseState state) { if (state == null) { Debug.Log("角色状态为空,无法添加"); return; } if (!mFSMStateDic.ContainsValue(state)) { Debug.Log("容器内不存在该状态"); return; } mFSMStateDic.Remove(state.mStateID); } //更新(执行)系统 public void UpdateSystem() { if (mCurrentState != null) { mCurrentState.StateUpdate(); mCurrentState.TransitionReason(); } } //转换状态 public void TransitionFSMState(FSMTransition transition) { FSMStateID stateID = mCurrentState.GetStateIdByTransition(transition); if (stateID != FSMStateID.NullFSMStateID) { mCurrentStateID = stateID; mCurrentState.StateEnd(); //换状态 mCurrentState = mFSMStateDic.FirstOrDefault(q => q.Key == stateID).Value; mCurrentState.StateStart(); } }}
各个状态(巡逻状态、追逐状态)抽象理解为一个对象
创建一个状态基类,各个状态子类中可以继承重写这个基类方法
using System.Collections;using System.Collections.Generic;using UnityEngine;using System.Linq;public abstract class FSMBaseState{ public FSMStateID mStateID { get; set; } //状态ID public FSMSystem mFSMSystem { get; set; } //该对象属于在哪个状态机 public Dictionary<FSMTransition, FSMStateID> mFSMStateIdDic = new Dictionary<FSMTransition, FSMStateID>(); public FSMBaseState(FSMSystem fsmSystem, FSMStateID stateID) { this.mFSMSystem = fsmSystem; this.mStateID = stateID; } public void AddTransition(FSMTransition transition, FSMStateID stateID) { if (mFSMStateIdDic.ContainsKey(transition)) { Debug.Log("本状态已经包含了该转换条件"); return; } mFSMStateIdDic.Add(transition, stateID); } public void DeleteTransition(FSMTransition transition) { if (!mFSMStateIdDic.ContainsKey(transition)) { Debug.Log("容器中没有该转换条件"); return; } mFSMStateIdDic.Remove(transition); } public FSMStateID GetStateIdByTransition(FSMTransition transition) { if (!mFSMStateIdDic.ContainsKey(transition)) { Debug.Log("容器内没有该转换条件,无法获取状态"); return FSMStateID.NullFSMStateID; } return mFSMStateIdDic.FirstOrDefault(q => q.Key == transition).Value; } public abstract void StateStart(); public abstract void StateUpdate(); public abstract void StateEnd(); //转化状态条件 public abstract void TransitionReason();}
以下是巡逻状态
using System;using System.Collections;using System.Collections.Generic;using UnityEngine;public class FSMPatrolState : FSMBaseState{ //路径点 private List<Transform> mStargetPointTransform = new List<Transform>(); //路径点索引 private int mPointIndex = 0; //士兵 private GameObject mSliderObj { get; set; } //主角 private GameObject mPlayerObj { get; set; } //士兵移动速度 private float mMoveSpeed = 4f; public FSMPatrolState(FSMSystem fsmSystem) : base(fsmSystem, FSMStateID.PatrolFSMStateID) { } public override void StateStart() { //获取路径点 Transform[] transforms = GameObject.Find("Points").GetComponentsInChildren<Transform>(); foreach (var m_transform in transforms) { if (m_transform != GameObject.Find("Points").transform) { mStargetPointTransform.Add(m_transform); Debug.Log(m_transform.position); } } //获取士兵对象 mSliderObj = GameObject.Find("Slider"); //获取主角对象 mPlayerObj = GameObject.Find("Player"); } public override void StateUpdate() { //确实目标点并移动 mSliderObj.transform.LookAt(this.mStargetPointTransform[this.mPointIndex].position); mSliderObj.transform.Translate(Vector3.forward * Time.deltaTime * mMoveSpeed); if (Vector3.Distance(mSliderObj.transform.position, this.mStargetPointTransform[this.mPointIndex].position) < 0.5f) { //切换目标点 this.mPointIndex++; if (this.mPointIndex >= this.mStargetPointTransform.Count) { this.mPointIndex = 0; } } } public override void StateEnd() { } public override void TransitionReason() { if (Vector3.Distance(mSliderObj.transform.position, mPlayerObj.transform.position) <= 2.0f) { //转化状态 if (this.mFSMSystem == null) { Debug.Log("目标状态机为空"); return; } mFSMSystem.TransitionFSMState(FSMTransition.SeePlayer); } }}
以下是追逐状态
using System;using System.Collections;using System.Collections.Generic;using UnityEngine;public class FSMChaseState : FSMBaseState{ private GameObject mPlayerObj { get; set; } private GameObject mSliderObj { get; set; } private float mSliderMoveSpeed = 6.0f; public FSMChaseState(FSMSystem fsmSystem) : base(fsmSystem, FSMStateID.ChaseFSMStateID) { } public override void StateStart() { mPlayerObj = GameObject.Find("Player"); mSliderObj = GameObject.Find("Slider"); } public override void StateUpdate() { if (Vector3.Distance(mPlayerObj.transform.position, mSliderObj.transform.position) <= 10.0f) { //开始面向主角 mSliderObj.transform.LookAt(mPlayerObj.transform.position); //开始追逐 mSliderObj.transform.Translate(Vector3.forward * Time.deltaTime * mSliderMoveSpeed); } } public override void StateEnd() { } public override void TransitionReason() { //当主角远离敌人 if (Vector3.Distance(mPlayerObj.transform.position, mSliderObj.transform.position) > 10.0f) { //转化状态 if (this.mFSMSystem == null) { Debug.Log("目标状态机为空"); return; } mFSMSystem.TransitionFSMState(FSMTransition.LeavePlayer); } }}
该状态机的优点在于当有不同类型的状态时候,可以直接添加到状态系统内,而不要需要状态系统内部的运行逻辑
using System.Collections;using System.Collections.Generic;using UnityEngine;public class Slider : MonoBehaviour{ private FSMSystem fsmSystem { get; set; }void Start () { fsmSystem = new FSMSystem(); //巡逻状态,在构造参数传一个系统参数,确定该状态是在哪个状态系统中管理的,状态转换的时候调用 FSMBaseState patrolState = new FSMPatrolState(fsmSystem); patrolState.AddTransition(FSMTransition.SeePlayer, FSMStateID.ChaseFSMStateID);//巡逻状态转化条件 //追逐状态 FSMBaseState chaseState = new FSMChaseState(fsmSystem); chaseState.AddTransition(FSMTransition.LeavePlayer, FSMStateID.PatrolFSMStateID); fsmSystem.AddFSMSate(patrolState); fsmSystem.AddFSMSate(chaseState);}void Update () { fsmSystem.UpdateSystem();}}
原文地址:blog.liujunliang.com.cn
阅读全文
0 0
- Unity3d实现有限状态机系统
- unity3d 有限状态机
- UNITY3D有限状态机
- Unity3D 有限状态机(一)
- Unity3D-FSM有限状态机
- unity3d(C#)的有限状态机设计
- 游戏开发设计模式之状态模式 & 有限状态机 & c#委托事件(unity3d 示例实现)
- 游戏开发设计模式之状态模式 & 有限状态机 & c#委托事件(unity3d 示例实现)
- 有限状态机嵌入式系统
- Unity3D有限状态机(FSM)学习笔记【1】有限状态机总述
- 有限状态机的实现
- 实现简单有限状态机
- 有限状态机的实现
- 有限状态机的一个实现
- 有限状态机原理及实现
- C语言实现有限状态机
- C语言实现有限状态机
- C语言实现有限状态机
- JavaScript知识整理
- 排序算法和搜索算法
- [日推荐]麻麻再也不用担心你忘记密码啦!
- F
- 末日的传说 洛谷p1338
- Unity3d实现有限状态机系统
- Linux-入门常用基础命令
- Java 接口类型的创建及使用
- Imagej分析所有气泡的粒径
- 正则表达式的一些案例
- 常考的地址协议
- struts2 从入门到总结
- 54-多重继承(下)单继承多接口
- 将数字字符串转化成整数值