Unity2D横板跳跃——更佳的跳跃手感

 参考b站教学

先来说说普通的跳跃方式

更加的跳跃手感在于你如何管理跳跃的速度和高度,让玩家只能跳到他们应该跳到的地方。

在unity里,一般有两种实现跳跃的方式:

第一种是使用unity物理引擎,通常是对一个物体施加一定的力来移动它,让它在重力的作用下再次下降。

第二种是自己使用代码模拟物体的垂直运动,在没有物理引擎的情况下手动让物体跳跃。(这种方法虽然工作量比较大,但是如果想要创建那种非自然的运动,编写自己的跳跃方式,那么这个方法将会很有用)

两种方法的原理仍然是对抗重力向上运动。

一、普遍方法实现

 (1)这种方法最简单,但是物体下落的时候感觉轻飘飘的,直接有效的方法就是在unity里面将Gravity的y值修改的更大,这样物体受到的重力越大,下落的越快。

注意,这里没有地面检测导致多次按跳跃键可以一直跳跃,不过后面有补充

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

//注意,这里没有地面检测导致多次按跳跃键可以一直跳跃,不过后面有补充
public class NormalJump : MonoBehaviour
{
    [SerializeField]float jumpForce;

    Rigidbody2D rb;

    bool isJump;
    void Start()
    {
        rb = GetComponent<Rigidbody2D>();
    }

    // Update is called once per frame
    void Update()
    {
        if (Input.GetKeyDown(KeyCode.Space))
        {
            isJump = true;
        }
    }


    private void FixedUpdate()
    {
        if (isJump)
        {
            Jump();
        }
    }
    void Jump()
    {
        rb.AddForce(Vector2.up * jumpForce, ForceMode2D.Impulse);
        isJump = false;
    }
}

补充:通用移动代码 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class HorizontalMove : MonoBehaviour
{
    [SerializeField] float moveSpeed;

    Rigidbody2D rb;

    float horizontalMove;
    void Start()
    {
        rb = GetComponent<Rigidbody2D>();
    }

    // Update is called once per frame
    void Update()
    {
        horizontalMove = Input.GetAxis("Horizontal");
    }

    private void FixedUpdate()
    {
        rb.velocity = new Vector2 (horizontalMove * moveSpeed, rb.velocity.y);
    }
}

然而增加物理对象的Gravity Scale会导致快速移动的物体穿过其他物体(比如地面),在接下来的物理更新中导致物体从地面反弹 ,解决方法就是将刚体的碰撞检测模式改为continuous(连续),而不是discrete(离散),这样就能防止它卡在其他物体中,同时更改插值模式,可以实现平滑的物理运动,固定更新位置变化,使得跳跃运动更加流畅。

(2)但是这种方法就会导致其他的游戏物体也会收到影响,而我们又只想对一个物体起作用,那么还有一个方法就是修改该物体的Gravity Scale(重力比例),值越大,受到的重力越大。

许多游戏里面使用跳跃曲线,上升和下降的时间一样长。

但是在某些游戏游戏机制中,玩家上跳的时间比下落的时间长(或者更短),手感和效果也会更佳,这就是接下来我们要实现的功能

接下来只实现上跳的时间比下落的时间长的效果

第一种,用物理引擎实现

 用物理效果实现的方式又有很多。但是每个方法的核心都是在物体下落的是否增大它的GravityScale来实现更快速的下落

第一种:物体实现固定的跳跃高度

其中运用到一个物理公式:umpForce = (Mathf.Sqrt(height * gravity * -2)) * mass,由h = 1/2gt方推导

 /// <summary>
    /// 以固定的高度跳跃
    /// </summary>
    void JumpWithinHeight()
    {
        if (Input.GetKeyDown(KeyCode.Space) && isGround)
        {
            rb.gravityScale = gravityScale;

            ///jumpForce = (Mathf.Sqrt(height * gravity * -2)) *mass gravity为负数
            //计算跳跃到height所需要的力,虽然这种计算方法会有一定的误差,但是总能保证物体固定跳到某一个高度
            jumpForce = Mathf.Sqrt(jumpHeight * (Physics2D.gravity.y * rb.gravityScale) * (-2)) * rb.mass;
            rb.AddForce(Vector2.up * jumpForce, ForceMode2D.Impulse);
        }

        if (rb.velocity.y >= 0.1)
        {
            rb.gravityScale = gravityScale;
        }
        else
        {
            rb.gravityScale = fallGravityScale;
        }
    }

 然而,虽然限制跳跃的高度是有用的,但是总是跳到相同的高度会让你在游戏中移动非常困难,所以让玩家根据按下按钮的时间来控制跳跃高度是一个好主意,也就是长按跳跃。

(2)接下来就是实现方法

实现可变跳跃的方法很多,当提前释放按键(或者跳跃时间小于完整跳跃时间),可以直接在物体上升时向物体施加向下的力,或者增大GravityScale,当物体下落又撤销向下的力或者回复原本的GravityScale。

/// <summary>
    /// 方法一:根据按键的时间来改变物体的跳跃高度,即长按跳的更高,短按更低
    /// 方法二:用一个bool jumpCancelled来记录玩家是否松开按键,松开了就跳的短,没松开就执行完整跳跃
    /// </summary>
    void JumpByTime()
    {
        if (Input.GetKeyDown(KeyCode.Space) && isGround)
        {
            rb.gravityScale = gravityScale;

            ///jumpForce = (Mathf.Sqrt(height * gravity * -2))  gravity为负数
            //计算跳跃到height所需要的力,虽然这种计算方法会有一定的误差,但是总能保证物体固定跳到某一个高度
            float jumpForce = Mathf.Sqrt(jumpHeight * (Physics2D.gravity.y * rb.gravityScale) * (-2)) * rb.mass;
            rb.AddForce(Vector2.up * jumpForce, ForceMode2D.Impulse);
            jumping = true;
            buttonPressTime = 0;//重置
        }

        if (jumping)
        {
            buttonPressTime += Time.deltaTime;//开始计时

            //在上升过程中松开按键
            if (buttonPressTime < buttonPressWindow && Input.GetKeyUp(KeyCode.Space))
            {
                //取消完整的跳跃,减少跳跃轨迹,需要抵消物体已经拥有的向上的动量
                //方式一使用GravityScale来使物体上升的更慢,从而达到更低的峰值
                rb.gravityScale = fallGravityScale;
            }


            //玩家开始下落(物体达到高度峰值),完成了完整跳跃
            if (rb.velocity.y < 0)
            {
                jumping = false;//物体开始下落就设置为false
                rb.gravityScale = fallGravityScale;
            }

        }
    }

 第二种,用非物理引擎实现

在没有物理引擎的作用下,我们不但需要实现物体跳跃向上移动,同时也要创造重力条件。

虽然物体能够跳跃了,但是由于碰撞检测的前提是,碰撞双方都需要有碰撞体,同时至少其中一个物体有rigidbody,但是我们这里跳跃的物体不能够有rigidbody,这就需要我们手动创建物理检测。

实现地面检测的方法很多,方法一就是在不应该跳跃的时候禁用重力作用,方法二就是射线检测,但是射线检测,或者盒检测等,会因为形状,大小不适而使物体在地形边缘处检测不到而掉落。

  • 22
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值