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

news2024/11/18 4:28:25

文章目录

  • 前言
  • 先看效果,手感很丝滑
  • 原理
  • 开始
    • 1. 看到检测点的检测范围
    • 2. 二段跳实现
    • 3. 动画控制器配置
  • 源码
  • 扩展
  • 完结

前言

随着游戏技术的不断发展,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。最近创建了一个新栏目【你问我答】,主要是想收集一下大家的问题,有时候一个问题可能几句话说不清楚,我就会以发布文章的形式来回答。 虽然有些问题我可能也不一定会,但是我会查阅各方资料,争取给出最好的建议,希望可以帮助更多想学编程的人,共勉~
请添加图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Kotlin~Decorator装饰器模式

概念 装饰模式指的是在不必改变原类文件和使用继承的情况下&#xff0c;动态地扩展一个对象的功能。它是通过创建一个包装对象&#xff0c;也就是装饰来包裹真实的对象。可以运行时动态添加新的功能&#xff0c;而无需改变原来的代码。 特点&#xff1a; 灵活扩展新的功能动态…

接口设计的总结

目录 前言 设计好接口的 36 个锦囊 总结 前言 作为后端开发&#xff0c;不管是什么语言&#xff0c;Java、Go 还是 C&#xff0c;其背后的后端思想都是类似的。我们做后端开发工程师&#xff0c;主要工作就是&#xff1a;如何把一个接口设计好。所以&#xff0c;今天就给大家…

北京大学考研机试题:二叉树

【题目来源】https://www.acwing.com/problem/content/description/3474/【题目描述】 如上图所示&#xff0c;由正整数 1&#xff0c;2&#xff0c;3…… 组成了一颗特殊二叉树。 我们已知这个二叉树的最后一个结点是 n。 现在的问题是&#xff0c;结点 m 所在的子树中一共包括…

MobileNeRF在Windows上的配置

MobileNeRF于2023年提出&#xff0c;源码地址&#xff1a;https://github.com/google-research/jax3d/tree/main/jax3d/projects/mobilenerf &#xff0c;论文为&#xff1a;《MobileNeRF: Exploiting the Polygon Rasterization Pipeline for Efficient Neural Field Renderin…

QT自定义工具条渐变背景颜色一例

使用样式定义&#xff1a; QWidget* toolbar new QWidget(this);toolbar->setObjectName("main_tool");toolbar->setStyleSheet("#main_tool{background: qlineargradient(x1:0 , y1:0 , x2:1 , y2:0,""stop:0 rgba(0,255,0, 0.2),"&q…

Nuxt3 components公共组件

1.目录结构 效果实现&#xff1a;写一个公共的right组件&#xff0c;在index和about页面同时引用它 2.index页面引入 index页面显示效果 about页面引用及效果

组件的自定义事件

src/components/School.vue <template><div class"school"><h2>学校名称&#xff1a;{{ name}}</h2><h2>学校地址&#xff1a;{{ address }}</h2><button click"sendSchoolName">把学校名给App</button>…

数据集成的强大联盟:Elasticsearch、Kibana、Logstash、MySQL

通常&#xff0c;很多关系数据项目都使用 MySQL。 它对于标准的 CRUD 操作是有益的&#xff0c;但有时我们需要做额外的过程。 当我们搜索某些内容时&#xff0c;我们会消耗资源或合并多个表。 有时&#xff0c;即使不是&#xff0c;可能仍然需要复杂的 SQL 查询。 也许这不是正…

如何查看OpenAI的AccessToken?

如何查看OpenAI的AccessToken&#xff1f; 记录一下如何查看 OpenAI的 AccessToken 文章目录 如何查看OpenAI的AccessToken&#xff1f;前提具体操作总结 前提 &#x1f4a7;首先&#xff0c;在获取AccessToken前&#xff0c;你需要达成 以下两个条件: 拥有一个可用的OpenA…

ARM CORETEX M0简介

ARM CORETEX M0简介 1. M0处理器简单框图 处理器内核&#xff1a;逻辑控制与运算 内部总线系统&#xff1a;单总线将处理器与外部的存储器和外部连接&#xff0c;进行数据交互&#xff08;冯诺依曼架构&#xff0c;数据与指令一起&#xff09; NVIC&#xff1a;嵌套向量中断控…

【Matlab】智能优化算法_亨利气体溶解度优化算法HGSO

【Matlab】智能优化算法_亨利气体溶解度优化算法HGSO 1.背景介绍2.数学模型2.1 亨利定律2.2 HGSO 3.文件结构4.伪代码5.详细代码及注释5.1 Create_Groups.m5.2 Evaluate.m5.3 fun_checkpoisions.m5.4 fun_getDefaultOptions.m5.5 HGSO.m5.6 main.m5.7 sumsqu.m5.8 update_posit…

机器学习总览

机器学习 1.什么是机器学习&#xff1f; 机器学习是使计算机像人类一样学习与行动的科学&#xff0c;并通过观察与现实世界交互的形式向计算机提供数据和信息&#xff0c;从而随着时间的推移以自主的方式改善其学习。 通过经验提高某些任务性能的计算机程序。 人工智能>机器…

FreeRTOS ~(六)信号量 ~ (1/3)信号量解决同步缺陷

前情提要 FreeRTOS ~&#xff08;四&#xff09;同步互斥与通信 ~ &#xff08;1/3&#xff09;同步的缺陷 FreeRTOS ~&#xff08;五&#xff09;队列的常规使用 ~ &#xff08;1/5&#xff09;队列解决同步缺陷 举例子说明&#xff1a;利用信号量解决前述的"同步的缺陷&…

最具价值开源项目收藏--持续更新

轻量级开源笔记应用&#xff08;memos&#xff09; 该项目基于 Go React.js SQLite 技术栈开发&#xff0c;兼具高性能与可定制性&#xff0c;适用于日常生活办公中的各类笔记管理场景。 开源地址&#xff1a;https://github.com/usememos/memos 跨平台无缝传输文件&#…

揭秘python函数:编程艺术的核心力量(3)

文章目录 前言递归lambda表达式lambda 的参数形式无参数位置参数关键字参数缺省参数可变参数1.包裹位置传递2.包裹关键字传递 带判断条件的lambda表达式列表数据按照字典key的值进行排序 高阶函数的使用内置高阶函数1.map()2.reduce()3.filter() 前言 前面我们已经学习了 pyth…

7-测试模型(2个)

目录 1.软件测试V模型 2.软件测试W模型&#xff08;双V模型&#xff09; 1.软件测试V模型 V模型最早是由Paul Rook在2&#xff10;世纪&#xff18;&#xff10;年代后期提出的&#xff0c;目的是改进软件开发的效率和效果。是瀑布模型的变种。 明确地标注了测试过程中存在的…

前端工程打包部署

打包 直接执行第二个脚本build即可 打包后的文件将会放在dist目录下 部署 NGINX&#xff1a;是一款轻量级的Web服务器/反向代理服务器及电子邮件&#xff08;IMAP/POP3&#xff09;代理服务器。其特点是占用内存少&#xff0c;并发能力强&#xff0c;在各大型互联网公司都有非…

R中高效安装包,以ComplexHeatmap包为例

包安装问题解决方案 1. Biocmanager安装 [2. 手动安装]&#xff08;正在更新……&#xff09; 目录 包安装问题解决方案前言1. install.packages()的介绍1.1 install.packages()的工作原理1.2 install.packages()安装失败的原因1.3 解决方案 2. BiocManage安装ComplexHeatmap总…

kubernetes的概念以及部署

简介&#xff1a; kubernetes&#xff0c;是一个全新的基于容器技术的分布式架构领先方案&#xff0c;是谷歌严格保密十几年的秘密武器----Borg系统的一个开源版本&#xff0c;于2014年9月发布第一个版本&#xff0c;2015年7月发布第一个正式版本。 kubernetes的本质是…

PDF怎么免费分割成多个文件?这几个方法非常好用!

记灵在线工具是一种常用的电子工具&#xff0c;尤其在工作和学习中&#xff0c;我们经常需要使用记灵工具进行文档处理和整理。其中&#xff0c;记灵工具的分割功能是非常有用的&#xff0c;因为它可以将一个大的文件分割成多个较小的文件&#xff0c;从而便于我们对文件进行分…