最终效果
前言
我们要实现的功能是双击疾跑,当玩家快速地按下同一个移动键两次时能进入跑步状态
我假设快速按下的定义为0.2秒内,按下同一按键两次
简单的分析一下需求,实现它的关键在于获得按键按下的时间,我们需要知道第一次按下按键的时间,然后判断规定时间内有没有按下按键
有两种实现方法
第一种
启动一个计时器,判断在计时器结束之前有没有再次按下这个键
第二种
是分别记录下两次按键的时间,然后用第二次按下的时间减去第一次按下的时间,判断是否小于0.2
这里我采用第二种方法,为了获取按下的时间,我们需要使用到Unity给我们提供的Time类,里面的Time.time会提供游戏启动到现在运行了多少秒,这个需求还需要我们检测到按键是否被按下,我打算使用Input Manager来实现
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进入跑步动画
新增人物控制脚本
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); // 更新刚体速度 } }
效果
参考
如果觉得本文实现的效果不错的话,非常推荐大家去支持一下原作者