Unity类银河恶魔城学习记录1-11 PlayerPrimaryAttack P38

Alex教程每一P的教程原代码加上我自己的理解初步理解写的注释,可供学习Alex教程的人参考
此代码仅为较上一P有所改变的代码

【Unity教程】从0编程制作类银河恶魔城游戏_哔哩哔哩_bilibili

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

public class Player : MonoBehaviour
{
    [Header("Move Info")]
    public float moveSpeed;//定义速度,与xInput相乘控制速度的大小
    public float jumpForce;
    [Header("Dash Info")]
    [SerializeField] private float dashCooldown;
    private float dashUsageTimer;//为dash设置冷却时间,在一定时间内不能连续使用
    public float dashSpeed;//冲刺速度
    public float dashDuration;//持续时间
    public float dashDir { get; private set; }
    [Header("Collision Info")]
    [SerializeField] private Transform groundCheck;//transform类,代表的时物体的位置,后面会来定位子组件的位置    
    [SerializeField] private float groundCheckDistance;
    [SerializeField] private Transform wallCheck;//transform类,代表的时物体的位置,后面会来定位子组件的位置    
    [SerializeField] private float wallCheckDistance;
    [SerializeField] private LayerMask whatIsGround;//LayerMask类,与Raycast配合,https://docs.unity3d.com/cn/current/ScriptReference/Physics.Raycast.html

    public int facingDir { get; private set; } = 1;
    private bool facingRight = true;//判断是否朝右
    #region 定义Unity组件
    public Animator anim { get; private set; }//这样才能配合着拿到自己身上的animator的控制权
    public Rigidbody2D rb { get; private set; }//配合拿到身上的Rigidbody2D组件控制权
    #endregion
    #region 定义States
    public PlayerStateMachine stateMachine { get; private set; }
    public PlayerIdleState idleState { get; private set; }
    public PlayerMoveState moveState { get; private set; }
    public PlayerJumpState jumpState { get; private set; }
    public PlayerAirState airState { get; private set; }
    public PlayerDashState dashState { get; private set; }
    public PlayerWallSlideState wallSlide { get; private set; }
    public PlayerWallJumpState wallJump { get; private set; }


    public PlayerPrimaryAttack primaryAttack { get; private set; }
    #endregion
    private void Awake()
    {
        stateMachine = new PlayerStateMachine();
        //通过构造函数,在构造时传递信息
        idleState = new PlayerIdleState(this, stateMachine, "Idle");
        moveState = new PlayerMoveState(this, stateMachine, "Move");
        jumpState = new PlayerJumpState(this, stateMachine, "Jump");
        airState = new PlayerAirState(this, stateMachine, "Jump");
        dashState = new PlayerDashState(this, stateMachine, "Dash");
        wallSlide = new PlayerWallSlideState(this, stateMachine, "WallSlide");
        wallJump = new PlayerWallJumpState(this, stateMachine, "Jump");//wallJump也是Jump动画


        primaryAttack = new PlayerPrimaryAttack(this, stateMachine, "Attack");
        //this 就是 Player这个类本身
    }//Awake初始化所以State,为所有State传入各自独有的参数,及animBool,以判断是否调用此动画(与animatoin配合完成)
    private void Start()
    {
        anim = GetComponentInChildren<Animator>();//拿到自己身上的animator的控制权
        rb = GetComponent<Rigidbody2D>();
        stateMachine.Initialize(idleState);

    }

    private void Update()//在mano中update会自动刷新但其他没有mano的不会故,需要在这个updata中调用其他脚本中的函数stateMachine.currentState.update以实现 //stateMachine中的update

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

    public void AnimationTrigger() => stateMachine.currentState.AnimationFinishTrigger();
    //从当前状态拿到AnimationTrigger进行调用的函数

    public void CheckForDashInput()
    {

        dashUsageTimer -= Time.deltaTime;//给dash上冷却时间
        if (IsWallDetected())
        {
            return;
        }//修复在wallslide可以dash的BUG
        if (Input.GetKeyDown(KeyCode.LeftShift) && dashUsageTimer < 0)
        {

            dashUsageTimer = dashCooldown;
            dashDir = Input.GetAxisRaw("Horizontal");//设置一个值,可以将dash的方向改为你想要的方向而不是你的朝向
            if (dashDir == 0)
            {
                dashDir = facingDir;//只有当玩家没有控制方向时才使用默认朝向
            }
            stateMachine.ChangeState(dashState);
        }

    }//将Dash切换设置成一个函数,使其在所以情况下都能使用
    public void SetVelocity(float _xVelocity, float _yVelocity)
    {
        rb.velocity = new Vector2(_xVelocity, _yVelocity);//将rb的velocity属性设置为对应的想要的二维向量。因为2D游戏的速度就是二维向量
        FlipController(_xVelocity);//在其他设置速度的时候调用翻转控制器
    }//控制速度的函数,此函数在其他State中可能会使用,但仅能通过player.SeVelocity调用
    public bool IsGroundDetected()
    {
        return Physics2D.Raycast(groundCheck.position, Vector2.down, groundCheckDistance, whatIsGround);
    }//通过RayCast检测是否挨着地面,https://docs.unity3d.com/cn/current/ScriptReference/Physics.Raycast.html
    //xxxxxxxx()   => xxxxxxxx  == xxxxxxxxxx() return xxxxxxxxx;
    public bool IsWallDetected()
    {
        return Physics2D.Raycast(wallCheck.position, Vector2.right * facingDir, wallCheckDistance, whatIsGround);
    }//通过RayCast检测是否挨着地面,https://docs.unity3d.com/cn/current/ScriptReference/Physics.Raycast.html
    //xxxxxxxx()   => xxxxxxxx  == xxxxxxxxxx() return xxxxxxxxx;
    private void OnDrawGizmos()
    {
        Gizmos.DrawLine(groundCheck.position, new Vector3(groundCheck.position.x, groundCheck.position.y - groundCheckDistance));//绘制一条从 from(前面的) 开始到 to(后面的) 的线。
        Gizmos.DrawLine(wallCheck.position, new Vector3(wallCheck.position.x + wallCheckDistance, wallCheck.position.y));//绘制一条从 from(前面的) 开始到 to(后面的) 的线。
    }//画线函数
    public void Flip()
    {
        facingDir = facingDir * -1;
        facingRight = !facingRight;
        transform.Rotate(0, 180, 0);//旋转函数,transform不需要额外定义,因为他是自带的
    }//翻转函数

    public void FlipController(float _x)//目前设置x,目的时能在空中时也能转身
    {
        if (_x > 0 && !facingRight)//当速度大于0且没有朝右时,翻转
        {
            Flip();
        }
        else if (_x < 0 && facingRight)
        {
            Flip();
        }
    }
}

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类,以承接来自Player.cs传过来的东西
    protected Player player;//创建Player类,以承接来自Player.cs传过来的东西
    protected float stateTimer;

    protected bool triggerCalled;//动画是否完成控制值

    #region Unity组件
    protected Rigidbody2D rb;//纯简化,将player.rb --> rb
    #endregion

    private string animBoolName;//控制此时的anim的BOOL值
    protected float xInput;//设置一个可以保存当前是否在按移动键的变量
    protected float yInput;
    public PlayerState(Player _player,PlayerStateMachine _stateMachine,string _animBoolName)
    {
        this.player = _player;
        this.stateMachine = _stateMachine;                                                
        this.animBoolName = _animBoolName;
    }//构造函数,用于传递信息
    
    public virtual void Enter()
    {
        player.anim.SetBool(animBoolName, true);//通过animator自带的函数,将animator里的Bool值改变为想要的值
        rb = player.rb;//纯简化,将player.rb --> rb
        triggerCalled = false;//默认为false表示没有完成动画
        
    }
    public virtual void Update()
    {
        stateTimer -= Time.deltaTime;//https://docs.unity3d.com/cn/current/ScriptReference/Time-deltaTime.html
                                     //从上一帧到当前帧的间隔(以秒为单位)(只读)。这个表达式就是表示每一帧都不断的减少时间
        player.anim.SetFloat("yVelocity", rb.velocity.y);//通过animator自带的函数,将animator里的Float值改变为想要的值,改变yVelocity以控制Jump与Fall动画的切换
        xInput = Input.GetAxisRaw("Horizontal");//对于键盘和游戏杆输入,该值将处于 -1...1 的范围内。 由于未对输入进行平滑处理,键盘输入将始终为 -1、0 或 1。 如果您想自己完成键盘输入的所有平滑处理,这非常有用。
        yInput = Input.GetAxisRaw("Vertical");
    }
    public virtual void Exit()
    {
        player.anim.SetBool(animBoolName, false);//通过animator自带的函数,将animator里的Bool值改变为想要的值
    }

    public virtual void AnimationFinishTrigger()
    {
        triggerCalled = true;
    }//动画控制函数,当动画完成时将控制器设置为true表达其动画已经完成了
}

PlayerGroundState.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
//GroundState用于保证只有在Idle和Move这两个地面状态下才能调用某些函数,并且稍微减少一点代码量
public class PlayerGroundState : PlayerState
{
    public PlayerGroundState(Player _player, PlayerStateMachine _stateMachine, string _animBoolName) : base(_player, _stateMachine, _animBoolName)
    {
    }

    public override void Enter()
    {
        base.Enter();
    }

    public override void Exit()
    {
        base.Exit();
    }
    public override void Update()
    {
        base.Update();

        if(Input.GetKeyDown(KeyCode.Mouse0))//p38 2.从ground进入攻击状态
        {
            stateMachine.ChangeState(player.primaryAttack);
        }
        if(player.IsGroundDetected()==false)
        {
            stateMachine.ChangeState(player.airState);
        }// 写这个是为了防止在空中直接切换为moveState了。

        if (Input.GetKeyDown(KeyCode.Space) && player.IsGroundDetected())
        {
            stateMachine.ChangeState(player.jumpState);
        }//空格切换为跳跃状态


    }

}

PlayerPrimaryAttack.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PlayerPrimaryAttack : PlayerState
{
    //p38 2.从ground进入
    public PlayerPrimaryAttack(Player _player, PlayerStateMachine _stateMachine, string _animBoolName) : base(_player, _stateMachine, _animBoolName)
    {
    }

    public override void Enter()
    {
        base.Enter();
    }

    public override void Exit()
    {
        base.Exit();
    }

    public override void Update()
    {
        base.Update();
        if(triggerCalled)
        {
            stateMachine.ChangeState(player.idleState);
        }
    }
}

PlayerAnimationTrigger.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class playerAnimationTriggers : MonoBehaviour
{
    private Player player => GetComponentInParent<Player>();//获得夫组件上的实际存在的Player组件
    private void AnimationTrigger()
    {
        player.AnimationTrigger();
    }
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

基于spring boot实现邮箱发送和邮箱验证

目录 一、邮箱发送实现1. 开通邮箱服务2. 添加邮箱依赖3.添加配置4.添加邮箱通用类5. 测试类 二、邮箱验证实现1.添加依赖2. 添加配置3.添加controller4. 测试 项目地址: https://gitee.com/nssnail/springboot-email 一、邮箱发送实现 1. 开通邮箱服务 使用qq邮箱、163邮箱都…

《计算机网络简易速速上手小册》第10章:未来网络技术趋势(2024 最新版)

文章目录 10.1 边缘计算与网络设计 - 未来网络的速度与激情10.1.1 基础知识10.1.2 重点案例&#xff1a;使用 Python 实现边缘计算的实时视频分析准备工作Python 脚本示例 10.1.3 拓展案例1&#xff1a;智能交通系统Python 脚本示例 - 边缘计算设备上的交通流量分析 10.1.4 拓展…

vcruntime140_1.dll 文件缺失的解决方法,简单的修复方法分享

遇到 vcruntime140_1.dll 文件缺失是一种常见的问题&#xff0c;但无需过于担心&#xff0c;因为这类问题通常有多种解决办法。接下来&#xff0c;我会为大家详细介绍如何处理 vcruntime140_1.dll 文件缺失的情况&#xff0c;以及在解决过程中应该注意的重要事项。 一.vcrunti…

Python flask 模板详解

文章目录 1 概述1.1 模板简介1.2 templates 文件1.3 简单应用 2 模板语法2.1 for 循环2.2 if 判断 3 模板的继承3.1 格式要求3.2 实现示例3.3 复用父模板的内容&#xff1a;super 1 概述 1.1 模板简介 定义&#xff1a;定义好的 html 文件&#xff0c;用于快速开发 web 页面J…

04-OpenFeign-请求超时机制

基于 2021.0.1版本 具体有以下几种超时参数设置 以下仅限2021.0.1 以前的版本&#xff0c;高于该版本的spring cloud 已修复该问题 1、默认的超时时间 默认不生效 连接超时时间10秒、读超时时间60秒&#xff0c;源码在feign.Request.Options#Options()这个方法中 2、open…

在Linux中如何理解页表和进程地址

1、进程地址是进程读取资源的窗口 2、页表决定了进程真实拥有的资源情况 3、合理的对进程地址空间页表进行资源划分&#xff0c;就可以对进程的资源进行分类 这个过程应该如何去理解呢请看下面的图 我们知道程序被加载到进程中&#xff0c;会产生相应的PCB&#xff0c;并且…

【JavaScript 漫游】【006】数据类型 array

文章简介 本文为【JavaScript 漫游】专栏的第 006 篇文章&#xff0c;记录笔者在了解 JS 数据类型 array 中摘录的知识点。 数组的本质是对象属组的 length 属性for ... in 循环和数组的遍历数组的空位类数组对象 除了上述 5 个重要知识点&#xff0c;学习数组更为重要的是掌…

CSS transition(过渡效果)详解并附带示例

CSS过渡效果&#xff08;CSS transitions&#xff09;是一种在元素属性值发生变化时&#xff0c;通过指定过渡效果来实现平滑的动画效果的方法。通过定义起始状态和结束状态之间的过渡属性&#xff0c;可以使元素的变化更加流畅和可视化。 过渡效果的基本语法如下&#xff1a;…

使用潜在向量进行检测、屏蔽和重建以进行遮挡的面部表情识别

Latent-OFER: Detect, Mask, and Reconstruct with Latent Vectors for Occluded Facial Expression Recognition 一、创新点 &#xff08;1&#xff09;提出了一种与表情相关的特征提取器&#xff0c;它使用空间注意力为特定的面部特征分配更高的权重&#xff0c;从而使我们能…

前端开发中不同语言【react-i18next】

目录 查看并设置语言 单页面&#xff1a;html lang ​编辑 浏览器 自定义翻译&#xff1a;react-i18next 设置 模块&#xff1a;staticData.ts 散(重复利用)&#xff1a;命名空间.json 应用 准备 html标签 查看并设置语言 单页面&#xff1a;html lang 英语: <…

RflySim | 定点位置控制器设计实验三

RflySim| 定点位置控制器设计实验三 01 分析实验 1.调节PD控制器的相关参数改善系统控制性能&#xff0c;并记录超调量和调节时间&#xff0c;得到满意的参数。 2.在得到满意参数后&#xff0c;对系统进行扫频以绘制Bod图&#xff0c;观察系统幅频响应、相频响应曲线&#xf…

【服务器】RAID(独立磁盘冗余阵列)

RAID&#xff08;独立磁盘冗余阵列&#xff09; 一、RAID的介绍二、RAID的分类#2-1 RAID 02-2 RAID 1#2-3 RAID 32-4 RAID 52-5 RAID 62-6 RAID 10(先做镜像&#xff0c;再做条带化)2-7 RAID 01&#xff08;先做条带&#xff0c;再做镜像&#xff09;2-8 RAID比较 三、磁盘阵列…

国内最全的Spring Boot系列之七

• 阿里巴巴前高级研发工程师 • 三家千万级互联网企业技术顾问 • MBTI/盖洛普技术专家 • 厦门某高校外聘教师 • 51CTO特约合作讲师 • 网易云课堂签约讲师 •《深入理解设计模式》作者 一转眼马上要过年了&#xff0c;回首2023年&#xff0c;感觉自己无所事事、碌碌无…

探索网络定位与连接:域名和端口的关键角色

目录 域名 域名的作用 域名的结构 域名的解析配置 父域名、子域名​编辑 https的作用 端口 图解端口 端口怎么用 判断网站是否存活 端口的作用 域名 域名是互联网上用于标识网站的一种易于记忆的地址。 域名是互联网基础架构的一个重要组成部分&#xff0c;它为网…

Django学习记录01

1.项目结构 djangoProject02 ├── manage.py 【项目的管理&#xff0c;启动项目、创建app、数据管理】【不要动】【常常用】 └── jangoProject02 ├── __init__.py ├── settings.py 【项目配置】 【常常修改】 ├── urls.py …

为什么要配置环境变量?

华子目录 什么是环境变量&#xff1f;Path环境变量使用%%引用环境变量操作步骤 使用%%引用环境变量的优点 用户变量和系统变量的区别 什么是环境变量&#xff1f; 环境变量&#xff1a;一般是指再操作系统中用来指定操作系统运行环境的一些参数&#xff0c;如&#xff1a;临时…

SpringBoot注解--07-- lombok 注解

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 1 Lombok介绍1.1 Lombok是什么?1.2 如何安装Lombok? 2 Lombok注解2.1 GetterSetter2.2 ToString2.3 EqualsAndHashCode2.4 NoArgsConstructor &#xff0c; Requi…

java仓库进销存商品库存管理系统springboot+vue

库存管理信息系统研究的内容涉及库存管理的全过程&#xff0c;包括入库、出库、退 货、订货、库存统计查询等等。 根据上述工作流程&#xff0c;库存管理系统将包含以下内容 1&#xff09;登录信息的输入&#xff0c;密码的修改。 2&#xff09;基本信息的输入&#xff0c;包括…

JAVA Web 学习(四)RabbitMQ、Zookeeper

十、消息队列服务器——RabbitMQ RabbitMQ是使用Erlang语言开发的开源消息队列系统&#xff0c;基于AMQP协议来实现。AMQP的主要特征是面向消息、队列、路由(包括点对点和发布/订阅)、可靠性、 安全。AMQP协议更多用在企业系统内&#xff0c;对数据一致性、稳定性和可靠性要求…

【实战】阿里智能编码助手通义灵码

文章目录 前言技术积累通义灵码是什么&#xff1f;Copilot是什么&#xff1f;通义灵码主要功能通义灵码有哪些优势&#xff1f;通义灵码支持语言/工具通义灵码接入方式通义灵码帮助中心 实战演示安装插件行/函数级实时续写自然语言生成代码代码优化单元测试生成代码注释生成解释…