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

相关文章

SpringBoot中使用 ThreadLocal 进行多线程上下文管理及注意事项小结

《SpringBoot中使用ThreadLocal进行多线程上下文管理及注意事项小结》本文详细介绍了ThreadLocal的原理、使用场景和示例代码,并在SpringBoot中使用ThreadLo... 目录前言技术积累1.什么是 ThreadLocal2. ThreadLocal 的原理2.1 线程隔离2

Python itertools中accumulate函数用法及使用运用详细讲解

《Pythonitertools中accumulate函数用法及使用运用详细讲解》:本文主要介绍Python的itertools库中的accumulate函数,该函数可以计算累积和或通过指定函数... 目录1.1前言:1.2定义:1.3衍生用法:1.3Leetcode的实际运用:总结 1.1前言:本文将详

浅析如何使用Swagger生成带权限控制的API文档

《浅析如何使用Swagger生成带权限控制的API文档》当涉及到权限控制时,如何生成既安全又详细的API文档就成了一个关键问题,所以这篇文章小编就来和大家好好聊聊如何用Swagger来生成带有... 目录准备工作配置 Swagger权限控制给 API 加上权限注解查看文档注意事项在咱们的开发工作里,API

Java数字转换工具类NumberUtil的使用

《Java数字转换工具类NumberUtil的使用》NumberUtil是一个功能强大的Java工具类,用于处理数字的各种操作,包括数值运算、格式化、随机数生成和数值判断,下面就来介绍一下Number... 目录一、NumberUtil类概述二、主要功能介绍1. 数值运算2. 格式化3. 数值判断4. 随机

Spring排序机制之接口与注解的使用方法

《Spring排序机制之接口与注解的使用方法》本文介绍了Spring中多种排序机制,包括Ordered接口、PriorityOrdered接口、@Order注解和@Priority注解,提供了详细示例... 目录一、Spring 排序的需求场景二、Spring 中的排序机制1、Ordered 接口2、Pri

Springboot 中使用Sentinel的详细步骤

《Springboot中使用Sentinel的详细步骤》文章介绍了如何在SpringBoot中使用Sentinel进行限流和熔断降级,首先添加依赖,配置Sentinel控制台地址,定义受保护的资源,... 目录步骤 1: 添加 Sentinel 依赖步骤 2: 配置 Sentinel步骤 3: 定义受保护的

Python中Markdown库的使用示例详解

《Python中Markdown库的使用示例详解》Markdown库是一个用于处理Markdown文本的Python工具,这篇文章主要为大家详细介绍了Markdown库的具体使用,感兴趣的... 目录一、背景二、什么是 Markdown 库三、如何安装这个库四、库函数使用方法1. markdown.mark

使用Navicat工具比对两个数据库所有表结构的差异案例详解

《使用Navicat工具比对两个数据库所有表结构的差异案例详解》:本文主要介绍如何使用Navicat工具对比两个数据库test_old和test_new,并生成相应的DDLSQL语句,以便将te... 目录概要案例一、如图两个数据库test_old和test_new进行比较:二、开始比较总结概要公司存在多

CSS3中使用flex和grid实现等高元素布局的示例代码

《CSS3中使用flex和grid实现等高元素布局的示例代码》:本文主要介绍了使用CSS3中的Flexbox和Grid布局实现等高元素布局的方法,通过简单的两列实现、每行放置3列以及全部代码的展示,展示了这两种布局方式的实现细节和效果,详细内容请阅读本文,希望能对你有所帮助... 过往的实现方法是使用浮动加

如何使用Spring boot的@Transactional进行事务管理

《如何使用Springboot的@Transactional进行事务管理》这篇文章介绍了SpringBoot中使用@Transactional注解进行声明式事务管理的详细信息,包括基本用法、核心配置... 目录一、前置条件二、基本用法1. 在方法上添加注解2. 在类上添加注解三、核心配置参数1. 传播行为(