问题背景
当一个物体在两个带碰撞体的方块组成的墙角时,只要”挤一挤”就可以从墙角穿墙而过:
原因分析
根据【Unity】Rigidbody.velocity 的陷阱一文,有以下结论:
使用 transform.Translate()
, transform.RotateAround()
, rigidbody.MovePosition()
, Vector3.MoveTowards()
等方法 “强制” 改变刚体的运动状态时,此时物体速度的改变并不会引发 Rigidbody.velocity
的改变,
- 如果仅使用
MovePosition()
控制物体移动(称之为”仅移动”),刚体组件的velocity
会一直为0 - 如果仅使用
AddForce()
控制物体移动(称之为”仅受力”),它的velocity
与真实速率一致 - 如果同时使用
MovePosition()
和AddForce()
控制物体移动,它的真实速率是”仅移动”和”仅受力”的效果之和,但velocity
的数值和”仅受力”时一致
也就是说,物理系统只能理解由 velocity
的变化而产生的运动(施加力->产生加速度->产生速度/直接修改 velocity
),当对一个由物理系统控制的刚体使用物理系统以外的方法施加运动时,物理系统就无法正确处理该物体的物理行为了,而上述的穿墙bug也正是因为角色本身的移动是由 MovePosition()
控制的,导致物理系统无法正确处理在墙角处的碰撞判定
解决方案
通过修改 velocity
来实现角色移动:
private void Move() {
var speed = _properties.speed; //在编辑器中设置的角色的速度
var verAxis = Input.GetAxisRaw("Vertical");
var horAxis = Input.GetAxisRaw("Horizontal");
Vector3 input = new Vector3(horAxis, 0, verAxis);
_rigidbody.velocity = input * speed;
}
注意事项
transform.Translate()
可能比较好理解,毕竟是通过直接修改 transform
组件来完成的运动,物理系统无法理解很正常,但是为什么 rigidbody.MovePosition()
也不行呢?翻一翻官方文档可以发现,Unity官方对这个方法的描述是:
“移动 kinematic刚体到指定位置”,即该方法仅作用于运动学刚体,即不受物理系统控制,需要由各种变换方法直接控制物体移动的刚体,不适用于普通的遵循力学规律的刚体。
Original: https://www.cnblogs.com/m1ds/p/16034873.html
Author: m1ds
Title: [Unity]如何解决带刚体的物体在墙角会穿墙的问题
原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/619561/
转载文章受原作者版权保护。转载请注明原作者出处!