【unity实战】Unity实现2D人物双击疾跑

最终效果

前言

我们要实现的功能是双击疾跑,当玩家快速地按下同一个移动键两次时能进入跑步状态

我假设快速按下的定义为0.2秒内,按下同一按键两次

简单的分析一下需求,实现它的关键在于获得按键按下的时间,我们需要知道第一次按下按键的时间,然后判断规定时间内有没有按下按键

有两种实现方法

第一种

启动一个计时器,判断在计时器结束之前有没有再次按下这个键

第二种

是分别记录下两次按键的时间,然后用第二次按下的时间减去第一次按下的时间,判断是否小于0.2

这里我采用第二种方法,为了获取按下的时间,我们需要使用到Unity给我们提供的Time类,里面的Time.time会提供游戏启动到现在运行了多少秒,这个需求还需要我们检测到按键是否被按下,我打算使用Input Manager来实现

csharp 复制代码
public static float GetAxis (string axisName);
public static float GetAxisRaw(string axisName);

GetAxisRaw会在检测到按键后,马上返回1或-1,松开按键后马上变成0

而GetAxis会在检测到按键的时候,从0过渡到1或-1,松开按键后再过渡到0

为了方便,我使用GetAxisRaw来获得输入的时间,当按键按下时意味着GetAxisRaw的返回值为1的绝对值,我们在符合条件的时候使用Time.time来获得当前的时间即可

但显然,我们不希望玩家按下a后马上按下d,还能让人物进入到疾跑状态,所以两个按键的输入时间要分开存储,还有一个需要注意的地方是,当玩家开始走路或疾跑时,a键或d键是按住不放的,所以当玩家在移动的时候,我们要使个bool变量为真,当这个变量为真时,就不再刷新输入的时间

我们设想一下,玩家进入游戏以后,马上按下了一次移动键,如果他电脑开游戏开的特别的快,他第一次按下移动键的时间,离打开游戏不到0.2秒,如果我们存储按键时间的变量,没有初始化,那么会默认赋值为0,当他第一次按下移动时,就会进入到疾跑状态,这很明显是我们不想要看到的bug

所以最后一个要点是给存储按键时间的变量进行初始化,但初始化的只要赋值为多少也是一个值得考虑的问题,如果赋值为一个极大的正数,就算赋值为1万,万一玩家一开始在挂机刚好在10,000.01秒,按一下移动按键,还是会错误地进入到疾跑状态,所以可以给他赋值为,负的最大等待输入时间,如果实在不放心,可以赋值为2倍,这样第一次输入就不会出现bug

经过了这么多的分析,相信你此时此刻已经完全明白了,接下来我们进入到代码实战环节

开始

配置动画,walk为true进入走路动画,run为true进入跑步动画

csharp 复制代码
public class PlayerController : MonoBehaviour
{
    private Rigidbody2D rb;
    private Animator animator;
    public float maxAwaitTime;
    private float leftPressTime, rightPressTime;
    private bool moving, canRun;
    public int walkSpeed, runSpeed;
    private int currentSpeed;
    private float h;

    private void Awake()
    {
        rb = GetComponent<Rigidbody2D>();
        animator = GetComponent<Animator>();
        leftPressTime = rightPressTime = -maxAwaitTime;
    }

    private void Update()
    {
        h = Input.GetAxisRaw("Horizontal");
        ChangeFaceDirection();
        CheckRun();
    }

    private void ChangeFaceDirection()
    {
        if (h == 1)
        {
            transform.localScale = new Vector3(1, 1, 1);
        }
        else if (h == -1)
        {
            transform.localScale = new Vector3(-1, 1, 1);
        }
    }

    private void CheckRun()
    {
        if (h == 1 && !moving)
        {
            if (Time.time - rightPressTime <= maxAwaitTime)
            {
                canRun = true;
            }
            rightPressTime = Time.time;
        }
        
        if (h == -1 && !moving)
        {
            if (Time.time - leftPressTime <= maxAwaitTime)
            {
                canRun = true;
            }
            leftPressTime = Time.time;
        }

		//取 h 的绝对值
        if (Mathf.Abs(h) == 1)
        {
            moving = true;
            if (canRun)
            {
                currentSpeed = runSpeed;
                animator.SetBool("run", true);
            }
            else
            {
                currentSpeed = walkSpeed;
                animator.SetBool("walk", true);
            }
        }
        else
        {
            animator.SetBool("run", false);
            animator.SetBool("walk", false);
            moving = false;
            canRun = false;
        }
    }

    private void FixedUpdate()
    {
        rb.velocity = new Vector2(h * currentSpeed * Time.deltaTime, rb.velocity.y);
    }
}

效果

参考

【视频】https://www.bilibili.com/video/BV1YN4113771/

完结

赠人玫瑰,手有余香!如果文章内容对你有所帮助,请不要吝啬你的点赞评论和关注,以便我第一时间收到反馈,你的每一次支持都是我不断创作的最大动力。当然如果你发现了文章中存在错误或者有更好的解决方法,也欢迎评论私信告诉我哦!

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

一位在小公司默默奋斗的开发者,出于兴趣爱好,于是最近才开始自习unity。如果你遇到任何问题,也欢迎你评论私信找我, 虽然有些问题我可能也不一定会,但是我会查阅各方资料,争取给出最好的建议,希望可以帮助更多想学编程的人,共勉~

相关推荐
谢泽浩18 分钟前
Unity 给模型贴上照片
unity·游戏引擎
z2014z18 分钟前
Unity Resource System 优化笔记
unity·游戏引擎
王维志24 分钟前
Unity 高亮插件HighlightPlus介绍
unity·游戏引擎
DisonTangor1 小时前
Ruffle 继续在开源软件中支持 Adobe Flash Player
游戏·adobe
zaizai10071 小时前
我的demo保卫萝卜中的技术要点
unity
菌菌巧乐兹3 小时前
Unity 百度AI实现无绿幕拍照抠像功能(详解版)
人工智能·百度·unity
VMOS云手机4 小时前
《仙境传说RO:新启航》游戏攻略,VMOS云手机辅助高效挂机助攻!
游戏·云手机·游戏辅助·黑科技·免费云手机
PC端游爱好者5 小时前
战神诸神黄昏9月19日登录PC端! 手机怎么玩战神诸神黄昏
游戏·智能手机·电脑·远程工作·玩游戏
孑么17 小时前
C# 委托与事件 观察者模式
开发语言·unity·c#·游戏引擎·游戏程序
疑惑的杰瑞18 小时前
[C语言]连子棋游戏
c语言·开发语言·游戏