类银河恶魔城学习记录1-8 PlayerDash补全 P35

Alex教程每一P的教程原代码加上我自己的理解初步理解写的注释,可供学习Alex教程的人参考

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

Player.cs
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; }
    #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");
        //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 CheckForDashInput()
    {
        dashUsageTimer -= Time.deltaTime;//给dash上冷却时间

        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;
    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
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;

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

    private string animBoolName;//控制此时的anim的BOOL值
    protected float xInput;//设置一个可以保存当前是否在按移动键的变量
    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
        
    }
    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。 如果您想自己完成键盘输入的所有平滑处理,这非常有用。
    }
    public virtual void Exit()
    {
        player.anim.SetBool(animBoolName, false);//通过animator自带的函数,将animator里的Bool值改变为想要的值
    }

}
PlayerStateMachine.cs
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函数
}
PlayerGroundState.cs
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(player.IsGroundDetected()==false)
        {
            stateMachine.ChangeState(player.airState);
        }// 写这个是为了防止在空中直接切换为moveState了。

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

}
PlayerIdleState.cs
cs 复制代码
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PlayerIdleState : PlayerGroundState//继承函数,获得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();
        if(xInput != 0)
        {
            stateMachine.ChangeState(player.moveState);//在这里我们能使用Player里的东西,主要是因为我们通过构造函数传过来Player实体,如果不传,则无法使用已经存在了的Player实体。
        }
    }
}
PlayerMoveState.cs
cs 复制代码
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PlayerMoveState : PlayerGroundState
{
    public PlayerMoveState(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();
        player.SetVelocity(xInput*player.moveSpeed, rb.velocity.y);//player.rb.velocity.y默认的为0,player.moveSpeed在player中定义,但可以在Unity引擎中更改
        if (xInput==0)
        {
            stateMachine.ChangeState(player.idleState);//在这里我们能使用Player里的东西,主要是因为我们通过构造函数传过来Player实体,如果不传,则无法使用已经存在了的Player实体。
        }
    }
}
PlayerJumpState.cs
cs 复制代码
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PlayerJumpState : PlayerState
{
    public PlayerJumpState(Player _player, PlayerStateMachine _stateMachine, string _animBoolName) : base(_player, _stateMachine, _animBoolName)
    {
    }

    public override void Enter()
    {
        base.Enter();
        rb.velocity = new Vector2(rb.velocity.x, player.jumpForce);//将y轴速度改变
    }
    public override void Update()
    {
        base.Update();
        if (rb.velocity.y < 0)//当速度小于0时切换为airState
        {
            stateMachine.ChangeState(player.airState);//与其说是airState,不如说是FallState
        }
    }

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

}
PlayerAirState.cs
cs 复制代码
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PlayerAirState : PlayerState
{
    public PlayerAirState(Player _player, PlayerStateMachine _stateMachine, string _animBoolName) : base(_player, _stateMachine, _animBoolName)
    {
    }

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


}
PlayerDashState.cs
cs 复制代码
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PlayerDashState : PlayerState
{   //由Ground进入
    public PlayerDashState(Player _player, PlayerStateMachine _stateMachine, string _animBoolName) : base(_player, _stateMachine, _animBoolName)
    {
    }

    public override void Enter()
    {
        base.Enter();
        stateTimer = player.dashDuration;设置Dash可以保持的值
        
    }

    public override void Exit()
    {
        base.Exit();
        player.SetVelocity(0, rb.velocity.y);//当退出时使速度为0防止动作结束后速度不变导致的持续移动

    }

    public override void Update()
    {
        base.Update();
        player.SetVelocity(player.dashSpeed * player.dashDir, 0);//这个写在Update里,防止在x轴方向减速了,同时Y轴写成0,以防止dash还没有完成就从空中掉下去了
        if (stateTimer < 0)当timer小于0,切换
        {
            stateMachine.ChangeState(player.idleState);

        }
    }
}
相关推荐
西岸行者2 天前
学习笔记:SKILLS 能帮助更好的vibe coding
笔记·学习
悠哉悠哉愿意2 天前
【单片机学习笔记】串口、超声波、NE555的同时使用
笔记·单片机·学习
别催小唐敲代码2 天前
嵌入式学习路线
学习
毛小茛2 天前
计算机系统概论——校验码
学习
babe小鑫2 天前
大专经济信息管理专业学习数据分析的必要性
学习·数据挖掘·数据分析
winfreedoms2 天前
ROS2知识大白话
笔记·学习·ros2
在这habit之下2 天前
Linux Virtual Server(LVS)学习总结
linux·学习·lvs
我想我不够好。2 天前
2026.2.25监控学习
学习
im_AMBER2 天前
Leetcode 127 删除有序数组中的重复项 | 删除有序数组中的重复项 II
数据结构·学习·算法·leetcode
CodeJourney_J2 天前
从“Hello World“ 开始 C++
c语言·c++·学习