【转】有限状态机用法教程

如博文无法正常显示,请访问原文地址: https://blog.csdn.net/ChinarCSDN/article/details/82263126

 

有限状态机用法教程

 

文章目录

  • 有限状态机用法教程

  • @[toc]
  • 1
  • Finite-state machine —— 有限状态机
  • 2
  • Foreword —— 前言()
  • 3
  • Example —— 示例
  • 4
  • Moltimode —— 多状态
  • 5
  • GameManager ——游戏总控脚本
  • 6
  • View —— 视图脚本
  • 7
  • Final effect —— 最终效果
  • 8
  • Project —— 项目文件
  • 支持
  • May Be —— 搞开发,总有一天要做的事!

 

全文高清图片,点击即可放大观看 (很多人竟然不知道)

 


1

Finite-state machine —— 有限状态机



有限状态机简称: FSM —— 简称状态机

是表示有限个状态以及在这些状态之间的转移和动作等行为的数学模型


其他的不多说,对于我们开发者来说,状态机可以在全局视角下,管理我们的游戏状态/人物状态

使我们的工程逻辑清晰,将游戏/项目各个状态的转换,交由状态机统一管理

极大的避免了当状态过多 / 转换状态过多时,每次都需要调用相应函数来完成转换的麻烦


对于初学者来讲,套用状态机来对状态进行管理,可能认为过于麻烦

其实不用怕,那只是因为不熟悉用法和逻辑流程导致的

熟练的运用状态机来管理我们的项目状态,是很有必要的

那会使后期,我们的工程非常便于维护
New举例子黑白88


2

Foreword —— 前言()



网上的大神们为了更全面的阐述状态机的具体工作方式,他们有些说的极为详细

但对于初学者来讲,直接看这样的图解,教程,多数都是一脸懵逼

例如:(图片引用自网络大神博客)
在这里插入图片描述在这里插入图片描述

众所周知 Chinar 这些大神讲的略有不同

Chinar 会通过一些简单的例子,来带领初学者了解并学会如何使用状态机来管理我们的工程.

师傅领进门,修行靠个人 ,一切都需要先入门后,自己再慢慢扩展,不然一切都是扯淡


3

Example —— 示例



脚本引用自 Wiki.unity3d —— 源码链接

这里 Chinar 用一个简单的游戏状态切换逻辑来说明状态机用法

MVC 设计模式


FSM 一共2个类,不需要挂载到游戏对象上

FSMState 状态父类,所有子类状态都继承于这个类

例如以下工程:我们要需要2个状态: 菜单状态 与 游戏状态

那么这两个类MenuState 和 GameState都需要继承自 FSMState

New举例子黑白88
在这里插入图片描述
状态机脚本

<span style="color:#000000"><code class="language-c">using UnityEngine<span style="color:#999999">;</span>
using System<span style="color:#999999">.</span>Collections<span style="color:#999999">.</span>Generic<span style="color:#999999">;</span>
using UnityEngine<span style="color:#999999">.</span>Experimental<span style="color:#999999">.</span>PlayerLoop<span style="color:#999999">;</span><span style="color:#6272a4">/// <summary></span>
<span style="color:#6272a4">/// Place the labels for the Transitions in this enum. —— 在此枚举中放置转换的标签。</span>
<span style="color:#6272a4">/// Don't change the first label, NullTransition as FSMSystem class uses it. —— 不要改变第一个标签:NullTransition,因为FSMSystem类使用它。</span>
<span style="color:#6272a4">/// </summary></span>
public <span style="color:#ff79c6">enum</span> Transition
<span style="color:#999999">{</span>NullTransition <span style="color:#6272a4">=</span> <span style="color:#f1fa8c">0</span><span style="color:#999999">,</span> <span style="color:#6272a4">// Use this transition to represent a non-existing transition in your system —— 使用此转换表示系统中不存在的转换</span>Game<span style="color:#999999">,</span>               <span style="color:#6272a4">//转到游戏</span>Menu                <span style="color:#6272a4">//转到菜单</span>
<span style="color:#999999">}</span><span style="color:#6272a4">/// <summary></span>
<span style="color:#6272a4">/// Place the labels for the States in this enum. ——  在此枚举中放置状态的标签。</span>
<span style="color:#6272a4">/// Don't change the first label, NullStateID as FSMSystem class uses it.不要改变第一个标签:NullStateID,因为FSMSystem类使用它。</span>
<span style="color:#6272a4">/// </summary></span>
public <span style="color:#ff79c6">enum</span> StateID
<span style="color:#999999">{</span>NullStateId <span style="color:#6272a4">=</span> <span style="color:#f1fa8c">0</span><span style="color:#999999">,</span> <span style="color:#6272a4">// Use this ID to represent a non-existing State in your system —— 使用此ID表示系统中不存在的状态</span>Menu<span style="color:#999999">,</span>            <span style="color:#6272a4">//菜单</span>Game             <span style="color:#6272a4">//游戏</span>
<span style="color:#999999">}</span><span style="color:#6272a4">/// <summary></span>
<span style="color:#6272a4">/// This class represents the States in the Finite State System.该类表示有限状态系统中的状态。</span>
<span style="color:#6272a4">/// Each state has a Dictionary with pairs (transition-state) showing 每个状态都有一个对显示(转换状态)的字典</span>
<span style="color:#6272a4">/// which state the FSM should be if a transition is fired while this state is the current state.如果在此状态为当前状态时触发转换,则FSM应处于那种状态。</span>
<span style="color:#6272a4">/// Method Reason is used to determine which transition should be fired .方法原因用于确定应触发哪个转换。</span>
<span style="color:#6272a4">/// Method Act has the code to perform the actions the NPC is supposed do if it's on this state.方法具有执行NPC动作的代码应该在这种状态下执行。</span>
<span style="color:#6272a4">/// </summary></span>
public abstract class FSMState <span style="color:#999999">:</span> MonoBehaviour
<span style="color:#999999">{</span>public    Dictionary<span style="color:#6272a4"><</span>Transition<span style="color:#999999">,</span> StateID<span style="color:#6272a4">></span> map <span style="color:#6272a4">=</span> new Dictionary<span style="color:#6272a4"><</span>Transition<span style="color:#999999">,</span> StateID<span style="color:#6272a4">></span><span style="color:#999999">(</span><span style="color:#999999">)</span><span style="color:#999999">;</span> <span style="color:#6272a4">//字典 《转换,状态ID》</span>protected StateID                         stateID<span style="color:#999999">;</span>                                     <span style="color:#6272a4">//私有ID</span>public    StateID                         ID                                           <span style="color:#6272a4">//状态ID</span><span style="color:#999999">{</span>get <span style="color:#999999">{</span> <span style="color:#ff79c6">return</span> stateID<span style="color:#999999">;</span> <span style="color:#999999">}</span><span style="color:#999999">}</span>protected GameManager manager<span style="color:#999999">;</span> <span style="color:#6272a4">//保证子类状态可以访问到总控 GameManager</span>public    GameManager Manager<span style="color:#999999">{</span>set <span style="color:#999999">{</span> manager <span style="color:#6272a4">=</span> value<span style="color:#999999">;</span> <span style="color:#999999">}</span><span style="color:#999999">}</span><span style="color:#6272a4">/// <summary></span><span style="color:#6272a4">/// 添加转换</span><span style="color:#6272a4">/// </summary></span><span style="color:#6272a4">/// <param name="trans">转换状态</param></span><span style="color:#6272a4">/// <param name="id">转换ID</param></span>public <span style="color:#ff79c6">void</span> <span style="color:#8be9fd">AddTransition</span><span style="color:#999999">(</span>Transition trans<span style="color:#999999">,</span> StateID id<span style="color:#999999">)</span><span style="color:#999999">{</span><span style="color:#ff79c6">if</span> <span style="color:#999999">(</span>trans <span style="color:#6272a4">==</span> Transition<span style="color:#999999">.</span>NullTransition<span style="color:#999999">)</span> <span style="color:#6272a4">// Check if anyone of the args is invalid —— //检查是否有参数无效</span><span style="color:#999999">{</span>Debug<span style="color:#999999">.</span><span style="color:#8be9fd">LogError</span><span style="color:#999999">(</span><span style="color:#f1fa8c">"FSMState ERROR: NullTransition is not allowed for a real transition"</span><span style="color:#999999">)</span><span style="color:#999999">;</span><span style="color:#ff79c6">return</span><span style="color:#999999">;</span><span style="color:#999999">}</span><span style="color:#ff79c6">if</span> <span style="color:#999999">(</span>id <span style="color:#6272a4">==</span> StateID<span style="color:#999999">.</span>NullStateId<span style="color:#999999">)</span><span style="color:#999999">{</span>Debug<span style="color:#999999">.</span><span style="color:#8be9fd">LogError</span><span style="color:#999999">(</span><span style="color:#f1fa8c">"FSMState ERROR: NullStateID is not allowed for a real ID"</span><span style="color:#999999">)</span><span style="color:#999999">;</span><span style="color:#ff79c6">return</span><span style="color:#999999">;</span><span style="color:#999999">}</span><span style="color:#ff79c6">if</span> <span style="color:#999999">(</span>map<span style="color:#999999">.</span><span style="color:#8be9fd">ContainsKey</span><span style="color:#999999">(</span>trans<span style="color:#999999">)</span><span style="color:#999999">)</span> <span style="color:#6272a4">// Since this is a Deterministic FSM,check if the current transition was already inside the map —— 因为这是一个确定性FSM,检查当前的转换是否已经在字典中</span><span style="color:#999999">{</span>Debug<span style="color:#999999">.</span><span style="color:#8be9fd">LogError</span><span style="color:#999999">(</span><span style="color:#f1fa8c">"FSMState ERROR: State "</span> <span style="color:#6272a4">+</span> stateID<span style="color:#999999">.</span><span style="color:#8be9fd">ToString</span><span style="color:#999999">(</span><span style="color:#999999">)</span> <span style="color:#6272a4">+</span> <span style="color:#f1fa8c">" already has transition "</span> <span style="color:#6272a4">+</span> trans<span style="color:#999999">.</span><span style="color:#8be9fd">ToString</span><span style="color:#999999">(</span><span style="color:#999999">)</span> <span style="color:#6272a4">+</span><span style="color:#f1fa8c">"Impossible to assign to another state"</span><span style="color:#999999">)</span><span style="color:#999999">;</span><span style="color:#ff79c6">return</span><span style="color:#999999">;</span><span style="color:#999999">}</span>map<span style="color:#999999">.</span><span style="color:#8be9fd">Add</span><span style="color:#999999">(</span>trans<span style="color:#999999">,</span> id<span style="color:#999999">)</span><span style="color:#999999">;</span><span style="color:#999999">}</span><span style="color:#6272a4">/// <summary></span><span style="color:#6272a4">/// This method deletes a pair transition-state from this state's map. —— 该方法从状态映射中删除一对转换状态。</span><span style="color:#6272a4">/// If the transition was not inside the state's map, an ERROR message is printed. —— 如果转换不在状态映射内,则会打印一条错误消息。</span><span style="color:#6272a4">/// </summary></span>public <span style="color:#ff79c6">void</span> <span style="color:#8be9fd">DeleteTransition</span><span style="color:#999999">(</span>Transition trans<span style="color:#999999">)</span><span style="color:#999999">{</span><span style="color:#ff79c6">if</span> <span style="color:#999999">(</span>trans <span style="color:#6272a4">==</span> Transition<span style="color:#999999">.</span>NullTransition<span style="color:#999999">)</span> <span style="color:#6272a4">// Check for NullTransition —— 检查状态是否为空</span><span style="color:#999999">{</span>Debug<span style="color:#999999">.</span><span style="color:#8be9fd">LogError</span><span style="color:#999999">(</span><span style="color:#f1fa8c">"FSMState ERROR: NullTransition is not allowed"</span><span style="color:#999999">)</span><span style="color:#999999">;</span><span style="color:#ff79c6">return</span><span style="color:#999999">;</span><span style="color:#999999">}</span><span style="color:#ff79c6">if</span> <span style="color:#999999">(</span>map<span style="color:#999999">.</span><span style="color:#8be9fd">ContainsKey</span><span style="color:#999999">(</span>trans<span style="color:#999999">)</span><span style="color:#999999">)</span> <span style="color:#6272a4">// Check if the pair is inside the map before deleting —— 在删除之前,检查这一对是否在字典中</span><span style="color:#999999">{</span>map<span style="color:#999999">.</span><span style="color:#8be9fd">Remove</span><span style="color:#999999">(</span>trans<span style="color:#999999">)</span><span style="color:#999999">;</span><span style="color:#ff79c6">return</span><span style="color:#999999">;</span><span style="color:#999999">}</span>Debug<span style="color:#999999">.</span><span style="color:#8be9fd">LogError</span><span style="color:#999999">(</span><span style="color:#f1fa8c">"FSMState ERROR: Transition "</span> <span style="color:#6272a4">+</span> trans<span style="color:#999999">.</span><span style="color:#8be9fd">ToString</span><span style="color:#999999">(</span><span style="color:#999999">)</span> <span style="color:#6272a4">+</span> <span style="color:#f1fa8c">" passed to "</span> <span style="color:#6272a4">+</span> stateID<span style="color:#999999">.</span><span style="color:#8be9fd">ToString</span><span style="color:#999999">(</span><span style="color:#999999">)</span> <span style="color:#6272a4">+</span><span style="color:#f1fa8c">" was not on the state's transition list"</span><span style="color:#999999">)</span><span style="color:#999999">;</span><span style="color:#999999">}</span><span style="color:#6272a4">/// <summary></span><span style="color:#6272a4">/// This method returns the new state the FSM should be if this state receives a transition and—— 如果该状态接收到转换,该方法返回FSM应该为新状态</span><span style="color:#6272a4">/// 得到输出状态</span><span style="color:#6272a4">/// </summary></span>public StateID <span style="color:#8be9fd">GetOutputState</span><span style="color:#999999">(</span>Transition trans<span style="color:#999999">)</span><span style="color:#999999">{</span><span style="color:#ff79c6">if</span> <span style="color:#999999">(</span>map<span style="color:#999999">.</span><span style="color:#8be9fd">ContainsKey</span><span style="color:#999999">(</span>trans<span style="color:#999999">)</span><span style="color:#999999">)</span> <span style="color:#6272a4">// Check if the map has this transition —— 检查字典中是否有这个状态</span><span style="color:#999999">{</span><span style="color:#ff79c6">return</span> map<span style="color:#999999">[</span>trans<span style="color:#999999">]</span><span style="color:#999999">;</span><span style="color:#999999">}</span><span style="color:#ff79c6">return</span> StateID<span style="color:#999999">.</span>NullStateId<span style="color:#999999">;</span><span style="color:#999999">}</span><span style="color:#6272a4">/// <summary></span><span style="color:#6272a4">/// This method is used to set up the State condition before entering it. —— 该方法用于在进入状态条件之前设置状态条件。</span><span style="color:#6272a4">/// It is called automatically by the FSMSystem class before assigning it to the current state.—— 在分配它之前,FSMSystem类会自动调用它到当前状态</span><span style="color:#6272a4">/// </summary></span>public virtual <span style="color:#ff79c6">void</span> <span style="color:#8be9fd">DoBeforeEntering</span><span style="color:#999999">(</span><span style="color:#999999">)</span><span style="color:#999999">{</span><span style="color:#999999">}</span><span style="color:#6272a4">/// <summary></span><span style="color:#6272a4">/// 此方法用于在FSMSystem更改为另一个变量之前进行任何必要的修改。在切换到新状态之前,FSMSystem会自动调用它。</span><span style="color:#6272a4">/// This method is used to make anything necessary, as reseting variables</span><span style="color:#6272a4">/// before the FSMSystem changes to another one. It is called automatically</span><span style="color:#6272a4">/// by the FSMSystem before changing to a new state.</span><span style="color:#6272a4">/// </summary></span>public virtual <span style="color:#ff79c6">void</span> <span style="color:#8be9fd">DoBeforeLeaving</span><span style="color:#999999">(</span><span style="color:#999999">)</span><span style="color:#999999">{</span><span style="color:#999999">}</span><span style="color:#6272a4">/// <summary></span><span style="color:#6272a4">/// 这个方法决定状态是否应该转换到它列表上的另一个NPC是对这个类控制的对象的引用</span><span style="color:#6272a4">/// This method decides if the state should transition to another on its list</span><span style="color:#6272a4">/// NPC is a reference to the object that is controlled by this class</span><span style="color:#6272a4">/// </summary></span>public virtual <span style="color:#ff79c6">void</span> <span style="color:#8be9fd">Reason</span><span style="color:#999999">(</span><span style="color:#999999">)</span><span style="color:#999999">{</span><span style="color:#999999">}</span><span style="color:#6272a4">/// <summary></span><span style="color:#6272a4">/// 这种方法控制了NPC在游戏世界中的行为。</span><span style="color:#6272a4">/// NPC做的每一个动作、动作或交流都应该放在这里</span><span style="color:#6272a4">/// NPC是这个类控制的对象的引用</span><span style="color:#6272a4">/// This method controls the behavior of the NPC in the game World.</span><span style="color:#6272a4">/// Every action, movement or communication the NPC does should be placed here</span><span style="color:#6272a4">/// NPC is a reference to the object that is controlled by this class</span><span style="color:#6272a4">/// </summary></span>public virtual <span style="color:#ff79c6">void</span> <span style="color:#8be9fd">Act</span><span style="color:#999999">(</span><span style="color:#999999">)</span><span style="color:#999999">{</span><span style="color:#999999">}</span>
<span style="color:#999999">}</span><span style="color:#6272a4">/// <summary></span>
<span style="color:#6272a4">///  FSMSystem class represents the Finite State Machine class.FSMSystem类表示有限状态机类。</span>
<span style="color:#6272a4">///  It has a List with the States the NPC has and methods to add, 它句有一个状态列表,NPC有添加、删除状态和更改机器当前状态的方法。</span>
<span style="color:#6272a4">///  delete a state, and to change the current state the Machine is on.</span>
<span style="color:#6272a4">/// </summary></span>
public class FSMSystem
<span style="color:#999999">{</span>private List<span style="color:#6272a4"><</span>FSMState<span style="color:#6272a4">></span> states<span style="color:#999999">;</span> <span style="color:#6272a4">//状态集</span><span style="color:#6272a4">// The only way one can change the state of the FSM is by performing a transition 改变FSM状态的唯一方法是进行转换</span><span style="color:#6272a4">// Don't change the CurrentState directly 不要直接改变当前状态</span>private StateID currentStateID<span style="color:#999999">;</span>public  StateID CurrentStateID<span style="color:#999999">{</span>get <span style="color:#999999">{</span> <span style="color:#ff79c6">return</span> currentStateID<span style="color:#999999">;</span> <span style="color:#999999">}</span><span style="color:#999999">}</span>private FSMState currentState<span style="color:#999999">;</span>public  FSMState CurrentState<span style="color:#999999">{</span>get <span style="color:#999999">{</span> <span style="color:#ff79c6">return</span> currentState<span style="color:#999999">;</span> <span style="color:#999999">}</span><span style="color:#999999">}</span><span style="color:#6272a4">/// <summary></span><span style="color:#6272a4">/// 默认构造函数</span><span style="color:#6272a4">/// </summary></span>public <span style="color:#8be9fd">FSMSystem</span><span style="color:#999999">(</span><span style="color:#999999">)</span><span style="color:#999999">{</span>states <span style="color:#6272a4">=</span> new List<span style="color:#6272a4"><</span>FSMState<span style="color:#6272a4">></span><span style="color:#999999">(</span><span style="color:#999999">)</span><span style="color:#999999">;</span><span style="color:#999999">}</span><span style="color:#6272a4">/// <summary></span><span style="color:#6272a4">/// 设置当前状态</span><span style="color:#6272a4">/// </summary></span><span style="color:#6272a4">/// <param name="state">初始状态</param></span>public <span style="color:#ff79c6">void</span> <span style="color:#8be9fd">SetCurrentState</span><span style="color:#999999">(</span>FSMState state<span style="color:#999999">)</span><span style="color:#999999">{</span>currentState   <span style="color:#6272a4">=</span> state<span style="color:#999999">;</span>currentStateID <span style="color:#6272a4">=</span> state<span style="color:#999999">.</span>ID<span style="color:#999999">;</span>state<span style="color:#999999">.</span><span style="color:#8be9fd">DoBeforeEntering</span><span style="color:#999999">(</span><span style="color:#999999">)</span><span style="color:#999999">;</span> <span style="color:#6272a4">//开始前状态切换</span><span style="color:#999999">}</span><span style="color:#6272a4">/// <summary></span><span style="color:#6272a4">/// This method places new states inside the FSM, —— 这个方法在FSM内部放置一个放置一个新状态</span><span style="color:#6272a4">/// or prints an ERROR message if the state was already inside the List. —— 或者,如果状态已经在列表中,则打印错误消息。</span><span style="color:#6272a4">/// First state added is also the initial state. 第一个添加的状态也是初始状态。</span><span style="color:#6272a4">/// </summary></span>public <span style="color:#ff79c6">void</span> <span style="color:#8be9fd">AddState</span><span style="color:#999999">(</span>FSMState fsmState<span style="color:#999999">,</span> GameManager manager<span style="color:#999999">)</span><span style="color:#999999">{</span><span style="color:#6272a4">// Check for Null reference before deleting 删除前判空</span><span style="color:#ff79c6">if</span> <span style="color:#999999">(</span>fsmState <span style="color:#6272a4">==</span> null<span style="color:#999999">)</span><span style="color:#999999">{</span>Debug<span style="color:#999999">.</span><span style="color:#8be9fd">LogError</span><span style="color:#999999">(</span><span style="color:#f1fa8c">"FSM ERROR: Null reference is not allowed"</span><span style="color:#999999">)</span><span style="color:#999999">;</span><span style="color:#999999">}</span><span style="color:#ff79c6">else</span> <span style="color:#6272a4">// First State inserted is also the Initial state, —— 插入的第一个状态也是初始状态,// the state the machine is in when the simulation begins —— 状态机是在模拟开始时</span><span style="color:#999999">{</span>fsmState<span style="color:#999999">.</span>Manager <span style="color:#6272a4">=</span> manager<span style="color:#999999">;</span> <span style="color:#6272a4">//给每个状态添加总控 GameManager</span><span style="color:#ff79c6">if</span> <span style="color:#999999">(</span>states<span style="color:#999999">.</span>Count <span style="color:#6272a4">==</span> <span style="color:#f1fa8c">0</span><span style="color:#999999">)</span><span style="color:#999999">{</span>states<span style="color:#999999">.</span><span style="color:#8be9fd">Add</span><span style="color:#999999">(</span>fsmState<span style="color:#999999">)</span><span style="color:#999999">;</span><span style="color:#ff79c6">return</span><span style="color:#999999">;</span><span style="color:#999999">}</span>foreach <span style="color:#999999">(</span>FSMState state in states<span style="color:#999999">)</span> <span style="color:#6272a4">// Add the state to the List if it's not inside it 如果状态不在列表中,则将其添加到列表中  (添加状态ID)</span><span style="color:#999999">{</span><span style="color:#ff79c6">if</span> <span style="color:#999999">(</span>state<span style="color:#999999">.</span>ID <span style="color:#6272a4">==</span> fsmState<span style="color:#999999">.</span>ID<span style="color:#999999">)</span><span style="color:#999999">{</span>Debug<span style="color:#999999">.</span><span style="color:#8be9fd">LogError</span><span style="color:#999999">(</span><span style="color:#f1fa8c">"FSM ERROR: Impossible to add state "</span> <span style="color:#6272a4">+</span> fsmState<span style="color:#999999">.</span>ID<span style="color:#999999">.</span><span style="color:#8be9fd">ToString</span><span style="color:#999999">(</span><span style="color:#999999">)</span> <span style="color:#6272a4">+</span><span style="color:#f1fa8c">" because state has already been added"</span><span style="color:#999999">)</span><span style="color:#999999">;</span><span style="color:#ff79c6">return</span><span style="color:#999999">;</span><span style="color:#999999">}</span><span style="color:#999999">}</span>states<span style="color:#999999">.</span><span style="color:#8be9fd">Add</span><span style="color:#999999">(</span>fsmState<span style="color:#999999">)</span><span style="color:#999999">;</span><span style="color:#999999">}</span><span style="color:#999999">}</span><span style="color:#6272a4">/// <summary></span><span style="color:#6272a4">/// This method delete a state from the FSM List if it exists,  —— 这个方法从FSM列表中删除一个存在的状态,</span><span style="color:#6272a4">///   or prints an ERROR message if the state was not on the List. —— 或者,如果状态不存在,则打印错误信息</span><span style="color:#6272a4">/// </summary></span>public <span style="color:#ff79c6">void</span> <span style="color:#8be9fd">DeleteState</span><span style="color:#999999">(</span>StateID id<span style="color:#999999">)</span><span style="color:#999999">{</span><span style="color:#ff79c6">if</span> <span style="color:#999999">(</span>id <span style="color:#6272a4">==</span> StateID<span style="color:#999999">.</span>NullStateId<span style="color:#999999">)</span> <span style="color:#6272a4">// Check for NullState before deleting —— 判空</span><span style="color:#999999">{</span>Debug<span style="color:#999999">.</span><span style="color:#8be9fd">LogError</span><span style="color:#999999">(</span><span style="color:#f1fa8c">"FSM ERROR: NullStateID is not allowed for a real state"</span><span style="color:#999999">)</span><span style="color:#999999">;</span><span style="color:#ff79c6">return</span><span style="color:#999999">;</span><span style="color:#999999">}</span>foreach <span style="color:#999999">(</span>FSMState state in states<span style="color:#999999">)</span> <span style="color:#6272a4">// Search the List and delete the state if it's inside it  搜索列表并删除其中的状态</span><span style="color:#999999">{</span><span style="color:#ff79c6">if</span> <span style="color:#999999">(</span>state<span style="color:#999999">.</span>ID <span style="color:#6272a4">==</span> id<span style="color:#999999">)</span><span style="color:#999999">{</span>states<span style="color:#999999">.</span><span style="color:#8be9fd">Remove</span><span style="color:#999999">(</span>state<span style="color:#999999">)</span><span style="color:#999999">;</span><span style="color:#ff79c6">return</span><span style="color:#999999">;</span><span style="color:#999999">}</span><span style="color:#999999">}</span>Debug<span style="color:#999999">.</span><span style="color:#8be9fd">LogError</span><span style="color:#999999">(</span><span style="color:#f1fa8c">"FSM ERROR: Impossible to delete state "</span> <span style="color:#6272a4">+</span> id<span style="color:#999999">.</span><span style="color:#8be9fd">ToString</span><span style="color:#999999">(</span><span style="color:#999999">)</span> <span style="color:#6272a4">+</span><span style="color:#f1fa8c">". It was not on the list of states"</span><span style="color:#999999">)</span><span style="color:#999999">;</span><span style="color:#999999">}</span><span style="color:#6272a4">/// <summary></span><span style="color:#6272a4">/// This method tries to change the state the FSM is in based on</span><span style="color:#6272a4">/// the current state and the transition passed. If current state</span><span style="color:#6272a4">///  doesn't have a target state for the transition passed, </span><span style="color:#6272a4">/// an ERROR message is printed.</span><span style="color:#6272a4">/// 该方法尝试根据当前状态和已通过的转换改变FSM所处的状态。如果当前状态没有传递的转换的目标状态,则输出错误消息。</span><span style="color:#6272a4">/// </summary></span>public <span style="color:#ff79c6">void</span> <span style="color:#8be9fd">PerformTransition</span><span style="color:#999999">(</span>Transition trans<span style="color:#999999">)</span><span style="color:#999999">{</span><span style="color:#ff79c6">if</span> <span style="color:#999999">(</span>trans <span style="color:#6272a4">==</span> Transition<span style="color:#999999">.</span>NullTransition<span style="color:#999999">)</span> <span style="color:#6272a4">// Check for NullTransition before changing the current state 在更改当前状态之前检查是否有NullTransition</span><span style="color:#999999">{</span>Debug<span style="color:#999999">.</span><span style="color:#8be9fd">LogError</span><span style="color:#999999">(</span><span style="color:#f1fa8c">"FSM ERROR: NullTransition is not allowed for a real transition"</span><span style="color:#999999">)</span><span style="color:#999999">;</span><span style="color:#ff79c6">return</span><span style="color:#999999">;</span><span style="color:#999999">}</span>StateID id <span style="color:#6272a4">=</span> currentState<span style="color:#999999">.</span><span style="color:#8be9fd">GetOutputState</span><span style="color:#999999">(</span>trans<span style="color:#999999">)</span><span style="color:#999999">;</span> <span style="color:#6272a4">// Check if the currentState has the transition passed as argument 检查currentState是否将转换作为参数传递</span><span style="color:#ff79c6">if</span> <span style="color:#999999">(</span>id <span style="color:#6272a4">==</span> StateID<span style="color:#999999">.</span>NullStateId<span style="color:#999999">)</span><span style="color:#999999">{</span>Debug<span style="color:#999999">.</span><span style="color:#8be9fd">LogError</span><span style="color:#999999">(</span><span style="color:#f1fa8c">"FSM ERROR: State "</span> <span style="color:#6272a4">+</span> currentStateID<span style="color:#999999">.</span><span style="color:#8be9fd">ToString</span><span style="color:#999999">(</span><span style="color:#999999">)</span> <span style="color:#6272a4">+</span> <span style="color:#f1fa8c">" does not have a target state "</span> <span style="color:#6272a4">+</span><span style="color:#f1fa8c">" for transition "</span> <span style="color:#6272a4">+</span> trans<span style="color:#999999">.</span><span style="color:#8be9fd">ToString</span><span style="color:#999999">(</span><span style="color:#999999">)</span><span style="color:#999999">)</span><span style="color:#999999">;</span><span style="color:#ff79c6">return</span><span style="color:#999999">;</span><span style="color:#999999">}</span>currentStateID <span style="color:#6272a4">=</span> id<span style="color:#999999">;</span> <span style="color:#6272a4">// Update the currentStateID and currentState		更新当前状态和ID</span>foreach <span style="color:#999999">(</span>FSMState state in states<span style="color:#999999">)</span><span style="color:#999999">{</span><span style="color:#ff79c6">if</span> <span style="color:#999999">(</span>state<span style="color:#999999">.</span>ID <span style="color:#6272a4">==</span> currentStateID<span style="color:#999999">)</span><span style="color:#999999">{</span>currentState<span style="color:#999999">.</span><span style="color:#8be9fd">DoBeforeLeaving</span><span style="color:#999999">(</span><span style="color:#999999">)</span><span style="color:#999999">;</span> <span style="color:#6272a4">// Do the post processing of the state before setting the new one 在设置新状态之前是否对状态进行后处理</span>currentState <span style="color:#6272a4">=</span> state<span style="color:#999999">;</span>currentState<span style="color:#999999">.</span><span style="color:#8be9fd">DoBeforeEntering</span><span style="color:#999999">(</span><span style="color:#999999">)</span><span style="color:#999999">;</span> <span style="color:#6272a4">// Reset the state to its desired condition before it can reason or act 在它推动和动作之前,重置状态到它所需的条件</span><span style="color:#ff79c6">break</span><span style="color:#999999">;</span><span style="color:#999999">}</span><span style="color:#999999">}</span><span style="color:#999999">}</span>
<span style="color:#999999">}</span>
</code></span>

4

Multimode —— 多状态



菜单状态脚本:MenuState

游戏状态脚本:GameState

我们来控制这两个状态,交由状态机进行切换
New举例子黑白88

菜单脚本

<span style="color:#000000"><code class="language-c"><span style="color:#6272a4">/// <summary></span>
<span style="color:#6272a4">/// 菜单状态</span>
<span style="color:#6272a4">/// </summary></span>
public class MenuState <span style="color:#999999">:</span> FSMState
<span style="color:#999999">{</span><span style="color:#ff79c6">void</span> <span style="color:#8be9fd">Awake</span><span style="color:#999999">(</span><span style="color:#999999">)</span><span style="color:#999999">{</span>stateID <span style="color:#6272a4">=</span> StateID<span style="color:#999999">.</span>Menu<span style="color:#999999">;</span><span style="color:#8be9fd">AddTransition</span><span style="color:#999999">(</span>Transition<span style="color:#999999">.</span>Game<span style="color:#999999">,</span> StateID<span style="color:#999999">.</span>Game<span style="color:#999999">)</span><span style="color:#999999">;</span> <span style="color:#6272a4">//(菜单状态下:需要转游戏)→→添加转换,转换游戏 —— 对应游戏状态</span><span style="color:#6272a4">//map.Add(Transition.Game, StateID.Game);//上边也可这么写</span><span style="color:#999999">}</span><span style="color:#ff79c6">void</span> <span style="color:#8be9fd">Start</span><span style="color:#999999">(</span><span style="color:#999999">)</span><span style="color:#999999">{</span>manager<span style="color:#999999">.</span>View<span style="color:#999999">.</span>StartButton<span style="color:#999999">.</span>onClick<span style="color:#999999">.</span><span style="color:#8be9fd">AddListener</span><span style="color:#999999">(</span>OnStarGameClick<span style="color:#999999">)</span><span style="color:#999999">;</span><span style="color:#999999">}</span><span style="color:#6272a4">/// <summary></span><span style="color:#6272a4">/// 开始游戏</span><span style="color:#6272a4">/// </summary></span>public <span style="color:#ff79c6">void</span> <span style="color:#8be9fd">OnStarGameClick</span><span style="color:#999999">(</span><span style="color:#999999">)</span><span style="color:#999999">{</span>manager<span style="color:#999999">.</span>Fsm<span style="color:#999999">.</span><span style="color:#8be9fd">PerformTransition</span><span style="color:#999999">(</span>Transition<span style="color:#999999">.</span>Game<span style="color:#999999">)</span><span style="color:#999999">;</span><span style="color:#999999">}</span><span style="color:#6272a4">/// <summary></span><span style="color:#6272a4">/// 进入该状态时</span><span style="color:#6272a4">/// </summary></span>public override <span style="color:#ff79c6">void</span> <span style="color:#8be9fd">DoBeforeEntering</span><span style="color:#999999">(</span><span style="color:#999999">)</span><span style="color:#999999">{</span>manager<span style="color:#999999">.</span>View<span style="color:#999999">.</span><span style="color:#8be9fd">ShowMenuUi</span><span style="color:#999999">(</span><span style="color:#999999">)</span><span style="color:#999999">;</span><span style="color:#999999">}</span><span style="color:#6272a4">/// <summary></span><span style="color:#6272a4">/// 离开该状态时</span><span style="color:#6272a4">/// </summary></span>public override <span style="color:#ff79c6">void</span> <span style="color:#8be9fd">DoBeforeLeaving</span><span style="color:#999999">(</span><span style="color:#999999">)</span><span style="color:#999999">{</span>manager<span style="color:#999999">.</span>View<span style="color:#999999">.</span><span style="color:#8be9fd">HideMenuUi</span><span style="color:#999999">(</span><span style="color:#999999">)</span><span style="color:#999999">;</span><span style="color:#999999">}</span>
<span style="color:#999999">}</span>
</code></span>

游戏脚本

<span style="color:#000000"><code class="language-c"><span style="color:#6272a4">/// <summary></span>
<span style="color:#6272a4">/// 游戏状态</span>
<span style="color:#6272a4">/// </summary></span>
public class GameState <span style="color:#999999">:</span> FSMState
<span style="color:#999999">{</span><span style="color:#ff79c6">void</span> <span style="color:#8be9fd">Awake</span><span style="color:#999999">(</span><span style="color:#999999">)</span><span style="color:#999999">{</span>stateID <span style="color:#6272a4">=</span> StateID<span style="color:#999999">.</span>Game<span style="color:#999999">;</span><span style="color:#8be9fd">AddTransition</span><span style="color:#999999">(</span>Transition<span style="color:#999999">.</span>Menu<span style="color:#999999">,</span> StateID<span style="color:#999999">.</span>Menu<span style="color:#999999">)</span><span style="color:#999999">;</span> <span style="color:#6272a4">//(游戏状态下:点击暂停需要转菜单)→→添加转换,转换菜单—— 对应菜单状态</span><span style="color:#6272a4">//map.Add(Transition.Menu, StateID.Menu);//上边也可这么写</span><span style="color:#999999">}</span><span style="color:#ff79c6">void</span> <span style="color:#8be9fd">Start</span><span style="color:#999999">(</span><span style="color:#999999">)</span><span style="color:#999999">{</span>manager<span style="color:#999999">.</span>View<span style="color:#999999">.</span>PauseButton<span style="color:#999999">.</span>onClick<span style="color:#999999">.</span><span style="color:#8be9fd">AddListener</span><span style="color:#999999">(</span>OnPauseButton<span style="color:#999999">)</span><span style="color:#999999">;</span><span style="color:#999999">}</span><span style="color:#6272a4">/// <summary></span><span style="color:#6272a4">/// 暂停</span><span style="color:#6272a4">/// </summary></span>public <span style="color:#ff79c6">void</span> <span style="color:#8be9fd">OnPauseButton</span><span style="color:#999999">(</span><span style="color:#999999">)</span><span style="color:#999999">{</span>manager<span style="color:#999999">.</span>Fsm<span style="color:#999999">.</span><span style="color:#8be9fd">PerformTransition</span><span style="color:#999999">(</span>Transition<span style="color:#999999">.</span>Menu<span style="color:#999999">)</span><span style="color:#999999">;</span><span style="color:#999999">}</span><span style="color:#6272a4">/// <summary></span><span style="color:#6272a4">/// 进入该状态时</span><span style="color:#6272a4">/// </summary></span>public override <span style="color:#ff79c6">void</span> <span style="color:#8be9fd">DoBeforeEntering</span><span style="color:#999999">(</span><span style="color:#999999">)</span><span style="color:#999999">{</span>manager<span style="color:#999999">.</span>View<span style="color:#999999">.</span><span style="color:#8be9fd">ShowGameUi</span><span style="color:#999999">(</span><span style="color:#999999">)</span><span style="color:#999999">;</span><span style="color:#999999">}</span><span style="color:#6272a4">/// <summary></span><span style="color:#6272a4">/// 离开该状态时</span><span style="color:#6272a4">/// </summary></span>public override <span style="color:#ff79c6">void</span> <span style="color:#8be9fd">DoBeforeLeaving</span><span style="color:#999999">(</span><span style="color:#999999">)</span><span style="color:#999999">{</span>manager<span style="color:#999999">.</span>View<span style="color:#999999">.</span><span style="color:#8be9fd">HideGameUi</span><span style="color:#999999">(</span><span style="color:#999999">)</span><span style="color:#999999">;</span><span style="color:#999999">}</span>
<span style="color:#999999">}</span>
</code></span>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45

5

GameManager ——游戏总控脚本



游戏总控脚本:GameManager —— 用来控制全局游戏逻辑 ©

我们在这个脚本中,将所有状态批量添加到状态机中

这里我通过修改,传入了 GameManager 到所有状态中

这样我们后期可以在各个状态中完成对 GameManager中函数的调用,同时节省了代码,逻辑也非常清晰


New举例子黑白88

游戏总控脚本

<span style="color:#000000"><code class="language-c">using UnityEngine<span style="color:#999999">;</span><span style="color:#6272a4">/// <summary></span>
<span style="color:#6272a4">/// 游戏总控脚本</span>
<span style="color:#6272a4">/// </summary></span>
public class GameManager <span style="color:#999999">:</span> MonoBehaviour
<span style="color:#999999">{</span>public FSMSystem Fsm<span style="color:#999999">;</span>  <span style="color:#6272a4">//有限状态机系统对象</span>public View      View<span style="color:#999999">;</span> <span style="color:#6272a4">// 显示层</span>private <span style="color:#ff79c6">void</span> <span style="color:#8be9fd">Awake</span><span style="color:#999999">(</span><span style="color:#999999">)</span><span style="color:#999999">{</span>View <span style="color:#6272a4">=</span> GameObject<span style="color:#999999">.</span><span style="color:#8be9fd">FindGameObjectWithTag</span><span style="color:#999999">(</span><span style="color:#f1fa8c">"View"</span><span style="color:#999999">)</span><span style="color:#999999">.</span>GetComponent<span style="color:#6272a4"><</span>View<span style="color:#6272a4">></span><span style="color:#999999">(</span><span style="color:#999999">)</span><span style="color:#999999">;</span> <span style="color:#6272a4">//这里要给 View 游戏对象设置标签 "View"</span><span style="color:#6272a4">//添加所有状态到状态集(这里,我也通过修改,将 GameManager传到所有状态中,简化代码,便于调用)</span>Fsm               <span style="color:#6272a4">=</span> new <span style="color:#8be9fd">FSMSystem</span><span style="color:#999999">(</span><span style="color:#999999">)</span><span style="color:#999999">;</span>                     <span style="color:#6272a4">//调用构造函数,内部会自动初始化 状态集</span>FSMState<span style="color:#999999">[</span><span style="color:#999999">]</span> states <span style="color:#6272a4">=</span> GetComponentsInChildren<span style="color:#6272a4"><</span>FSMState<span style="color:#6272a4">></span><span style="color:#999999">(</span><span style="color:#999999">)</span><span style="color:#999999">;</span> <span style="color:#6272a4">//找到所有 状态</span>foreach <span style="color:#999999">(</span>FSMState state in states<span style="color:#999999">)</span><span style="color:#999999">{</span>Fsm<span style="color:#999999">.</span><span style="color:#8be9fd">AddState</span><span style="color:#999999">(</span>state<span style="color:#999999">,</span> this<span style="color:#999999">)</span><span style="color:#999999">;</span> <span style="color:#6272a4">//将状态,逐个添加到 状态机中</span><span style="color:#999999">}</span>MenuState menuState <span style="color:#6272a4">=</span> GetComponentInChildren<span style="color:#6272a4"><</span>MenuState<span style="color:#6272a4">></span><span style="color:#999999">(</span><span style="color:#999999">)</span><span style="color:#999999">;</span>Fsm<span style="color:#999999">.</span><span style="color:#8be9fd">SetCurrentState</span><span style="color:#999999">(</span>menuState<span style="color:#999999">)</span><span style="color:#999999">;</span> <span style="color:#6272a4">//默认状态是 菜单状态</span><span style="color:#999999">}</span>
<span style="color:#999999">}</span>
</code></span>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28

6

View —— 视图脚本



用 View 脚本来对我们所有 UI 元素进行赋值与管理

项目中引用了 DoTween 插件,来完成对UI简单动画的控制
New举例子黑白88

视图脚本

<span style="color:#000000"><code class="language-c">using DG<span style="color:#999999">.</span>Tweening<span style="color:#999999">;</span>
using UnityEngine<span style="color:#999999">;</span>
using UnityEngine<span style="color:#999999">.</span>UI<span style="color:#999999">;</span><span style="color:#6272a4">/// <summary></span>
<span style="color:#6272a4">/// 视图脚本 —— 管理UI元素</span>
<span style="color:#6272a4">/// </summary></span>
public class View <span style="color:#999999">:</span> MonoBehaviour
<span style="color:#999999">{</span>private RectTransform menuUi<span style="color:#999999">;</span>      <span style="color:#6272a4">//菜单页</span>private RectTransform gameUi<span style="color:#999999">;</span>      <span style="color:#6272a4">//游戏页</span>public  Button        StartButton<span style="color:#999999">;</span> <span style="color:#6272a4">//开始按钮</span>public  Button        PauseButton<span style="color:#999999">;</span> <span style="color:#6272a4">//暂停按钮</span>public  Ease          PubEase<span style="color:#999999">;</span><span style="color:#6272a4">/// <summary></span><span style="color:#6272a4">/// 初始化函数</span><span style="color:#6272a4">/// </summary></span><span style="color:#ff79c6">void</span> <span style="color:#8be9fd">Awake</span><span style="color:#999999">(</span><span style="color:#999999">)</span><span style="color:#999999">{</span>menuUi      <span style="color:#6272a4">=</span> <span style="color:#999999">(</span>RectTransform<span style="color:#999999">)</span> <span style="color:#8be9fd">Find</span><span style="color:#999999">(</span><span style="color:#f1fa8c">"Menu Ui"</span><span style="color:#999999">)</span><span style="color:#999999">;</span>gameUi      <span style="color:#6272a4">=</span> <span style="color:#999999">(</span>RectTransform<span style="color:#999999">)</span> <span style="color:#8be9fd">Find</span><span style="color:#999999">(</span><span style="color:#f1fa8c">"Game Ui"</span><span style="color:#999999">)</span><span style="color:#999999">;</span>StartButton <span style="color:#6272a4">=</span> <span style="color:#8be9fd">Find</span><span style="color:#999999">(</span><span style="color:#f1fa8c">"Menu Ui/Menu Button"</span><span style="color:#999999">)</span><span style="color:#999999">.</span>GetComponent<span style="color:#6272a4"><</span>Button<span style="color:#6272a4">></span><span style="color:#999999">(</span><span style="color:#999999">)</span><span style="color:#999999">;</span>PauseButton <span style="color:#6272a4">=</span> <span style="color:#8be9fd">Find</span><span style="color:#999999">(</span><span style="color:#f1fa8c">"Game Ui/Pause Button"</span><span style="color:#999999">)</span><span style="color:#999999">.</span>GetComponent<span style="color:#6272a4"><</span>Button<span style="color:#6272a4">></span><span style="color:#999999">(</span><span style="color:#999999">)</span><span style="color:#999999">;</span><span style="color:#999999">}</span><span style="color:#6272a4">/// <summary></span><span style="color:#6272a4">/// 显示菜单页</span><span style="color:#6272a4">/// </summary></span>public <span style="color:#ff79c6">void</span> <span style="color:#8be9fd">ShowMenuUi</span><span style="color:#999999">(</span><span style="color:#999999">)</span><span style="color:#999999">{</span>menuUi<span style="color:#999999">.</span><span style="color:#8be9fd">DOScale</span><span style="color:#999999">(</span>new <span style="color:#8be9fd">Vector3</span><span style="color:#999999">(</span><span style="color:#f1fa8c">0.3f</span><span style="color:#999999">,</span> <span style="color:#f1fa8c">0.3f</span><span style="color:#999999">,</span> <span style="color:#f1fa8c">0.3f</span><span style="color:#999999">)</span><span style="color:#999999">,</span> <span style="color:#f1fa8c">0.1f</span><span style="color:#999999">)</span><span style="color:#999999">.</span><span style="color:#8be9fd">OnComplete</span><span style="color:#999999">(</span><span style="color:#999999">(</span><span style="color:#999999">)</span> <span style="color:#6272a4">=</span><span style="color:#6272a4">></span><span style="color:#999999">{</span>menuUi<span style="color:#999999">.</span><span style="color:#8be9fd">DOScale</span><span style="color:#999999">(</span>Vector3<span style="color:#999999">.</span>one<span style="color:#999999">,</span> <span style="color:#f1fa8c">0.3f</span><span style="color:#999999">)</span><span style="color:#999999">;</span>StartButton<span style="color:#999999">.</span>enabled <span style="color:#6272a4">=</span> true<span style="color:#999999">;</span><span style="color:#999999">}</span><span style="color:#999999">)</span><span style="color:#999999">.</span><span style="color:#8be9fd">SetEase</span><span style="color:#999999">(</span>PubEase<span style="color:#999999">)</span><span style="color:#999999">;</span>menuUi<span style="color:#999999">.</span><span style="color:#8be9fd">DOAnchorPos</span><span style="color:#999999">(</span>Vector2<span style="color:#999999">.</span>zero<span style="color:#999999">,</span> <span style="color:#f1fa8c">0.3f</span><span style="color:#999999">)</span><span style="color:#999999">.</span><span style="color:#8be9fd">SetEase</span><span style="color:#999999">(</span>PubEase<span style="color:#999999">)</span><span style="color:#999999">;</span><span style="color:#999999">}</span><span style="color:#6272a4">/// <summary></span><span style="color:#6272a4">/// 隐藏菜单页</span><span style="color:#6272a4">/// </summary></span>public <span style="color:#ff79c6">void</span> <span style="color:#8be9fd">HideMenuUi</span><span style="color:#999999">(</span><span style="color:#999999">)</span><span style="color:#999999">{</span>menuUi<span style="color:#999999">.</span><span style="color:#8be9fd">DOScale</span><span style="color:#999999">(</span>new <span style="color:#8be9fd">Vector3</span><span style="color:#999999">(</span><span style="color:#f1fa8c">0.3f</span><span style="color:#999999">,</span> <span style="color:#f1fa8c">0.3f</span><span style="color:#999999">,</span> <span style="color:#f1fa8c">0.3f</span><span style="color:#999999">)</span><span style="color:#999999">,</span> <span style="color:#f1fa8c">0.1f</span><span style="color:#999999">)</span><span style="color:#999999">.</span><span style="color:#8be9fd">OnComplete</span><span style="color:#999999">(</span><span style="color:#999999">(</span><span style="color:#999999">)</span> <span style="color:#6272a4">=</span><span style="color:#6272a4">></span><span style="color:#999999">{</span>menuUi<span style="color:#999999">.</span><span style="color:#8be9fd">DOAnchorPos</span><span style="color:#999999">(</span>new <span style="color:#8be9fd">Vector2</span><span style="color:#999999">(</span><span style="color:#6272a4">-</span><span style="color:#f1fa8c">600</span><span style="color:#999999">,</span> <span style="color:#6272a4">-</span><span style="color:#f1fa8c">450</span><span style="color:#999999">)</span><span style="color:#999999">,</span> <span style="color:#f1fa8c">0.3f</span><span style="color:#999999">)</span><span style="color:#999999">;</span>menuUi<span style="color:#999999">.</span><span style="color:#8be9fd">DOScale</span><span style="color:#999999">(</span>Vector3<span style="color:#999999">.</span>zero<span style="color:#999999">,</span> <span style="color:#f1fa8c">0.3f</span><span style="color:#999999">)</span><span style="color:#999999">.</span><span style="color:#8be9fd">OnComplete</span><span style="color:#999999">(</span><span style="color:#999999">(</span><span style="color:#999999">)</span> <span style="color:#6272a4">=</span><span style="color:#6272a4">></span> <span style="color:#999999">{</span> StartButton<span style="color:#999999">.</span>enabled <span style="color:#6272a4">=</span> false<span style="color:#999999">;</span> <span style="color:#999999">}</span><span style="color:#999999">)</span><span style="color:#999999">.</span><span style="color:#8be9fd">SetEase</span><span style="color:#999999">(</span>PubEase<span style="color:#999999">)</span><span style="color:#999999">;</span><span style="color:#999999">}</span><span style="color:#999999">)</span><span style="color:#999999">.</span><span style="color:#8be9fd">SetEase</span><span style="color:#999999">(</span>PubEase<span style="color:#999999">)</span><span style="color:#999999">;</span><span style="color:#999999">}</span><span style="color:#6272a4">/// <summary></span><span style="color:#6272a4">/// 显示游戏页</span><span style="color:#6272a4">/// </summary></span>public <span style="color:#ff79c6">void</span> <span style="color:#8be9fd">ShowGameUi</span><span style="color:#999999">(</span><span style="color:#999999">)</span><span style="color:#999999">{</span>gameUi<span style="color:#999999">.</span><span style="color:#8be9fd">DOScale</span><span style="color:#999999">(</span>new <span style="color:#8be9fd">Vector3</span><span style="color:#999999">(</span><span style="color:#f1fa8c">0.3f</span><span style="color:#999999">,</span> <span style="color:#f1fa8c">0.3f</span><span style="color:#999999">,</span> <span style="color:#f1fa8c">0.3f</span><span style="color:#999999">)</span><span style="color:#999999">,</span> <span style="color:#f1fa8c">0.1f</span><span style="color:#999999">)</span><span style="color:#999999">.</span><span style="color:#8be9fd">OnComplete</span><span style="color:#999999">(</span><span style="color:#999999">(</span><span style="color:#999999">)</span> <span style="color:#6272a4">=</span><span style="color:#6272a4">></span><span style="color:#999999">{</span>gameUi<span style="color:#999999">.</span><span style="color:#8be9fd">DOScale</span><span style="color:#999999">(</span>Vector3<span style="color:#999999">.</span>one<span style="color:#999999">,</span> <span style="color:#f1fa8c">0.3f</span><span style="color:#999999">)</span><span style="color:#999999">;</span>PauseButton<span style="color:#999999">.</span>enabled <span style="color:#6272a4">=</span> true<span style="color:#999999">;</span><span style="color:#999999">}</span><span style="color:#999999">)</span><span style="color:#999999">.</span><span style="color:#8be9fd">SetEase</span><span style="color:#999999">(</span>PubEase<span style="color:#999999">)</span><span style="color:#999999">;</span>gameUi<span style="color:#999999">.</span><span style="color:#8be9fd">DOAnchorPos</span><span style="color:#999999">(</span>Vector2<span style="color:#999999">.</span>zero<span style="color:#999999">,</span> <span style="color:#f1fa8c">0.3f</span><span style="color:#999999">)</span><span style="color:#999999">.</span><span style="color:#8be9fd">SetEase</span><span style="color:#999999">(</span>PubEase<span style="color:#999999">)</span><span style="color:#999999">;</span><span style="color:#999999">}</span><span style="color:#6272a4">/// <summary></span><span style="color:#6272a4">/// 隐藏游戏页</span><span style="color:#6272a4">/// </summary></span>public <span style="color:#ff79c6">void</span> <span style="color:#8be9fd">HideGameUi</span><span style="color:#999999">(</span><span style="color:#999999">)</span><span style="color:#999999">{</span>gameUi<span style="color:#999999">.</span><span style="color:#8be9fd">DOScale</span><span style="color:#999999">(</span>new <span style="color:#8be9fd">Vector3</span><span style="color:#999999">(</span><span style="color:#f1fa8c">0.3f</span><span style="color:#999999">,</span> <span style="color:#f1fa8c">0.3f</span><span style="color:#999999">,</span> <span style="color:#f1fa8c">0.3f</span><span style="color:#999999">)</span><span style="color:#999999">,</span> <span style="color:#f1fa8c">0.1f</span><span style="color:#999999">)</span><span style="color:#999999">.</span><span style="color:#8be9fd">OnComplete</span><span style="color:#999999">(</span><span style="color:#999999">(</span><span style="color:#999999">)</span> <span style="color:#6272a4">=</span><span style="color:#6272a4">></span><span style="color:#999999">{</span>gameUi<span style="color:#999999">.</span><span style="color:#8be9fd">DOAnchorPos</span><span style="color:#999999">(</span>new <span style="color:#8be9fd">Vector2</span><span style="color:#999999">(</span><span style="color:#6272a4">-</span><span style="color:#f1fa8c">600</span><span style="color:#999999">,</span> <span style="color:#6272a4">-</span><span style="color:#f1fa8c">450</span><span style="color:#999999">)</span><span style="color:#999999">,</span> <span style="color:#f1fa8c">0.3f</span><span style="color:#999999">)</span><span style="color:#999999">;</span>gameUi<span style="color:#999999">.</span><span style="color:#8be9fd">DOScale</span><span style="color:#999999">(</span>Vector3<span style="color:#999999">.</span>zero<span style="color:#999999">,</span> <span style="color:#f1fa8c">0.3f</span><span style="color:#999999">)</span><span style="color:#999999">.</span><span style="color:#8be9fd">OnComplete</span><span style="color:#999999">(</span><span style="color:#999999">(</span><span style="color:#999999">)</span> <span style="color:#6272a4">=</span><span style="color:#6272a4">></span> <span style="color:#999999">{</span> PauseButton<span style="color:#999999">.</span>enabled <span style="color:#6272a4">=</span> false<span style="color:#999999">;</span> <span style="color:#999999">}</span><span style="color:#999999">)</span><span style="color:#999999">.</span><span style="color:#8be9fd">SetEase</span><span style="color:#999999">(</span>PubEase<span style="color:#999999">)</span><span style="color:#999999">;</span><span style="color:#999999">}</span><span style="color:#999999">)</span><span style="color:#999999">.</span><span style="color:#8be9fd">SetEase</span><span style="color:#999999">(</span>PubEase<span style="color:#999999">)</span><span style="color:#999999">;</span><span style="color:#999999">}</span><span style="color:#6272a4">/// <summary></span><span style="color:#6272a4">/// 查找对Ui元素完成赋值</span><span style="color:#6272a4">/// </summary></span><span style="color:#6272a4">/// <param name="uiElement">Ui名查找路径</param></span>Transform <span style="color:#8be9fd">Find</span><span style="color:#999999">(</span>string uiElement<span style="color:#999999">)</span><span style="color:#999999">{</span><span style="color:#ff79c6">return</span> transform<span style="color:#999999">.</span><span style="color:#8be9fd">Find</span><span style="color:#999999">(</span><span style="color:#f1fa8c">"Canvas/"</span> <span style="color:#6272a4">+</span> uiElement<span style="color:#999999">)</span><span style="color:#999999">;</span><span style="color:#999999">}</span>
<span style="color:#999999">}</span>
</code></span>

7

Final effect —— 最终效果



我们通过状态机简单的完成了 开始游戏 和暂停的状态切换

代码中注释写的非常详细了,请初学者认真看下

具体流程就是:

1. GameManager 完成将所有子类状态添加到状态集中

2. View 获取到我们所需要的所有 UI 元素对象,并提供公有方法可供各个状态访问

3. 确认好各个状态的进入 与离开时机发生时,需要执行的事件,并交由状态机去管理!

状态进入:DoBeforeEntering()
状态离开:DoBeforeLeaving()

4. 例子较为简单,为了方便初学者理解学习只写了2个状态

根据需求,大家可以举一反三,多写几个状态练习一下,其实流程很简单!


8

Project —— 项目文件



项目文件为 unitypackage 文件包:

下载导入 Unity 即可使用

New举例子黑白88

点击下载 —— 项目资源 (积分支持)

点击下载 —— 项目资源 (Chinar免费)

最终效果: (由于GIF录制 60帧数的限制,所以我点击太快了,看着有些卡似得)
在这里插入图片描述

 

至此:状态机教程结束

 


支持

May Be —— 搞开发,总有一天要做的事!

 

拥有自己的服务器,无需再找攻略!

Chinar 提供一站式教程,闭眼式创建!

为新手节省宝贵时间,避免采坑!

 

先点击领取 —— 阿里全产品优惠券 (享受最低优惠)


 

1 —— 云服务器超全购买流程 (新手必备!)


2 —— 阿里ECS云服务器自定义配置 - 购买教程(新手必备!)


3—— Windows 服务器配置、运行、建站一条龙 !


4 —— Linux 服务器配置、运行、建站一条龙 !


 

 

技术交流群:806091680 ! Chinar 欢迎你的加入

 


END

本博客为非营利性个人原创,除部分有明确署名的作品外,所刊登的所有作品的著作权均为本人所拥有,本人保留所有法定权利。违者必究

对于需要复制、转载、链接和传播博客文章或内容的,请及时和本博主进行联系,留言,Email: ichinar@icloud.com

对于经本博主明确授权和许可使用文章及内容的,使用时请注明文章或内容出处并注明网址

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/437112.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

通用usb集线器驱动_多口充电、高速传输——ORICO晶锐系列7口集线器测评

随着笔电越来越薄&#xff0c;机身接口数量越来越少&#xff0c;U盘、存储卡、移动硬盘、鼠标、蓝牙适配器等明显感觉无处可插&#xff0c;因此USB集线器就成为笔电的最佳拍档。近期&#xff0c;ORICO(奥睿科)推出了一款晶锐系列7口集线器产品&#xff0c;它集成了7个USB3.0接口…

信息系统中的树

代码树 作用域树 类树 窗口树 文件系统树 图形场景树 设备树 Git版本树

【转】C#开发笔记之05-迭代器中的状态机(State Machine)到底是什么?

C#开发笔记概述 该文章的最新版本已迁移至个人博客【比特飞】&#xff0c;单击链接 https://www.byteflying.com/archives/961 访问。 状态机可以理解为实现了备忘录模式&#xff08;仅作为理解&#xff09;的、能够记录状态的机器&#xff0c;这个机器记录的是某个对象的中间…

python两个集合相减_python集合的运算,两个集合相减是什么意思

&#xfeff;# 在对集合做运算时&#xff0c;不会影响原来的集合&#xff0c;而是返回一个运算结果# 创建两个集合s {1,2,3,4,5}s2 {3,4,5,6,7}# & 交集运算result s & s2 # {3, 4, 5}# | 并集运算result s | s2 # {1,2,3,4,5,6,7}# - 差集result s - s2 # {1, 2}…

什么是runtime?

常见的有以下类型 C/C编译型静态语言的runtimeObjective C的编译型动态语言runtimeJAVA运行在虚拟机上的准动态语言的runtime runtime就是程序运行时的环境&#xff0c;指程序中除去程序开发者编写的代码剩下的那部分代码&#xff0c;它存在的目的是实现语言特性、运行特性、…

【转】状态机思路在程序设计中的应用

状态机思路在单片机程序设计中的应用 状态机的概念 状态机是软件编程中的一个重要概念。比这个概念更重要的是对它的灵活应用。在一个思路清晰而且高效的程序中&#xff0c;必然有状态机的身影浮现。 比如说一个按键命令解析程序&#xff0c;就可以被看做状态机&#xff1a;本…

python表格处理免费教程_手把手教你用Python处理Excel表格

openpyxl是一个第三方库&#xff0c;可以处理xlsx格式的Excel文件。pip install openpyxl安装。读取Excel文件需要导入相关函数from openpyxl import load_workbook# 默认可读写&#xff0c;若有需要可以指定write_only和read_only为Truewb load_workbook(pythontab.xlsx)默认…

LNK2019:无法解析的外部符号

原因1&#xff1a; .lib里面的函数没有导出。 原因2&#xff1a; 没有链接.lib文件 原因3&#xff1a; 没有添加.lib文件所在目录到库目录。 原因4&#xff1a; 所引用的lib文件引用了其他.lib文件&#xff0c;而这个.lib你也要引入进来。 原因5&#xff1a; 导出库是…

【转】超详细的UML状态图符号,初学者也能轻松看懂状态图

UML状态图&#xff0c;用于显示状态机&#xff0c;即描述一个对象所处的可能状态以及状态之间的转移。用状态图建模可以帮助开发人员分析复杂对象的各种状态的转换&#xff0c;以及对象何时执行怎样的动作。那状态图又是怎样表示这些信息的呢&#xff1f;要想看明白其中的奥妙&…

舒尔特注意力训练表格_舒尔特注意力训练,舒尔特方格练习入口

孩子的注意力是否集中&#xff0c;直接影响孩子的上课效率和作业正确率&#xff0c;最终影响学习成绩。道理大家都懂&#xff0c;关键是如何保证注意力的集中。接下来&#xff0c;我给大家推荐一个简单方便在家就能完成的训练方法&#xff0c;把它比作小游戏也不为过。那就是舒…

VS静态库和动态库的区别

静态库&#xff1a; 没有链接完整依赖就能生成成功&#xff0c;使用者在使用时会涉及到链接问题&#xff0c;弱引用&#xff0c;只是记录的引用。 动态库&#xff1a; 必须链接完整依赖才能生成成功 &#xff0c;强引用。

【转】浅析C# 状态机Stateless

最近在折腾一些控制相关的软件设计&#xff0c;想起来 状态机 这个东西&#xff0c;对解决一些控制系统状态切换还是挺有用的。 状态机&#xff08;有限状态自动机&#xff09;网上有很多介绍。简单理解就是定义一系列状态&#xff0c;通过一系列的事件&#xff0c;可以使得状…

nginx文件系统大小_Nginx 了解一下?

这篇文章主要简单的介绍下 Nginx 的相关知识&#xff0c;主要包括以下几部分内容&#xff1a;Nginx 适用于哪些场景&#xff1f;为什么会出现 Nginx&#xff1f;Nginx 优点Nginx 的编译与配置Nginx 适用于哪些场景&#xff1f;如图所示&#xff0c;一个请求会先经过 Nginx 到达…

QGIS笔记

地理信息系统 地理信息系统&#xff0c;可以看做是地理信息附加信息组成的。地理信息是研究对象&#xff0c;附加信息是研究结果&#xff0c;二者结合展示给用户查阅。 地理信息系统的核心是数据&#xff0c;界面是为了渲染数据。 其他 特征Feature是指一行记录。属性表即数…

存储过程排版工具_安利一款比Evernote更为实用的云笔记工具,不容错过

作为一个爱分享的自媒体人&#xff0c;出于工作和兴趣前前后后接触到的云笔记工具很多&#xff0c;例如&#xff1a;有道云笔记、为知笔记、语雀、印象笔记、oneNote...在笔记工具的使用上还是略有点点心得&#xff0c;今天给大家分享一款实用的云笔记工具——Baklib&#xff0…

【转】有限状态机(FSM)学习总结C#

FSM&#xff08;Finite State Machine有限状态机&#xff09;可以理解成是对行为逻辑的抽象&#xff0c;就好象人在生活中会做出各种行为&#xff0c;例如吃饭、睡觉等&#xff0c;这些所有我们都看作是“行为”的分支&#xff0c;由大脑决定每种行为具体是什么实施。在整个FSM…

一篇关于Qt开发技巧的文章收藏

跨平台C开发&#xff1a;10年Qt开发经验覆盖100多个Qt开发技巧&#xff01;-控件新闻-慧都网 (evget.com)

【转】C#数据结构-有限状态机

有限状态机FSM的要点是&#xff1a; 拥有一组状态&#xff0c;并且可以在这组状态之间进行切换。 状态机同时只能在一个状态。 一连串的输入或事件被发送给机器。 每个状态都有一系列的转换&#xff0c;转换与输入和另一状态相关。当输入进来&#xff0c;如果它与当前…

python中if嵌套语句的作用_讲解Python中if语句的嵌套用法

{"moduleinfo":{"card_count":[{"count_phone":1,"count":1}],"search_count":[{"count_phone":4,"count":4}]},"card":[{"des":"阿里技术人对外发布原创技术内容的最大平台&…

ffmpeg录屏鼠标闪烁问题解决方法

场景&#xff1a; 平台&#xff1a;win7 x64。显卡很差的电脑&#xff0c;使用ffmpeg录屏&#xff0c;鼠标闪烁的几乎看不到。录屏实现方法是使用ffmpeg&#xff0c;源采用的是gdigrab。 解决方法&#xff1a; 安装screen capture recorder安装ffmpeg&#xff0c;执行命令ff…