Unity 2D角色静止状态高效检测与停止移动后朝向保留方案咨询
问题解决方案
1. 静止状态检测优化
原方案使用rb.IsSleeping()依赖Unity刚体自带的休眠判定,默认需要刚体完全静止0.1秒以上才会触发休眠,因此天然存在延迟。优化方案如下:
- 新增可配置的静止判定阈值参数,可根据项目手感灵活调整
- 同时检测水平输入是否归零+刚体X轴速度是否低于阈值两个条件,满足就立即判定为静止,无需等待刚体休眠
如果需要完全无延迟的判定(松开按键就判定静止),直接移除速度检测逻辑,只判断输入是否为0即可。
示例修改代码片段:
// 类顶部新增可调节参数 public float stationaryThreshold = 0.1f; // Update中替换原休眠判定行 bool isNoInput = Mathf.Abs(Input.GetAxis("Horizontal")) < 0.01f; bool isLowSpeed = Mathf.Abs(rb.velocity.x) < stationaryThreshold; ani.SetBool("Stationary", isNoInput && isLowSpeed);
2. 角色朝向保持实现
原代码仅在有水平输入时更新动画的Move X参数,输入归零后就丢失了最后一次朝向记录,解决方案是新增变量存储有效朝向:
- 新增私有变量
lastHorizontalDirection,默认值对应角色初始朝向 - 每次水平输入不为0时,同步更新该变量的数值
- 动画参数赋值、角色翻转逻辑都优先使用该变量,输入为0时也不会覆盖原有朝向记录
如果你的角色通过Scale翻转实现左右朝向,在更新朝向变量的位置同步修改Scale数值即可。
示例修改代码片段:
// 类顶部新增变量 private float lastHorizontalDirection = 1f; // 默认朝右 // Update中修改方向判断逻辑 if (Mathf.Abs(direction) > 0.01f) { rb.velocity = new Vector2(direction * speed, rb.velocity.y); ani.SetFloat("Move X", direction); lastHorizontalDirection = direction; // 更新最后朝向 // 开启scale翻转就取消注释下一行 // transform.localScale = new Vector3(lastHorizontalDirection > 0 ? 1 : -1, 1, 1); } else { rb.velocity = new Vector2(0, rb.velocity.y); // 如需动画保持朝向显示,可补充下一行 // ani.SetFloat("Move X", lastHorizontalDirection); }
完整修改后代码
using System.Collections; using System.Collections.Generic; using UnityEngine; public class KittenController2 : MonoBehaviour { Rigidbody2D rb; Animator ani; public float speed; public float jumpForce; public float stationaryThreshold = 0.1f; private float direction = 0f; private float lastHorizontalDirection = 1f; void Start() { rb = GetComponent<Rigidbody2D>(); ani = GetComponent<Animator>(); } void Update() { direction = Input.GetAxis("Horizontal"); bool isNoInput = Mathf.Abs(direction) < 0.01f; bool isLowSpeed = Mathf.Abs(rb.velocity.x) < stationaryThreshold; ani.SetBool("Stationary", isNoInput && isLowSpeed); if (direction > 0f) { rb.velocity = new Vector2(direction * speed, rb.velocity.y); ani.SetFloat("Move X", direction); lastHorizontalDirection = direction; } else if (direction < 0f) { rb.velocity = new Vector2(direction * speed, rb.velocity.y); ani.SetFloat("Move X", direction); lastHorizontalDirection = direction; } else { rb.velocity = new Vector2(0, rb.velocity.y); } if (Input.GetKeyDown(KeyCode.Space)) { Jump(); } } void FixedUpdate() { } void Jump() { rb.AddForce(new Vector2(0f, jumpForce), ForceMode2D.Impulse); ani.SetTrigger("Jump"); } }
内容的提问来源于stack exchange,提问作者Evelyn
相关产品推荐
相关产品推荐

