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

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

效果演示

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

主要实现功能:

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

人物素材

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

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

动画关系

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

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

角色移动和翻转

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

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

c# 复制代码
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;
    }
}

地面判断相关代码:

c# 复制代码
public void Check()
{
    isGround = Physics2D.OverlapCircle(transform.position, checkRaduis, groundLayer);
}

滑块控制

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

相关代码:

c# 复制代码
public void OnChangeSpeed(float newSpeed)
{
    speed = newSpeed * maxSpeed;
}

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

完整代码

PlayerController.cs

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

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

相关推荐
优梦创客6 小时前
《黑神话悟空》开发框架与战斗系统解析
unity·游戏开发·黑神话悟空·战斗系统·解包
仙魁XAN12 小时前
Unity 设计模式 之 创造型模式-【工厂方法模式】【抽象工厂模式】
unity·设计模式·工厂方法模式·抽象工厂模式
我要吐泡泡了哦14 小时前
GAMES104:15 游戏引擎的玩法系统基础-学习笔记
笔记·学习·游戏引擎
躺下睡觉~1 天前
Unity-Transform类-父子关系
java·unity·游戏引擎
躺下睡觉~1 天前
Unity-Transform类-缩放和看向
unity·游戏引擎
君莫愁。1 天前
【Unity】检测鼠标点击位置是否有2D对象
unity·c#·游戏引擎
咩咩觉主1 天前
Unity实战案例全解析:PVZ 植物卡片状态分析
unity·c#·游戏引擎
蓝裕安1 天前
伪工厂模式制造敌人
开发语言·unity·游戏引擎
谢泽浩1 天前
Unity 给模型贴上照片
unity·游戏引擎
z2014z1 天前
Unity Resource System 优化笔记
unity·游戏引擎