unity 有限状态机使用

2024-06-09 14:48
文章标签 使用 unity 状态机 有限

本文主要是介绍unity 有限状态机使用,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

有限状态机,(英语:Finite-state machine, FSM),又称有限状态自动机,简称状态机,是表示有限个状态以及在这些状态之间的转移和动作等行为的数学模型。状态存储关于过去的信息,它反映从系统开始到现在时刻输入的变化;转移指示状态变更,用必须满足来确使转移发生的条件来描述它;动作是在给定时刻要进行的活动描述。有多种类型的动作:
进入动作(entry action):在进入状态时进行;
退出动作:在退出状态时进行;
输入动作:依赖于当前状态和输入条件进行;
转移动作:在特定转移时进行。
游戏引擎是有限状态机最为成功的应用领域之一,由于设计良好的状态机能够被用来取代部分的人工智能算法,因此游戏中的每个角色或者器件都有可能内嵌一个状态机。考虑RPG游戏中城门这样一个简单的对象,它具有打开(Opened)、关闭(Closed)、上锁(Locked)、解锁(Unlocked)四种状态,如图1所示。当玩家到达一个处于状态Locked的门时,如果此时他已经找到了用来开门的钥匙,那么他就可以利用它将门的当前状态转变为Unlocked,进一步还可以通过旋转门上的把手将其状态转变为Opened,从而成功地进入城内。
在描述有限状态机时,状态、事件、转换和动作是经常会碰到的几个基本概念。
状态(State)指的是对象在其生命周期中的一种状况,处于某个特定状态中的对象必然会满足某些条件、执行某些动作或者是等待某些事件。
事件(Event)指的是在时间和空间上占有一定位置,并且对状态机来讲是有意义的那些事情。事件通常会引起状态的变迁,促使状态机从一种状态切换到另一种状态。
转换(Transition)指的是两个状态之间的一种关系,表明对象将在第一个状态中执行一定的动作,并将在某个事件发生同时某个特定条件满足时进入第二个状态。
动作(Action)指的是状态机中可以执行的那些原子操作,所谓原子操作指的是它们在运行的过程中不能被其他消息所中断,必须一直执行下去。
创建状态机的基类
“`
using UnityEngine;
using System.Collections;

public interface Istate {

uint GetStateId();//获取状态id
void EnterState(Istate preState);//进入状态
void LeaveState(Istate nextState);//离开状态
void OnUpdate();//更新状态
void OnFixedUpdate();//更新状态
void OnLateUpdate();//更新状态

}


创建状态管理类

using UnityEngine;
using System.Collections;

public class PatrolState : Istate
{
Transform player;
Transform enemy;
Transform[] paths;
Animator anim;
CharacterController cc;
int pathIndex = 0;
public PatrolState(Transform player, Transform enemy, Transform[] paths)
{
this.paths = paths;
this.player = player;
this.enemy = enemy;
anim = enemy.GetComponent();
cc = enemy.GetComponent();

}
public uint GetStateId()
{//获取状态idreturn (uint)EnemyStateId.PatrolState;
}public void EnterState(Istate preState)
{//设置动画为运动anim.SetBool("Idel", false);
}public void LeaveState(Istate nextState)
{}public void OnUpdate()
{//控制移动和移动方向enemy.LookAt(paths[pathIndex]);cc.SimpleMove(enemy.transform.forward * 3f);if (Vector3.Distance(enemy.position, paths[pathIndex].position) < 1){//当敌人与下一个节点距离小于1,转换节点pathIndex++;if (pathIndex >= paths.Length){pathIndex = 0;}}//当敌人与玩家距离小于15,切换为追击玩家状态if (Vector3.Distance(enemy.position, player.position) < 15){enemy.GetComponent<EnemyCtrl>().SwitchState((uint)EnemyStateId.ChaseState);}}public void OnFixedUpdate()
{}public void OnLateUpdate()
{}

}

“`
创建状态管理类

using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class StateMachine
{Dictionary<uint, Istate> stateDic = new Dictionary<uint, Istate>();Istate currentState;uint currentStateId;public Istate CurrentState{//获取当前状态get { return currentState; }}public uint CurrentStateId{//获取当前状态idget { return currentState.GetStateId(); }}public void RegisterState(Istate state){//如果状态没有被注册过,注册状态if (state == null || stateDic.ContainsKey(state.GetStateId())){return;}stateDic.Add(state.GetStateId(), state);}//切换状态public void SwitchState(uint stateId){if (currentState != null && stateId == currentStateId){return;}Istate newState;Istate oldState;stateDic.TryGetValue(stateId, out newState);if (newState != null){if(currentState!=null){currentState.LeaveState(newState);}oldState = currentState;currentState = newState;currentState.EnterState(oldState);}}public void Update(){if (currentState!=null){currentState.OnUpdate();}}public void FixedUpdate(){if (currentState != null){currentState.OnFixedUpdate();}}public void LateUpdate(){if (currentState != null){currentState.OnLateUpdate();}}}

UI管理类

using UnityEngine;
using System.Collections;
public enum EnemyStateId : uint
{NullState = 0, PatrolState, ChaseState, AttackState
}
public class EnemyCtrl : AttackAndDamage
{public Transform player;public Transform[] paths;private StateMachine fsm;//初始化void Awake(){//初始化状态机fsm = new StateMachine();}void Start(){//注册状态RegisterState();}private void RegisterState(){//注册状态fsm.RegisterState(new PatrolState(player, this.transform, paths));fsm.RegisterState(new ChaseState(player, this.transform));fsm.RegisterState(new AttackState(player, this.transform,baseAttack));fsm.SwitchState((uint)EnemyStateId.PatrolState);}public void SwitchState(uint stateId) {//进行状态切换fsm.SwitchState(stateId);}// 更新数据void Update(){//进行状态更新fsm.Update();}void FixedUpdate(){fsm.FixedUpdate();}void LateUpdate(){fsm.LateUpdate();}}

这篇关于unity 有限状态机使用的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1045486

相关文章

postgresql使用UUID函数的方法

《postgresql使用UUID函数的方法》本文给大家介绍postgresql使用UUID函数的方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录PostgreSQL有两种生成uuid的方法。可以先通过sql查看是否已安装扩展函数,和可以安装的扩展函数

如何使用Lombok进行spring 注入

《如何使用Lombok进行spring注入》本文介绍如何用Lombok简化Spring注入,推荐优先使用setter注入,通过注解自动生成getter/setter及构造器,减少冗余代码,提升开发效... Lombok为了开发环境简化代码,好处不用多说。spring 注入方式为2种,构造器注入和setter

MySQL中比较运算符的具体使用

《MySQL中比较运算符的具体使用》本文介绍了SQL中常用的符号类型和非符号类型运算符,符号类型运算符包括等于(=)、安全等于(=)、不等于(/!=)、大小比较(,=,,=)等,感兴趣的可以了解一下... 目录符号类型运算符1. 等于运算符=2. 安全等于运算符<=>3. 不等于运算符<>或!=4. 小于运

使用zip4j实现Java中的ZIP文件加密压缩的操作方法

《使用zip4j实现Java中的ZIP文件加密压缩的操作方法》本文介绍如何通过Maven集成zip4j1.3.2库创建带密码保护的ZIP文件,涵盖依赖配置、代码示例及加密原理,确保数据安全性,感兴趣的... 目录1. zip4j库介绍和版本1.1 zip4j库概述1.2 zip4j的版本演变1.3 zip4

Python 字典 (Dictionary)使用详解

《Python字典(Dictionary)使用详解》字典是python中最重要,最常用的数据结构之一,它提供了高效的键值对存储和查找能力,:本文主要介绍Python字典(Dictionary)... 目录字典1.基本特性2.创建字典3.访问元素4.修改字典5.删除元素6.字典遍历7.字典的高级特性默认字典

使用Python构建一个高效的日志处理系统

《使用Python构建一个高效的日志处理系统》这篇文章主要为大家详细讲解了如何使用Python开发一个专业的日志分析工具,能够自动化处理、分析和可视化各类日志文件,大幅提升运维效率,需要的可以了解下... 目录环境准备工具功能概述完整代码实现代码深度解析1. 类设计与初始化2. 日志解析核心逻辑3. 文件处

一文详解如何使用Java获取PDF页面信息

《一文详解如何使用Java获取PDF页面信息》了解PDF页面属性是我们在处理文档、内容提取、打印设置或页面重组等任务时不可或缺的一环,下面我们就来看看如何使用Java语言获取这些信息吧... 目录引言一、安装和引入PDF处理库引入依赖二、获取 PDF 页数三、获取页面尺寸(宽高)四、获取页面旋转角度五、判断

C++中assign函数的使用

《C++中assign函数的使用》在C++标准模板库中,std::list等容器都提供了assign成员函数,它比操作符更灵活,支持多种初始化方式,下面就来介绍一下assign的用法,具有一定的参考价... 目录​1.assign的基本功能​​语法​2. 具体用法示例​​​(1) 填充n个相同值​​(2)

Spring StateMachine实现状态机使用示例详解

《SpringStateMachine实现状态机使用示例详解》本文介绍SpringStateMachine实现状态机的步骤,包括依赖导入、枚举定义、状态转移规则配置、上下文管理及服务调用示例,重点解... 目录什么是状态机使用示例什么是状态机状态机是计算机科学中的​​核心建模工具​​,用于描述对象在其生命

使用Python删除Excel中的行列和单元格示例详解

《使用Python删除Excel中的行列和单元格示例详解》在处理Excel数据时,删除不需要的行、列或单元格是一项常见且必要的操作,本文将使用Python脚本实现对Excel表格的高效自动化处理,感兴... 目录开发环境准备使用 python 删除 Excphpel 表格中的行删除特定行删除空白行删除含指定