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

相关文章

Python通用唯一标识符模块uuid使用案例详解

《Python通用唯一标识符模块uuid使用案例详解》Pythonuuid模块用于生成128位全局唯一标识符,支持UUID1-5版本,适用于分布式系统、数据库主键等场景,需注意隐私、碰撞概率及存储优... 目录简介核心功能1. UUID版本2. UUID属性3. 命名空间使用场景1. 生成唯一标识符2. 数

SpringBoot中如何使用Assert进行断言校验

《SpringBoot中如何使用Assert进行断言校验》Java提供了内置的assert机制,而Spring框架也提供了更强大的Assert工具类来帮助开发者进行参数校验和状态检查,下... 目录前言一、Java 原生assert简介1.1 使用方式1.2 示例代码1.3 优缺点分析二、Spring Fr

Android kotlin中 Channel 和 Flow 的区别和选择使用场景分析

《Androidkotlin中Channel和Flow的区别和选择使用场景分析》Kotlin协程中,Flow是冷数据流,按需触发,适合响应式数据处理;Channel是热数据流,持续发送,支持... 目录一、基本概念界定FlowChannel二、核心特性对比数据生产触发条件生产与消费的关系背压处理机制生命周期

java使用protobuf-maven-plugin的插件编译proto文件详解

《java使用protobuf-maven-plugin的插件编译proto文件详解》:本文主要介绍java使用protobuf-maven-plugin的插件编译proto文件,具有很好的参考价... 目录protobuf文件作为数据传输和存储的协议主要介绍在Java使用maven编译proto文件的插件

SpringBoot线程池配置使用示例详解

《SpringBoot线程池配置使用示例详解》SpringBoot集成@Async注解,支持线程池参数配置(核心数、队列容量、拒绝策略等)及生命周期管理,结合监控与任务装饰器,提升异步处理效率与系统... 目录一、核心特性二、添加依赖三、参数详解四、配置线程池五、应用实践代码说明拒绝策略(Rejected

C++ Log4cpp跨平台日志库的使用小结

《C++Log4cpp跨平台日志库的使用小结》Log4cpp是c++类库,本文详细介绍了C++日志库log4cpp的使用方法,及设置日志输出格式和优先级,具有一定的参考价值,感兴趣的可以了解一下... 目录一、介绍1. log4cpp的日志方式2.设置日志输出的格式3. 设置日志的输出优先级二、Window

Ubuntu如何分配​​未使用的空间

《Ubuntu如何分配​​未使用的空间》Ubuntu磁盘空间不足,实际未分配空间8.2G因LVM卷组名称格式差异(双破折号误写)导致无法扩展,确认正确卷组名后,使用lvextend和resize2fs... 目录1:原因2:操作3:报错5:解决问题:确认卷组名称​6:再次操作7:验证扩展是否成功8:问题已解

Qt使用QSqlDatabase连接MySQL实现增删改查功能

《Qt使用QSqlDatabase连接MySQL实现增删改查功能》这篇文章主要为大家详细介绍了Qt如何使用QSqlDatabase连接MySQL实现增删改查功能,文中的示例代码讲解详细,感兴趣的小伙伴... 目录一、创建数据表二、连接mysql数据库三、封装成一个完整的轻量级 ORM 风格类3.1 表结构

使用Docker构建Python Flask程序的详细教程

《使用Docker构建PythonFlask程序的详细教程》在当今的软件开发领域,容器化技术正变得越来越流行,而Docker无疑是其中的佼佼者,本文我们就来聊聊如何使用Docker构建一个简单的Py... 目录引言一、准备工作二、创建 Flask 应用程序三、创建 dockerfile四、构建 Docker

Python使用vllm处理多模态数据的预处理技巧

《Python使用vllm处理多模态数据的预处理技巧》本文深入探讨了在Python环境下使用vLLM处理多模态数据的预处理技巧,我们将从基础概念出发,详细讲解文本、图像、音频等多模态数据的预处理方法,... 目录1. 背景介绍1.1 目的和范围1.2 预期读者1.3 文档结构概述1.4 术语表1.4.1 核