Unity更好的移动跳跃手感
实际对比效果
(学习的前提是你对unity移动跳跃等有一定的基础)
优化前的效果
优化后的效果
(这张图如果有卡顿现象建议刷新网页重新试试,因为gif占的内存有点大,为了提供更高质量的gif)
对比之下是不是发现第二张图带来的感觉更好,这里列出具体优化了哪些地方:
- 移动优化:刚开始移动时速度有个缓慢的提升(效果不会很明显,但是对游戏手感有一定增加)
- 跳跃优化:跳跃不再是直上直下,根据按下空格的时间不同跳跃的高度不同、下落的速度也不同
- 背景优化:背景会跟随角色的移动而有轻微的移动,形成视差效果
- 双击加速
- 冲刺(网上有许多教程这里就不说明了)
下面一一来说明这些效果具体是如何实现的:
移动优化
获取按键输入
首先要知道 Update
和 FixedUpdate
的区别
- Update: 在每次渲染新的一帧的时候才会调用,这个函数的更新频率和设备的性能有关,这会导致同一个游戏在不同的机器上效果不一致,有的快有的慢。因为Update的执行间隔不一样了。
- FixedUpdate: 在固定的时间间隔执行,不受游戏帧率的影响,处理 Rigidbody 时,需要用 FixedUpdate 代替Update,因为 FixedUpdate 是以固定的时间间隔来被调用,所以人物运动起来比较平滑(运动起来不会有忽快忽慢的感觉)
根据上述我们可以知道如果玩家的移动是通过 Rigidbody 实现的,我们需要写在 FixedUpdate 中,但是其余获取按键输入等都要写在Update中,否则会出现按键失灵的现象
角色正常移动时我们一般获取按键输入会用这个方式
horizontalmove_int = Input.GetAxisRaw("Horizontal");
GetAxisRaw
这个函数只能返回 -1,0,1 三个数值,是无法实现我们所需要的移动时速度缓慢提升的效果,所以我们需要使用 GetAxis
这个函数,对输入进行平滑的处理,从而使速度有个缓慢提升的效果
- Input.GetAxis: 对于键盘和游戏杆输入设备,该值将处于 -1...1 的范围内。
- Input.GetAxisRaw: 对于键盘和游戏杆输入,该值将处于 -1...1 的范围内。 由于未对输入进行平滑处理,键盘输入将始终为 -1、0 或 1。
根据上述我们在 Update 中写出对应的脚本,并且保留原本的 horizontalmove_int
,在旋转方向时我们会用到这个变量
private float horizontalmove_float; private float horizontalmove_int; void Update() { horizontalmove_int = Input.GetAxisRaw("Horizontal"); horizontalmove_float = Input.GetAxis("Horizontal"); }
操作角色移动
角色的移动我们就通过控制 Rigidbody 实现,根据我们获取到的 horizontalmove_float
来操作,然后根据 horizontalmove_int
实现角色图像的左右翻转
private void FixedUpdate() { rb.velocity = new Vector2(horizontalmove_float * speed, rb.velocity.y); if (horizontalmove_int != 0) transform.localScale = new Vector3(horizontalmove_int, 1, 1); }
跳跃优化
原视频出处:
https://www.youtube.com/watch?v=7KiK0Aqtmzc
(原视频讲的更详细清晰,如果想详细了解原理可以看原视频)
关于跳跃的优化我们是需要在已经写好了跳跃代码的前提下增加新的东西,所以这里就不详细,我们这里直接创建一个新的脚本对已有的跳跃效果进行优化
优化只需要优化两个关键因素,一个是增加下落时的真实性,一个是增加跳跃时的真实性
- 让物体在下路时根据实际的重力调整下落速度使得物体下落更快更真实
- 让物体在跳跃时如果放开了跳跃键,同样让物体根据重力下落
代码如下:
using System.Collections; using System.Collections.Generic; using UnityEngine; public class BetterJump : MonoBehaviour { private Rigidbody2D rb; //创建个变量分开控制两个情况,便于调整,一个是下落的倍率,一个是低跳的倍率 public float fallMultiplier = 4f; public float lowJumpMultiplier = 7f; void Awake() { rb = GetComponent<Rigidbody2D>(); } void Update() { if (rb.velocity.y < 0) { rb.velocity += Vector2.up * Physics2D.gravity.y * (fallMultiplier - 1) * Time.deltaTime; } else if (rb.velocity.y > 0 && !Input.GetButton("Jump")) { rb.velocity += Vector2.up * Physics2D.gravity.y * (lowJumpMultiplier - 1) * Time.deltaTime; } Debug.Log(Physics2D.gravity.y); } }
直接添加脚本挂载到对应角色身上即可。
背景优化
固定的背景带来的游戏体验很呆滞,目前大部分的平台类游戏的背景都会跟随玩家的移动而移动,并且离的越远的背景(图层越靠后)移动速度越慢,可以带来一个很好的视觉效果
这里我用了这个素材,因为作者把不同层次的图片已经重命名完全排好了顺序,可以直接调整素材的 z 轴来调整前后顺序
https://edermunizz.itch.io/free-pixel-art-forest
表面上背景是跟随角色移动,但是每次再切换场景时要通过查找等其他方法获得角色的位置,这会增加一定消耗,不如直接选择让背景跟随摄像机的移动,直接通过拖拽方式获取摄像机,然后根据摄像机的位置移动背景
实现思路如下:
-
每个背景都有一个自己的初始位置,我们要让背景根据自己的初始位置跟随摄像机移动,否则会导致所有背景直接堆叠在摄像机的位置上
-
不同层次的背景移动的速度不一样,通过创建两个浮点型的变量来当做移动速度的倍率(范围为0-1,为0时不移动,为1时完全跟随相机移动),不同的图层调整不同的倍率即可
具体代码如下:
using UnityEngine; public class Parallax : MonoBehaviour { public Transform _camera; //移动速度倍率 public float moverateX, moverateY; //获取初始位置 private float startpointX, startpointY; private void Start() { startpointX = transform.position.x; startpointY = transform.position.y; } private void FixedUpdate() { //背景的移动 transform.position = new Vector3(startpointX + _camera.position.x * moverateX, startpointY + _camera.position.y * moverateY, transform.position.z); } }
双击加速
双击方向键加速移动的问题,主要难度在于判断键盘的输入
判断是否双击方向键,可以通过获取键盘两次按下方向键的时间然后求差,如果在 0.08f(这里经过了多次调整最后选择了这个长度) 以内我们可以判断为是双击然后进行加速
这里我画了个图来说明思路更为清晰:
在判断是按下 A 还是 D 时我们要分开计算,所以代码会有一点冗长
根据我们的思路来直接写出对应的代码:
private void DoubleTouch() // 双击跑步 { //记录第一次放开方向键的时间 if (Input.GetKeyUp(KeyCode.A)) { releaseAtime = Time.time; } if (Input.GetKey(KeyCode.A)) { //记录第二次按下方向键的时间 if (Input.GetKeyDown(KeyCode.A)) pressAtime = Time.time; //如果两次间隔小于 0.08 则提高速度 if (pressAtime - releaseAtime <= 0.08f) { //速度等于原本的速度加上提升的速度,这里是为了方便之后还原速度 speed = normalspeed + speedup; } } //最后判断结束双击时还原最初的速度 if (Input.GetKeyUp(KeyCode.A)) { speed = normalspeed; } //另一个方向键同上 if (Input.GetKeyUp(KeyCode.D)) { releaseDtime = Time.time; } if (Input.GetKey(KeyCode.D)) { if (Input.GetKeyDown(KeyCode.D)) pressDtime = Time.time; if (pressDtime - releaseDtime <= 0.08f) { speed = normalspeed + speedup; } } if (Input.GetKeyUp(KeyCode.D)) { speed = normalspeed; } }
直接将此函数放在 Update 函数中即可直接使用
本文作者:shadow-fy
本文链接:https://www.cnblogs.com/shadow-fy/p/17201358.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步