【Unity造轮子】2D横版平台跳跃游戏实现多段跳完美手感(含源码)

前言

随着游戏技术的不断发展,2D横版平台跳跃游戏成为许多玩家的最爱。这类游戏以其简单而有趣的玩法和精致的视觉效果吸引着无数游戏爱好者。然而,对于那些追求更高游戏体验的玩家们来说,寻找完美手感的多段跳成为了重要的目标。在本文中,我们将探讨2D横版平台跳跃游戏中实现多段跳的关键技术,并分享如何获得令人满意的完美手感。

之前我其实写过相关内容,但是写的比较粗糙,这里进行重新整理

先看效果,手感很丝滑

在这里插入图片描述

原理

通常我们将平台跳跃代码放在Update方法中,可能会导致以下问题:

  • 时间不一致:Update方法的调用时间不固定,取决于帧率。这意味着在帧率低的时候,跳跃力会受到较大影响,而在帧率高的时候,跳跃力会变强。这可能导致跳跃不一致,并影响游戏体验。

FixedUpdate的好处:

  • 固定的时间步长:FixedUpdate在固定时间间隔内调用,使得物理模拟更加准确。这意味着在不同的帧率下,物理效果会保持一致,避免了帧率对游戏物理的影响。

  • 避免抖动:使用FixedUpdate可以减少物体在移动过程中的抖动效果。如果将物理计算放在Update中,由于不同帧之间的时间间隔不同,物体的移动可能会不连续,导致抖动现象。

综上所述,平台跳跃代码最好放在FixedUpdate中,以避免时间不一致等问题,并提供更稳定的物理模拟效果。

开始

1. 看到检测点的检测范围

首先为了方便测试,我没调用函数OnDrawGizmosSelected,函数OnDrawGizmosSelected()在鼠标点击到脚本挂载的物体的身上的时候运行,不管有多少父类对象,它都会执行,可以用它看见地面加检测点的检测范围,用于调试有很大帮助

public Transform groundCheck; // 地面检测点
public LayerMask ground; // 地面图层
public float checkRadius;//检测范围

private void FixedUpdate()
{
    
    
  	isGround = Physics2D.OverlapCircle(groundCheck.position, checkRadius, ground); // 检测是否在地面上
}

//鼠标点击到脚本挂载的物体的身上的时候运行
private void OnDrawGizmosSelected()
{
    
    
    if (groundCheck != null)
    {
    
    
        Gizmos.color = Color.red;
        //绘制一个线框球体
        Gizmos.DrawWireSphere(groundCheck.position, checkRadius);
    }
}

可以看见地面加检测点的检测范围了
在这里插入图片描述

2. 二段跳实现

我都加了详细的中文注释,就不过多解释了

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

public class PlayerController : MonoBehaviour
{
    
    
    private Rigidbody2D rb; // 刚体组件
    private Collider2D coll; // 碰撞体组件
    private Animator anim; // 动画组件
    public float speed, jumpForce; // 移动速度和跳跃力度
    public Transform groundCheck; // 地面检测点
    public LayerMask ground; // 地面图层
    public bool isGround, isJump; // 是否在地面上,是否跳跃
    public int canJumpCount = 2;// 可跳跃次数
    bool jumpPressed; // 是否按下跳跃键
    int jumpCount; // 跳跃次数

    //检测范围
    public float checkRadius;

    void Start()
    {
    
    
        rb = GetComponent<Rigidbody2D>(); // 获取刚体组件
        coll = GetComponent<Collider2D>(); // 获取碰撞体组件
        anim = GetComponent<Animator>(); // 获取动画组件
    }

    void Update()
    {
    
    
        if (Input.GetButtonDown("Jump") && jumpCount > 0)
        {
    
    
            jumpPressed = true; // 如果按下跳跃键并且还有跳跃次数,设置 jumpPressed 为 true
        }

    }

    private void FixedUpdate()
    {
    
    
        isGround = Physics2D.OverlapCircle(groundCheck.position, checkRadius, ground); // 检测是否在地面上
        GroundMovement(); // 地面移动
        Jump(); // 跳跃
        SwitchAnim();//动画切换
    }

    //画出的射线可以看见
    private void OnDrawGizmosSelected()
    {
    
    
        if (groundCheck != null)
        {
    
    
            Gizmos.color = Color.red;
            Gizmos.DrawWireSphere(groundCheck.position, checkRadius);
        }

    }

    void GroundMovement()
    {
    
    
        float horizontal = Input.GetAxisRaw("Horizontal"); // 获取水平方向输入
        rb.velocity = new Vector2(horizontal * speed, rb.velocity.y); // 设置刚体速度
        if (horizontal != 0)
        {
    
    
            transform.localScale = new Vector3(horizontal, 1, 1); // 翻转角色
        }
    }

    void Jump()
    {
    
    
        // 是否在地面上
        if (isGround)
        {
    
    
            jumpCount = canJumpCount; // 如果在地面上,设置可跳跃次数为canJumpCount
            isJump = false; // 设置 isJump 为 false
        }

        if (jumpPressed)
        {
    
    
            //如果按下跳跃键// 在地面上
            if (isGround)
            {
    
    
                isJump = true; // 设置 isJump 为 true
                rb.velocity = new Vector2(rb.velocity.x, jumpForce); // 设置刚体速度
                jumpCount--; // 跳跃次数减 1
                jumpPressed = false; // 设置 jumpPressed 为 false
            }
            else if (jumpCount > 0)
            {
    
    
                Debug.Log("二段跳");
                rb.velocity = new Vector2(rb.velocity.x, jumpForce); // 设置刚体速度
                jumpCount--; // 跳跃次数减 1
                jumpPressed = false; // 设置 jumpPressed 为 false
            }
        }


    }

    // 动画
    void SwitchAnim()
    {
    
    
        anim.SetFloat("isRun", Mathf.Abs(rb.velocity.x)); // 设置动画参数
        if (isGround)
        {
    
    
            anim.SetBool("isFall", false);
            anim.SetBool("isJump", false);
        }
        else if (rb.velocity.y > 0)
        {
    
    
            // 播放跳跃动画
            anim.SetBool("isJump", true);
            anim.SetBool("isFall", false);
        }
        else if(rb.velocity.y < 0)
        {
    
    
            // 播放下落动画
            anim.SetBool("isFall", true);
            anim.SetBool("isJump", false);
        }
    }
}

3. 动画控制器配置

在这里插入图片描述

源码

https://download.csdn.net/download/qq_36303853/87695336

扩展

在现实世界物理上,一个物体的跳跃跟落下,时间应该是相等的。我们都知道
在这里插入图片描述

对于Unity内置的游戏物理引擎,它们也是这样来处理最简单的跳跃的运动。但其实这样的效果并不是我们所想要的。

可以想象,一个角色跳上去,然后轻飘飘的落地,这样的手感是很糟糕的,我们并不希望下落的过程耽误我们太多的时间,同时长时间的下落过程会让角色看起来没有质感。

想要进一步优化跳跃可以看我之前写的一篇文章:实现马里奥一样更具物理感的长按长跳与短跳

完结

如果你发现了文章中存在错误或者有更好的解决方法,也欢迎评论私信告诉我哦

好了,我是向宇,https://xiangyu.blog.csdn.net/

一位在小公司默默奋斗的开发者,出于兴趣爱好,于是开始自习unity。最近创建了一个新栏目【你问我答】,主要是想收集一下大家的问题,有时候一个问题可能几句话说不清楚,我就会以发布文章的形式来回答。 虽然有些问题我可能也不一定会,但是我会查阅各方资料,争取给出最好的建议,希望可以帮助更多想学编程的人,共勉~
请添加图片描述

猜你喜欢

转载自blog.csdn.net/qq_36303853/article/details/131592471
今日推荐