类银河恶魔城学习记录1-1 Player状态机的搭建 P28

对状态机的介绍

什么是状态机?一篇文章就够了 - 知乎

说实话,目前并不能深入理解状态机的奇妙之处(当然,我觉得状态机作为教程的重要组成部分是不得不理解的,所以以下我会对游戏教程内的状态机做一些我认为的解释,如有错误,请多包涵)

基本的Player状态机组成

基本的Player状态机,我认为由4个部分组成

1.Player脚本,与Player组件绑定,能提供Unity自带的MonoBehavior来实现游戏内的更新与初始化。

2.PlayerState脚本,作为所有的状态,例如游戏角色奔跑状态,静止状态的父脚本,提供一个最基础的框架

3.PlayerStateMachine脚本,作为在一定条件下,转换一个角色的状态的机器。及从奔跑状态转移到静止状态的脚本

4.Player-XX-State脚本,继承了PlayerState脚本,但是实际上表示了真正的具体的动作的脚本。

简单实例说明

源代码
Player.cs
using System.Collections;
using System.Collections.Generic;
using Unity.VisualScripting;
using UnityEngine;public class Player : MonoBehaviour
{#region 定义Statespublic PlayerStateMachine stateMachine { get; private set; }public PlayerIdleState idleState { get; private set; }public PlayerMoveState moveState { get; private set; }#endregionprivate void Awake(){stateMachine = new PlayerStateMachine();//通过构造函数,在构造时传递信息idleState = new PlayerIdleState(this, stateMachine, "Idle");moveState = new PlayerMoveState(this, stateMachine, "Move");//this 就是 Player这个类本身}//Awake初始化所以State,为所有State传入各自独有的参数,及animBool,以判断是否调用此动画(与animatoin配合完成)private void Start(){stateMachine.Initialize(idleState);}private void Update()//在mano中update会自动刷新但其他没有mano的不会故,需要在这个updata中调用其他脚本中的函数stateMachine.currentState.update以实现 //stateMachine中的update{stateMachine.currentState.Update();//反复调用CurrentState的Update函数}
}
PlayerState.cs
using System.Collections;
using System.Collections.Generic;
using System.Security.Authentication.ExtendedProtection;
using UnityEngine;
//被继承的总类,后面的所以state都需要继承它
//实际上Player并没有进入过这个状态,没有调用此脚本,所有的调用均属于此脚本的子脚本
public class PlayerState
{protected PlayerStateMachine stateMachine;//创建PlayerStateMachine类,以对其进行控制protected Player player;//创建Player类,以对其进行控制private string animBoolName;//控制此时的anim的BOOL值public PlayerState(Player _player,PlayerStateMachine _stateMachine,string _animBoolName){this.player = _player;this.stateMachine = _stateMachine;                                                this.animBoolName = _animBoolName;}//构造函数,用于传递信息public virtual void Enter(){Debug.Log("I enter+" + animBoolName);}public virtual void Update(){Debug.Log("I'm in+" + animBoolName);}public virtual void Exit(){Debug.Log("I exit " + animBoolName);}}
 PlayerStateMachine.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class PlayerStateMachine
{public PlayerState currentState { get; private set; }public void Initialize(PlayerState _startState){currentState = _startState;currentState.Enter();}//初始化状态函数,及通过将idleState传送进来,以便于调用idleState中的Enter函数public void ChangeState(PlayerState _newState){currentState.Exit();currentState = _newState;currentState.Enter();}//更改状态函数//1.调用当前状态的Exit函数,使动画为false//2.传入新的状态,替换原来的状态//3.调用新的状态的Enter函数
}
 PlayerIdleState.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class PlayerIdleState : PlayerState//继承函数,获得PlayerState里的所有函数和参数
{public PlayerIdleState(Player _player, PlayerStateMachine _stateMachine, string _animBoolName) : base(_player, _stateMachine, _animBoolName){}//构造函数,用于传递信息。//当外补New出对象时,New出的对象里传入参数public override void Enter(){base.Enter();}public override void Exit(){base.Exit();}public override void Update(){base.Update();}
}
基本代码运行逻辑

在游戏运行时,Unity引擎会自动调用与组件绑定的脚本进行初始化,如何将带有MonoBehavior的脚本的Awake和Enter和Update函数调用。

---------------------------------------------------------------------

Player.cs

using System.Collections;
using System.Collections.Generic;
using Unity.VisualScripting;
using UnityEngine;

public class Player : MonoBehaviour
{
    #region 定义States
    public PlayerStateMachine stateMachine { get; private set; }
    public PlayerIdleState idleState { get; private set; }
    public PlayerMoveState moveState { get; private set; }

    #endregion
    private void Awake()
    {
        stateMachine = new PlayerStateMachine();
        //通过构造函数,在构造时传递信息
        idleState = new PlayerIdleState(this, stateMachine, "Idle");
        moveState = new PlayerMoveState(this, stateMachine, "Move");

        //this 就是 Player这个类本身
    }//Awake初始化所以State,为所有State传入各自独有的参数,及animBool,以判断是否调用此动画(与animatoin配合完成)
    private void Start()
    {
        stateMachine.Initialize(idleState);
    }
    private void Update()//在mano中update会自动刷新但其他没有mano的不会故,需要在这个updata中调用其他脚本中的函数stateMachine.currentState.update以实现 //stateMachine中的update

    {
        stateMachine.currentState.Update();//反复调用CurrentState的Update函数
    }
}

---------------------------------------------------------------------
Awake函数中,我们实现了对其他三个类型的声明对象调用传入了参数

此时我们就相当于在Player中获得了其他3个脚本也就是PlayerStateMachine PlayerIdleState PlayerMoveState的所有参数与函数,且参数被初始化。

由于这只是状态机的框架,Idle和MoveState里并没有写入新的参数与函数,所以让我们先对PlayerState进行分析,因为这是Idle和MoveState的父脚本。这两个脚本里的参数,除了通过 

//通过构造函数,在构造时传递信息,改变了他的animBoolName以外没有任何的区别。

---------------------------------------------------------------------

PlayerState.cs

using System.Collections;
using System.Collections.Generic;
using System.Security.Authentication.ExtendedProtection;
using UnityEngine;
//被继承的总类,后面的所以state都需要继承它
//实际上Player并没有进入过这个状态,没有调用此脚本,所有的调用均属于此脚本的子脚本

public class PlayerState
{
    protected PlayerStateMachine stateMachine;//创建PlayerStateMachine类,以对其进行控制
    protected Player player;//创建Player类,以对其进行控制
    private string animBoolName;//控制此时的anim的BOOL值
    public PlayerState(Player _player,PlayerStateMachine _stateMachine,string _animBoolName)
    {
        this.player = _player;
        this.stateMachine = _stateMachine;                                                
        this.animBoolName = _animBoolName;
    }//构造函数,用于传递信息
    
    public virtual void Enter()
    {
        Debug.Log("I enter+" + animBoolName);
    }
    public virtual void Update()
    {
        Debug.Log("I'm in+" + animBoolName);
    }
    public virtual void Exit()
    {
        Debug.Log("I exit " + animBoolName);

    }

}

---------------------------------------------------------------

不行了,我摆烂了,总之我以后真有机会还是出视频讲好了,文字好麻烦啊
 

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

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

相关文章

2024年 复习 HTML5+CSS3+移动web 笔记 之CSS遍 第5天

第 五 天 整个网站例 5.1 准备工作 项目目录与版心 base.css 5.2 网页制作思路 5.3 header 区域-整体布局 5.4 header区域-logo 5.5 header区域-导航 index.html <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8">&l…

【初中生讲机器学习】4. 支持向量机算法怎么用?一个实例带你看懂!

创建时间&#xff1a;2024-02-02 最后编辑时间&#xff1a;2024-02-03 作者&#xff1a;Geeker_LStar 你好呀~这里是 Geeker_LStar 的人工智能学习专栏&#xff0c;很高兴遇见你~ 我是 Geeker_LStar&#xff0c;一名初三学生&#xff0c;热爱计算机和数学&#xff0c;我们一起加…

0203-2-输入输出系统

第六章&#xff1a;输入输出系统 I/O系统的功能&#xff0c;模型和接口 I/O系统管理的对象是I/O设备和相应的设备控制器。 I/O系统的基本功能 隐藏物理设备的细节与设备的无关性提高处理机和I/O设备的利用率对I/O设备进行控制确保对设备的正确共享错误处理 I/O软件的层次结…

MySQL 索引和事务

目录 1 索引1.1 简介1.2 使用1.3 示例 2 事务2.1 简介2.2 使用 1 索引 1.1 简介 索引是一种特殊的文件&#xff0c;包含着对数据表里所有记录的引用指针。可以对表中的一列或多列创建索引&#xff0c;并指定索引的类型&#xff0c;各类索引有各自的数据结构实现。 索引底层是…

Windows、Linux、Mac数据库的安装(mysql、MongoDB、Redis)

数据库的安装 作为数据存储的重要部分&#xff0c;数据库同样是必不可少的&#xff0c;数据库可以分为关系型数据库和非关系型数据库。 关系型数据库如 SQLite、MySQL、Oracle、SQL Server、DB2 等&#xff0c;其数据库是以表的形式存储&#xff1b;非关系型数据库如 MongoDB…

flutter开发实战-Camera自定义相机拍照功能实现

flutter开发实战-Camera自定义相机拍照功能实现 一、前言 在项目中使用image_picker插件时候&#xff0c;在android设备上使用无法默认设置前置摄像头&#xff08;暂时不清楚什么原因&#xff09;&#xff0c;由于项目默认需要使用前置摄像头&#xff0c;所以最终采用自定义…

stack_queue:三个关键注意事项解析

一、stack与容器 template<class T, class Container> class stack { private:Container _con; };Container 为容器&#xff0c;在实例化创建对象时&#xff0c;我们可以传 vector<T> 或 list<T> 等作为栈的底层。 举例&#xff1a; int main() {stack<i…

《苍穹外卖》知识梳理P1-多模块项目的创建

《苍穹外卖》知识梳理P1 一.多模块项目的创建 个人认为对于一个项目的学习&#xff0c;应当先从它的项目结构入手&#xff0c;明确了各个模块的职责与功能&#xff0c;后边尽心编写以及改写的时候会更加得心应手。 该项目分为了3个模块&#xff1a;sky-common模块&#xff0…

西瓜书学习笔记——核化线性降维(公式推导+举例应用)

文章目录 算法介绍实验分析 算法介绍 核化线性降维是一种使用核方法&#xff08;Kernel Methods&#xff09;来进行降维的技术。在传统的线性降维方法中&#xff0c;例如主成分分析&#xff08;PCA&#xff09;和线性判别分析&#xff08;LDA&#xff09;&#xff0c;数据被映…

【备战蓝桥杯】——循环结构终篇

&#x1f308;个人主页: Aileen_0v0 &#x1f525;热门专栏: 华为鸿蒙系统学习|计算机网络|数据结构与算法 ​&#x1f4ab;个人格言:“没有罗马,那就自己创造罗马~” #mermaid-svg-yl4Tqejg4LkjZLAM {font-family:"trebuchet ms",verdana,arial,sans-serif;font-siz…

云尘 -- 铁三域控

描述&#xff1a; flag1 直接fscan开扫 发现存活两台机子123和141&#xff0c;其中141这台机子扫出来有ms17-010漏洞 继续信息收集&#xff0c;用nmap扫一波全端口&#xff0c;看看有没有遗漏 141这台机子一开始没扫到&#xff0c;看着提示使用-Pn再扫一遍就行了。因为如果当…

如何回答消息确认不丢失

1、如何知道有消息丢失&#xff1f; 2、哪些环节可能d 3、如何确保消息不丢失 二、消息丢失的环节 三&#xff0c;防止消息丢失的阶段操作 消息生产阶段 消息存储阶段 消息消费阶段 如何解决消息积压的问题 从消费端解决问题&#xff1a;