【Unity】2D角色跳跃控制器

news2024/11/25 11:45:04

最近加了学校的Nova独游社,本文是社团出的二面题,后续有时间优化下可能会做成一个二维冒险小游戏。本文主要涉及相关代码,参考教程:《勇士传说》横版动作类游戏开发教程

效果演示

【Unity】2D角色跳跃模拟器

主要实现功能:

  • 角色移动翻转
  • 地图周围空气墙
  • 角色跳跃与长按连跳
  • 地面判断与连跳限制
  • 滑块控制速度与弹跳力

人物素材

人物素材选用的是童年游戏《死神VS火影》中黑崎一护卍解形态,动作分帧图如下,进行扣绿处理后,可以导入到unity中进行自动切图。

在这里插入图片描述
本项目目前只用到前三个动作:待机动作、奔跑动作和跳跃动作。

动画关系

动画状态图如图所示,首先进入idol待机状态,播放待机动画,根据角色的速度切换奔跑状态。

在这里插入图片描述

任意状态按下空格键,则切换到跳跃状态。跳跃状态使用了混合树,细分成四个状态,jump1为起跳动作,jump2为上升动作,jump3为滞空动作,jump4为落地动作。

在这里插入图片描述

角色移动和翻转

角色的移动主要通过读取用户的输入对刚体的位置进行调整,如果输入为反方向,则沿x轴对人物进行翻转,代码如下:

void Movement()
  {
      float horizontalmove;//定义变量,当horizontalmove等于-1时向左,等于1时向右,等于0时不动;
      horizontalmove = Input.GetAxis("Horizontal");//绑定输入;
      if (horizontalmove != 0)
      {
          rb.velocity = new Vector2(horizontalmove * speed, rb.velocity.y);//更新速度变量
      }

      float faceDir = transform.localScale.x;

      if (horizontalmove > 0)
          faceDir = (float)0.5;
      if (horizontalmove < 0)
          faceDir = (float)-0.5;

      // 人物翻转
      transform.localScale = new Vector3(faceDir, (float)0.5, (float)0.5);
  }

角色跳跃与长按连跳

角色蓄力跳主要通过计时器实现,按下空格时,倒计时启动,如果秒松开,isJumping设为False,执行普通跳跃,直接调整角色y轴位置。如果按住不松手,则持续执行跳跃,倒计时结束再执行普通跳跃,从而跳的更高,代码如下:

void Jump()
{   
    // 普通跳
    if (Input.GetKeyDown(KeyCode.Space) && physicscheck.isGround)
    {
        isJumping = true;
        jumpTimeCounter = jumpTime;
        rb.velocity = new Vector2(rb.velocity.x, jumpForce);
    }
    // 蓄力跳
    if (Input.GetKey(KeyCode.Space) && isJumping == true)
    {
        if(jumpTimeCounter > 0)
        {
            rb.velocity = new Vector2(rb.velocity.x, jumpForce);
            jumpTimeCounter -= Time.deltaTime;
        }
        else
        {
            isJumping = false;
        }
    }
    if (Input.GetKeyUp(KeyCode.Space))
    {
        isJumping = false;
    }
}

地面判断相关代码:

public void Check()
{
    isGround = Physics2D.OverlapCircle(transform.position, checkRaduis, groundLayer);
}

滑块控制

滑块传参只需要在游戏的Canvas中设置Slider,在参数面板中绑定相关方法:

在这里插入图片描述

相关代码:

public void OnChangeSpeed(float newSpeed)
{
    speed = newSpeed * maxSpeed;
}

public void OnChangeJumpForce(float newJumpForce)
{
    jumpForce = newJumpForce * maxJumpForce;
}

完整代码

PlayerController.cs

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

public class PlayerController : MonoBehaviour
{
    public Rigidbody2D rb;  //添加Rigidbody

    [Header("基本属性")]
    public float speed = 10;  //速度
    public float jumpForce = 4; //跳跃力度

    private float jumpTimeCounter;
    public float jumpTime;
    private bool isJumping;

    // Slider相关
    private float maxSpeed = 50;
    private float maxJumpForce = 30;

    private PhysicsCheck physicscheck;

    private void Awake()
    {
        physicscheck = GetComponent<PhysicsCheck>();
    }

    // Update is called once per frame
    void Update()
    {
        Movement();//移动
        Jump();
    }

    void Movement()
    {
        float horizontalmove;//定义变量,当horizontalmove等于-1时向左,等于1时向右,等于0时不动;
        horizontalmove = Input.GetAxis("Horizontal");//绑定输入;
        if (horizontalmove != 0)
        {
            rb.velocity = new Vector2(horizontalmove * speed, rb.velocity.y);//更新速度变量
        }

        float faceDir = transform.localScale.x;

        if (horizontalmove > 0)
            faceDir = (float)0.5;
        if (horizontalmove < 0)
            faceDir = (float)-0.5;

        // 人物翻转
        transform.localScale = new Vector3(faceDir, (float)0.5, (float)0.5);

    }

    void Jump()
    {   
        // 普通跳
        if (Input.GetKeyDown(KeyCode.Space) && physicscheck.isGround)
        {
            isJumping = true;
            jumpTimeCounter = jumpTime;
            rb.velocity = new Vector2(rb.velocity.x, jumpForce);
        }
        // 蓄力跳
        if (Input.GetKey(KeyCode.Space) && isJumping == true)
        {
            if(jumpTimeCounter > 0)
            {
                rb.velocity = new Vector2(rb.velocity.x, jumpForce);
                jumpTimeCounter -= Time.deltaTime;
            }
            else
            {
                isJumping = false;
            }
        }
        if (Input.GetKeyUp(KeyCode.Space))
        {
            isJumping = false;
        }
    }
    public void OnChangeSpeed(float newSpeed)
    {
        speed = newSpeed * maxSpeed;
    }

    public void OnChangeJumpForce(float newJumpForce)
    {
        jumpForce = newJumpForce * maxJumpForce;
    }
}

拓展

对于2D平面游戏来说,有的游戏会做更多优化,比如:

  • 跳跃缓冲(Jump Buffer):当玩家即将落地前按下跳跃键时,该次跳跃命令将被缓存,玩家落地后会直接执行缓存的跳跃命令;包含可以调整大小的 缓存时间;
  • 野狼时间(Coyote Time):当玩家刚刚离开地面几帧时,玩家按下跳跃键仍然可以起跳;包含可以调整大小的野狼时间;

实测发现,只要移动速度和弹跳值合适,手感本身就还不错,因此就没去实现这些有些花哨的设计,不过可以纳入之后拓展的一个考虑范畴。

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

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

相关文章

【从0到1设计一个网关】重试与限流的实现

文章目录 重试限流上文已经讲到了如何设计一个高可用的稳定的网关,那么这里就实现其中两种比较常用的方法。 重试 这里的重试,我将会在IO异常以及请求超时的时候进行一个请求重试。 首先,我们在路由过滤器中添加一个重试的函数,用于在请求出现如上两个异常的时候进行重试。…

帧间快速算法论文阅读

Low complexity inter coding scheme for Versatile Video Coding (VVC) 通过分析相邻CU的编码区域&#xff0c;预测当前CU的编码区域&#xff0c;以终止不必要的分割模式。 &#x1d436;&#x1d448;1、&#x1d436;&#x1d448;2、&#x1d436;&#x1d448;3、&#x…

论文阅读—— CEASC(cvpr2023)

arxiv&#xff1a;https://arxiv.org/abs/2303.14488 github&#xff1a;https://github.com/Cuogeihong/CEASC 为了进一步减轻SC中的信息损失&#xff0c;使训练过程更加稳定&#xff0c;我们在训练过程中除了稀疏卷积之外&#xff0c;还保持了正常的密集卷积&#xff0c;生成…

JAVA- 面向对象编程(上)

&#x1f308;个人主页: Aileen_0v0&#x1f525;系列专栏:PYTHON学习系列专栏&#x1f4ab;个人格言:"没有罗马,那就自己创造罗马~" 目录 面向对象的特征及理解 new Static Summary: 面向对象的特征及理解 面试题:oop的三大特征是什么? ---> 封装,继承,…

Gorm 中的迁移指南

探索使用 GORM 在 Go 中进行数据库迁移和模式更改的世界 在应用程序开发的不断变化的景观中&#xff0c;数据库模式更改是不可避免的。GORM&#xff0c;强大的 Go 对象关系映射库&#xff0c;通过迁移提供了一种无缝的解决方案来管理这些变化。本文将作为您全面的指南&#xf…

【数据结构】败者树的建树与比较过程

文章目录 前置知识归并段 建树过程比较过程疑问为什么比较次数减少了&#xff1f;如果某个归并段的元素一直获胜&#xff0c;没有元素了怎么办&#xff1f;处理方法 1处理方法 2 前置知识 归并段 外部排序算法通常用于处理大规模数据&#xff0c;其中数据量远超过计算机内存的…

社区牛奶智能售货机为你带来便利与实惠

社区牛奶智能售货机为你带来便利与实惠 低成本&#xff1a;社区牛奶智能货机的最大优势在于成本低廉&#xff0c;租金和人工开支都很少。大部分时间&#xff0c;货柜都是由无人操作来完成销售任务。 购买便利&#xff1a;社区居民只需通过手机扫码支付&#xff0c;支付后即可自…

哈希表----数据结构

引入 如果你是一个队伍的队长&#xff0c;现在有 24 个队员&#xff0c;需要将他们分成 6 组&#xff0c;你会怎么分&#xff1f;其实有一种方法是让所有人排成一排&#xff0c;然后从队头开始报数&#xff0c;报的数字就是编号。当所有人都报完数后&#xff0c;这 24 人也被分…

【Python环境管理工具】Anaconda安装及使用教程

Anaconda安装及使用教程 1 Anaconda简介2 Anaconda下载及安装2.1 下载及安装2.2 手动配置环境变量&#xff08;重点&#xff09;2.3 测试Anaconda环境是否配置成功 3 Anaconda使用教程3.1 Anaconda Prompt环境管理的常用命令3.1.1 检查conda3.1.2 管理运行环境 4 Pycharm与Anac…

C++ STL 迭代器失效

一、学习资料 STL迭代器的使用 二、vector容器获取值是下标法和at()的区别 vector<int> vA; int array[]{0,1,2,3,4}; vA.assign(array,array5); cout<<vA[6]<<endl; cout<<va.at(6)<<endl;如上述代码&#xff0c;当使用vA[6]的方式出现访问越…

EASYX播放音频文件

添加winmm.lib的依赖 选中链接器中的输入选项&#xff1a;添加附加依赖项winmm.lib并且应用即可 添加音频相关代码 #include <easyx.h> #include <stdio.h> #include <math.h> // 宏定义 #define WINDOW_WIDTH 800 #define WINDOW_HEIGHT 600 #define MAX_…

K8s学习笔记——资源组件篇

引言 前一篇文章我们介绍了K8s的概念理解和常用命令&#xff0c;这篇我们重点介绍K8s的资源组件和相关配置使用。 1. Node & Pod Node: 是 Pod 真正运行的主机&#xff0c;可以是物理机&#xff0c;也可以是虚拟机。为了管理 Pod&#xff0c;每个 Node 节点上至少要运行…

剖析 Tomcat 线程池与 JDK 线程池的区别和联系

文章目录 引言JDK 线程池Tomcat 线程池Tomcat 连接器Tomcat 的 ExecutorTomcat 线程池配置 区别和联系区别联系 结论 &#x1f389;欢迎来到Java面试技巧专栏~剖析 Tomcat 线程池与 JDK 线程池的区别和联系 ☆* o(≧▽≦)o *☆嗨~我是IT陈寒&#x1f379;✨博客主页&#xff1a…

qt报错permission denied

写fk项目的时候&#xff0c;报这个错&#xff0c;然后网上查&#xff0c;说的是因为之前运行的qt进程没有关闭&#xff0c;然后我在任务管理器上查看&#xff0c;却没有看见有我正在运行的qt程序&#xff0c;我再出现清除 qmake也不可以&#xff0c;然后我再去删除out目录下的所…

软件提示msvcp110.dll丢失的5个修复方法,快速解决dll丢失问题

你是否曾遇到过msvcp110.dll文件丢失的情况&#xff1f;msvcp110.dll是Microsoft Visual C 2012运行时库中的一个动态链接库文件&#xff0c;它是Visual Studio 2012编译的程序所必需的。它包含了许多C标准库函数的实现&#xff0c;如字符串处理、数学运算等。当我们运行一个程…

C# 文件 文件夹 解除占用

文件/文件夹 解除占用或直接删除。 编程语言&#xff1a;C# 这个就不用过多功能描述了。 注册windows 文件/文件夹 右键菜单。 文件夹解除占用&#xff1a;遍历文件夹所有文件&#xff0c;判断是否被占用&#xff0c;先解除文件占用&#xff0c;后解除文件夹占用&#xff0…

Pikachu(一)

暴力破解 Burte Force&#xff08;暴力破解&#xff09;概述 “暴力破解”是一攻击手段&#xff0c;在web攻击中&#xff0c;一般会使用这种手段对应用系统的认证信息进行获取。 其过程就是使用大量的认证信息在认证接口进行尝试登录&#xff0c;直到得到正确的结果。 为了提高…

uni-app学习笔记

目录 一、前期准备 1、项目认识 2、pages.json基本配置 3、创建页面 二、tabBar 1、获取图标 2、代码配置 三、基础认识 1、页面生命周期 2、App.vue应用生命周期 四、基础组件 1、scroll-view可滚动视图区域 2、提示框 3、swiper滑块视图容器 4、form表单组件 一…

第 370 周赛 100112. 平衡子序列的最大和(困难,离散化,权值树状数组)

太难了&#xff0c;看答案理解了半天 题目的要求可以理解为 nums[ij] - ij > nums[ii] - ii &#xff0c;所以问题化为求序列 bi nums[i] - i 的非递减子序列的最大元素和需要前置知识&#xff0c;离散化&#xff0c;树状数组离散化&#xff1a;将分布大却数量少(即稀疏)的…

【嵌入式框架】搭建调试输出、建立时间系统

一、Zorb简介 Zorb Framework是一个基于面向对象的思想来搭建一个轻量级的嵌入式框架。 搭建Zorb Framework的目的是为在不能运行Linux的芯片上快速开发应用&#xff0c;不用反复造轮子。 Zorb Framework的初步设计功能有&#xff1a; 1、时间系统功能zf_time 2、环形缓冲…