类银河恶魔城学习记录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.mzph.cn/news/663304.shtml

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

相关文章

加速知识检索:伯克利DeepMind联合研究,RaLMSpec让语言模型服务飞速提升2-7倍!

近年来,随着大型语言模型(LLM)的出现,在多样化的 NLP 任务上取得了令人瞩目的成果。然而,知识密集型任务仍是 NLP 领域中的一项挑战,因为这些任务不仅要求模型要理解和生成自然语言,还要能够访问…

Tomcat在Java web的应用

Tomcat在Java web的应用 本来这篇博客顺应之前的内容,应该是需要写Tomcat的简介、基本使用、配置和部署项目、Web的项目结构、创建MavenWeb、idea本地集成以及Tomcat的Maven插件的笔记内容,但是总觉得没必要,因为这些内容网上肯定很多了&…

移动机器人激光SLAM导航(四):GMapping SLAM 篇

参考引用 GMapping ROS-Wiki从零开始搭二维激光SLAMGMapping 漫谈小白学移动机器人机器人工匠阿杰wpr_simulation 移动机器人激光SLAM导航(文章链接汇总) 1. GMapping 1.1 FastSLAM 问题分解 概率论相关公式 1. 条件概率公式: p ( x , y ) …

C语言的基础学习

C语言的变量 ## C语言中的变量 在C语言中,变量是对程序中数据所占内存空间的一种抽象定义。定义变量时,用户定义变量的名、变量的类型,这些都是变量的操作属性。不仅可以通过变量名访问该变量,系统还通过该标识符确定变量在内存中的位置 [❷](https://www.dotcpp.com/cour…

将链表反转

反转链表在解决需要从尾节点开始遍历到头节点的地方很实用,是一种常用的解题技巧。在反转时,我们可以考虑从前向后反转和从后向前反转两种方式。 法一:递归 每次将链表的头节点的下一个节点作为新的头节点,然后对剩余部分调用递归…

深度学习入门笔记(五)前馈网络与反向传播

接着上一节,本节讲解模型自我学习的数学计算过程究竟是怎么样的。 5.1 前馈网络 一个最简单的前馈神经网络如图所示,对于每一个隐藏层,输入对应前一层每一个节点权重乘以节点输出值,输出则是经过激活函数(例如sigmoid函数)计算后的值。 在这样的网络中,输入的数据 x 经…

HSMES中的计划管理

MES(生产制造执行系统),旨在帮助制造企业实现高质量和高效率生产,通过实时监控生产过程,智能的生产计划排程,灵活的工艺设置,进而实现企业的数字化生产。对于生产计划的管控是其中不可或缺的一环…

jQuery 获取并设置 CSS 类 —— W3school 详解 简单易懂(十五)

通过 jQuery,可以很容易地对 CSS 元素进行操作。 jQuery 操作 CSS jQuery 拥有若干进行 CSS 操作的方法。我们将学习下面这些: addClass() - 向被选元素添加一个或多个类removeClass() - 从被选元素删除一个或多个类toggleClass() - 对被选元素进行添…

Python 抽象类

在Python中,抽象类是一种特殊的类,不能直接实例化,而是被用作其他类的基类。它定义了一组方法的接口,但没有具体的实现。子类必须实现这些方法才能实例化。 要创建一个抽象类,您需要使用abc模块中的ABC(Abstract Base Class)类,并通过将metaclass设置为ABCMeta来指定它…

小白水平理解面试经典题目_数组类Leetcode 412. Fizz Buzz【数学解法】

412 FizzBuzz 小白渣翻译: 给定一个整数 n ,返回一个字符串数组 answer (从 1 开始索引),其中: answer[i] “FizzBuzz” 如果 i 能被 3 和 5 整除。answer[i] “Fizz” 如果 i 能被 3 整除。answer[i]…

8. 实现VLAN间的通信

文章目录 一. 初识VLAN通信1.1. VLAN的概述1.2. Dot1q 终结子接口(单臂路由 )1.3. VLANIF接口 二. 实验专题2.1. 实验1: Dotlq 终结子接口2.1.1. 实验目的2.1.2. 实验拓扑图2.1.3. 实验步骤(1)配置PC机的网络(2)交换机…

八、访存顺序(Memory Ordering)

前言 这部分的内容比较抽象,很多内容我无法理解,都是直接翻译过来的。虽然难,但是不可不看,如果遇到无法理解的都直接跳过,那后面都无法学习下去了。觉得无法理解是因为目前的知识还很欠缺,到后面具备了这…

React16源码: React中event事件触发的源码实现

event 事件触发过程 1 )概述 在之前事件绑定时,绑定的是两个方法 一个是 dispatchInteractiveEvent另外一个 dispatchEvent 其实它们调用的方法都是差不多的,一开始会有一点小的区别 2 )源码 定位到 packages/react-dom/src/ev…

MySQL 函数参考手册(MySQL 高级函数)

目录 MySQL BIN() 函数 MySQL BINARY 函数 MySQL CASE 函数 MySQL CAST() 函数 MySQL COALESCE() 函数 MySQL CONNECTION_ID() 函数 MySQL CONV() 函数 MySQL CONVERT() 函数 MySQL CURRENT_USER() 函数 MySQL DATABASE() 函数 MySQL IF() 函数 MySQL IFNULL() 函数…

在PostgreSQL中不开归档?恭喜你!锅你背定了

📢📢📢📣📣📣 哈喽!大家好,我是【IT邦德】,江湖人称jeames007,10余年DBA及大数据工作经验 一位上进心十足的【大数据领域博主】!😜&am…

k8s中deployment模板

一、清单文件 apiVersion: apps/v1 kind: Deployment metadata:annotations:version: "1.1.6"labels:k8s-app: deployment-nginxname: deployment-nginxnamespace: test spec:minReadySeconds: 30progressDeadlineSeconds: 600replicas: 2revisionHistoryLimit: 5sel…

智能汽车竞赛摄像头处理——摄像头入门(2)

前言 在上一节中,我们学习了如何将总钻风摄像头的图像显示在1.8寸TFT显示屏上,其实我建议大家显示屏还是要选用ips200,像素点多一些,显示的图像更加清晰。 二值化处理 (1)对原始的灰度图像进行二值化&am…

【操作宝典】IntelliJ IDEA新建maven项目详细教程

目录 🌼1. 配置maven环境 🌼2. 创建maven项目 🌼3. 创建maven项目完整示例 a. 导入spring boot环境 b. 修改maven配置 c. 下载jar包 d. 创建Java类 🌼1. 配置maven环境 【安装指南】maven下载、安装与配置详细教程-CSDN博客…

反物质(anti matter)和湮灭反应(Annihilation)浅读

反物质 反物质是正常物质的反状态。当正反物质相遇时,双方就会相互湮灭抵消,发生爆炸并产生巨大能量。 概念 正电子、负质子都是反粒子,它们跟通常所说的电子、质子相比较,电量相等但电性相反。科学家设想在宇宙中可能存在完全由…

【GitHub项目推荐--一个 C++ 实现快速存储的库】【转载】

一个提供可嵌入、持久键值存储以实现快速存储的库。 github地址 https://github.com/facebook/rocksdb 国内镜像 http://www.gitpp.com/ag/rocksdb RocksDB 是一个开源的嵌入式键值存储库,由 Facebook 开发,用于处理大量的数据,特别适合于…