前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【Unity】2D角色跳跃控制器

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

作者头像
zstar
发布2023-11-06 09:28:14
4520
发布2023-11-06 09:28:14
举报
文章被收录于专栏:往期博文

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

效果演示

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

主要实现功能:

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

人物素材

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

本项目目前只用到前三个动作:待机动作、奔跑动作和跳跃动作。

动画关系

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

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

角色移动和翻转

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

代码语言:javascript
复制
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轴位置。如果按住不松手,则持续执行跳跃,倒计时结束再执行普通跳跃,从而跳的更高,代码如下:

代码语言:javascript
复制
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;
    }
}

地面判断相关代码:

代码语言:javascript
复制
public void Check()
{
    isGround = Physics2D.OverlapCircle(transform.position, checkRaduis, groundLayer);
}

滑块控制

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

相关代码:

代码语言:javascript
复制
public void OnChangeSpeed(float newSpeed)
{
    speed = newSpeed * maxSpeed;
}

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

完整代码

PlayerController.cs

代码语言:javascript
复制
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):当玩家刚刚离开地面几帧时,玩家按下跳跃键仍然可以起跳;包含可以调整大小的野狼时间;

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

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2023-11-05,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 效果演示
  • 人物素材
  • 动画关系
  • 角色移动和翻转
  • 角色跳跃与长按连跳
  • 滑块控制
  • 完整代码
  • 拓展
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档