瞬杀★弑龙 发表于 2021-9-7 13:42:57

2021-9-4 爆肝一整天,关于2D横板游戏中攀爬楼梯的考虑



今日份关于2D横板游戏中攀爬楼梯的考虑



[*]引言
[*]关于攀爬楼梯考虑
[*]

[*]总体考虑
[*]玩家站在1处
[*]玩家站在2处
[*]玩家通过跳跃来到3处
[*]1处升至3处 和 2处降至3处
[*]3处升至2处
[*]3处降至1处
[*]其他考虑

[*]办理方案及代码
[*]

[*]动画条件
[*]办理代码(非完全代码)
[*]

[*]首先是一些设置
[*]初始化
[*]然后,重点来了,各类情况分析
[*]最重要的几点分析(条件时在梯子范围内)
[*]两个检测函数
[*]考虑梯子上的受力情况
[*]各类函数实现,没什么好说的
[*]最坑爹的地方来了,如何判断在梯子范围内和位于梯子底部


[*]结束
[*]

[*]下面放几张效果图
[*]

[*]梯子底部不影响下蹲
[*]底部向上攀爬
[*]停留在梯子上
[*]战立在梯子顶端
[*]顶部向下攀爬



引言

以前觉得2D横板游戏制作起来很简朴,殊不知一个小小的动作就需要考虑这么多要素。通过对这个小小的2D横版游戏的设计,我对那些开发出好玩炫酷分身打击手感,不停琢磨提高游戏的性能及优化的开发者们的敬意油然而生啊!!!
关于攀爬楼梯考虑


总体考虑



[*]玩家在梯子上将不能左右移动,不能跳跃
[*]增加梯子上的停留动画,保证在梯子上停留时不会出现原地攀爬的情况
玩家站在1处



[*]按下s键,仍应播放下蹲动作,而不是攀趴下降动作,无竖直方向受力
[*]按下w键,播放攀爬上升动作,受力向上
玩家站在2处



[*]按下w键,不播放攀爬上升动画,无竖直方向受力
[*]按下s键, 播放攀趴下降动画,受力向下
玩家通过跳跃来到3处



[*]按下w键,播放攀爬上升动画,受力向上
[*]按下s键,播放攀趴下降动画,受力向下
1处升至3处 和 2处降至3处



[*]暂时没想到有什么可考虑的
3处升至2处



[*]停止播放攀爬上升动画,播放站立动画
[*]不影响跳跃(检测盒子检测到的不再是地面)
[*]下蹲无效
[*]到达桥的顶点后,桥上是可以站立的
3处降至1处



[*]停止播放攀趴下降动画,播放站立动画
[*]不影响跳跃(检测盒子检测到再次酿成地面)
[*]不影响下蹲
其他考虑



[*]到达梯子什么地方可以攀爬,如果太宽,大概会出现没有借助梯子而是悬空攀爬的情况
[*]被攻击就会掉落
办理方案及代码

情况极其复杂,经过本日一整天的调试,我才乐成得完成我对于攀爬的各种需求。
动画条件




[*]很明显,我将跳跃与着落分开,然后又将向上攀爬,向下攀爬,停止攀爬分开。
[*]本来连线照旧较为简朴的,因为将转换状态时间设置为0,为通过不停调试,发现多条连线只管不需要转换时间,但如果没有直接连通的线,仍会出现许多不合常理的bug。例如到梯子顶部仍无法结束攀爬动画的情况。因此,经过不停调试,我增加了很多连线。
办理代码(非完全代码)

自己动手敲一敲哦,就会发现这其中照旧很斲丧脑细胞的。
首先是一些设置

   
    public float BoxHeight = 0.2f;

   
    public LayerMask groundMask;

   
    public LayerMask bridgeMask;

   
    public float ClimbSpeed = 10.0f;

    private bool isOnLadder = false; // 是否在梯子上

    private bool isClimb = false; // 是否正在攀爬

   
    public bool bridgeBottom = false; // 是否在梯子底

   
    public bool bridgeTop = false; // 是否在梯子顶

    private Animator _animator;

    private Rigidbody2D _rigidbody2D;

    private Collider2D _collider2D;

    private Collider2D BridgeCollider;

    private Vector2 playersize; // 玩家大小

    private Vector2 boxsize; // 检测盒子尺寸

    // 所有状态参数的id定义
    #region
    private int id_run;
    private int id_jump;
    private int id_fall;
    private int id_climbup;
    private int id_climbdown;
    private int id_onladder;
    private int id_bridgebottom;
    private int id_bridgetop;
    private int id_crouch;
    private int id_hurt;
    #endregion 初始化

    void Awake()
    {
      _animator = GetComponent<Animator>();
      _rigidbody2D = GetComponent<Rigidbody2D>();
      _collider2D = GetComponent<Collider2D>();
      playersize = GetComponent<SpriteRenderer>().bounds.size;
      boxsize = new Vector2(playersize.x * 0.3f, BoxHeight);// 设置检测盒的大小

      healthscontroller = GameObject.FindGameObjectWithTag("healths").GetComponent<HealthsController>();

      BridgeCollider = GameObject.FindGameObjectWithTag("bridgetop").GetComponent<Collider2D>();

      // 所有状态参数转为其id,提高性能
      #region
      id_run = Animator.StringToHash("run");
      id_jump = Animator.StringToHash("jump");
      id_fall = Animator.StringToHash("fall");
      id_climbup = Animator.StringToHash("climbup");
      id_climbdown = Animator.StringToHash("climbdown");
      id_onladder = Animator.StringToHash("onladder");
      id_bridgebottom = Animator.StringToHash("bridgebottom");
      id_bridgetop = Animator.StringToHash("bridgetop");
      id_crouch = Animator.StringToHash("crouch");
      id_hurt = Animator.StringToHash("hurt");
      #endregion
    } 然后,重点来了,各类情况分析

    // Update is called once per frame
    void Update()
    {
      // 判断是否到达梯子顶
      #region
      if (bridgeTop)
      {
            isClimb = false;
            _animator.SetBool(id_bridgetop, true);
      }
      else
      {
            _animator.SetBool(id_bridgetop, false);
      }
      #endregion

      // 判断是否到达梯子底
      #region
      if (bridgeBottom)
      {
            isClimb = false;
            _animator.SetBool(id_bridgebottom, true);
      }
      else
      {
            _animator.SetBool(id_bridgebottom, false);
      }
      #endregion
    }

    private void FixedUpdate()
    {
      // 判断在地面上则下落停止
      if (IsOnGround())
      {
            StopFall();
            _animator.SetBool(id_climbdown, false);
            _animator.SetBool(id_bridgebottom, true);
      }
               
                // 判断在梯子顶部
      if (IsOnBridge())
      {
            StopFall();
            bridgeTop = true;
            BridgeCollider.isTrigger = false; // 空气墙是否有碰撞
            _animator.SetBool(id_climbup, false);
            _animator.SetBool(id_crouch, false);
      }
      else
      {
            bridgeTop = false;
      } 最重要的几点分析(条件时在梯子范围内)


[*]在梯子底部按下w键,执行向上攀爬
[*]在梯子顶部按下s键,执行向下攀爬
[*]不在梯子顶部按下w键,执行向上攀爬
[*]不在梯子底部按下s键,执行向下攀爬
[*]按下w或者s键后抬起,执行停止攀爬
      // 攀爬楼梯相关
      if (isOnLadder)
      {
            _animator.SetBool(id_onladder, true);
            1.if (Input.GetButton("Climb") && bridgeBottom)
            {
                ClimbUp();
            }
            2.else if(Input.GetButton("Crouch") && bridgeTop)
            {
                BridgeCollider.isTrigger = true;
                ClimbDown();
            }
            3.else if (Input.GetButton("Climb") && !bridgeTop)
            {
                ClimbUp();
            }
            4.else if (Input.GetButton("Crouch") && !bridgeBottom)
            {
                ClimbDown();
            }
            5.if (Input.GetButtonUp("Climb") || Input.GetButtonUp("Crouch"))
            {
                StopClimb();
            }
      }
      else
      {
            _animator.SetBool(id_onladder, false);
            BridgeCollider.isTrigger = true;
      }
    } 两个检测函数

   // 利用检测盒子检测人物是否在地面上
   private bool IsOnGround()
   {
       Vector2 boxcenter = (Vector2)transform.position + (Vector2.down * playersize.y * 0.5f);
       return Physics2D.OverlapBox(boxcenter, boxsize, 0, groundMask);
   }

// 利用检测盒子检测人物是否在梯子顶部
   private bool IsOnBridge()
   {
       Vector2 boxcenter = (Vector2)transform.position + (Vector2.down * playersize.y * 0.5f);
       return Physics2D.OverlapBox(boxcenter, boxsize, 0, bridgeMask);
   } 考虑梯子上的受力情况

在梯子上停留的话应该是不动的,因此,要将重力倍数设置为0
    ///   /// 改变上升着落重力大小的函数,可以让人物没有飘飘的感觉,提升玩家体验    ///   private void BetterJump()    {      if (_rigidbody2D.velocity.y > 0 && !isClimb)      {            _rigidbody2D.gravityScale = JumpUpGravity;      }      else if (_rigidbody2D.velocity.y <span class="token operator">
页: [1]
查看完整版本: 2021-9-4 爆肝一整天,关于2D横板游戏中攀爬楼梯的考虑