Unity中如何让自定义移动的Kinematic Rigidbody2D遵守碰撞?
解决方案与问题解析
先纠正你对Kinematic Rigidbody2D的理解
Kinematic刚体的核心逻辑是完全由代码控制运动,Unity物理引擎不会自动对它施加碰撞响应——哪怕开启了use full kinematic contact,也只是让它能触发OnCollisionEnter2D这类碰撞事件,不会自动调整速度或位置来避免穿模。你看到的"忽略Static碰撞、速度不受影响"是正常行为,碰撞检测仅用于告知你"发生了碰撞",修正逻辑需要自己写。
推荐方案:用Dynamic Rigidbody2D实现自定义移动+物理碰撞防穿模
这是最省心的方案,既保留物理引擎的碰撞防穿模能力,又能完全自定义移动逻辑:
- Rigidbody2D设置:
- 类型改为
Dynamic - 开启
Constraints里的Freeze Rotation(避免角色旋转) - 把
Gravity Scale设为0(关闭内置重力,用自己的逻辑控制)
- 类型改为
- 代码逻辑调整:
不要直接硬改velocity(容易和物理引擎的碰撞响应冲突),改用AddForce或者在修正速度时结合物理状态,示例代码如下(优化你的测试逻辑):
这种方式下,当角色碰撞到Static刚体时,物理引擎会自动修正速度和位置,不会出现穿模或卡住的问题,同时你完全掌控移动逻辑。using UnityEngine; public class MovementTest : MonoBehaviour { Rigidbody2D rb; public float maxFallSpeed = 10f; public float gravityAccel = 1f; void Start() { rb = GetComponent<Rigidbody2D>(); rb.gravityScale = 0; rb.constraints = RigidbodyConstraints2D.FreezeRotation; } void FixedUpdate() { // 自定义重力逻辑,限制最大下落速度 if (rb.velocity.y > -maxFallSpeed) { rb.AddForce(Vector2.down * gravityAccel, ForceMode2D.Force); } // 这里可以添加左右移动逻辑,比如: // float horizontalInput = Input.GetAxis("Horizontal"); // rb.AddForce(Vector2.right * horizontalInput * moveForce, ForceMode2D.Force); // 或直接控制velocity.x(需注意碰撞后的速度修正) } }
备选方案:继续用Kinematic,但手动实现碰撞修正
如果坚持用Kinematic,必须提前检测移动路径并修正位置,避免穿模:
- 用
Physics2D.BoxCast或Rigidbody2D.Cast替代单点Raycast,检测角色移动方向上的碰撞 - 在FixedUpdate中,先计算本次想要移动的位移,再用Cast检测该路径上是否有碰撞体
- 如果检测到碰撞,将位移截断到碰撞点的位置,再执行移动
示例逻辑伪代码:
void FixedUpdate() { // 计算想要移动的位移 Vector2 moveDelta = Vector2.down * accel * Time.fixedDeltaTime; // 用BoxCast检测位移路径 RaycastHit2D hit = Physics2D.BoxCast(transform.position, GetComponent<Collider2D>().bounds.size, 0f, moveDelta.normalized, moveDelta.magnitude, LayerMask.GetMask("Ground")); if (hit) { // 碰撞到地面,只移动到碰撞点前的位置 transform.Translate(moveDelta.normalized * hit.distance); // 重置下落速度 rb.velocity = new Vector2(rb.velocity.x, 0); } else { // 无碰撞,正常移动 transform.Translate(moveDelta); // 或更新velocity(Kinematic下velocity仅用于状态记录) rb.velocity = moveDelta / Time.fixedDeltaTime; } }
同时优化地面检测:用多个Raycast(角色底部左右+中间)或者BoxCast,避免单点检测的不稳定导致的穿模/卡住。
不推荐:完全自定义碰撞系统
除非有特殊需求(比如极端性能优化或自定义物理规则),否则不要自己写完整的碰撞系统——需要处理碰撞形状、分层、重叠检测、响应逻辑等大量细节,容易出现各种bug,效率远不如Unity内置物理引擎。
内容的提问来源于stack exchange,提问作者blue_birb
相关产品推荐
相关产品推荐

