RigidBody穿墙问题(PHYSICS):常规方案无效,求代码修改指导
Unity 控制器穿墙问题解决方案
已尝试以下常规碰撞体调整方案,均无效:
- 确保碰撞体非触发器
- 玩家模型与碰撞体尺寸匹配
- 碰撞检测设置为
Continuous Dynamic
问题根源在控制器代码而非碰撞体,实际运行中存在大量穿墙现象。
原控制器代码
void Update() { RaycastHit hit; if (Physics.Raycast(transform.position, Vector3.down, out hit, raycastDist, groundLayer)) isGrounded = true; else isGrounded = false; transform.rotation = Quaternion.Euler(0, angle, 0); float horizontalInput = Input.GetAxis("Horizontal"); angle -= horizontalInput * angleSpeed * Time.deltaTime; Vector3 newPosition = Quaternion.Euler(0, angle, 0) * new Vector3(0, 0, radius); newPosition.y = rb.position.y; // leave Y unchanged to allow for jumps rb.position = newPosition; //jump if (Input.GetKeyDown(KeyCode.Space) && isGrounded) { Debug.Log("Jumping"); rb.AddForce(Vector3.up * jumpForce, ForceMode.Impulse); } }
问题分析
直接通过angle计算位置并赋值给rb.position会忽略物理碰撞:当刚体因碰撞被推离计算出的位置时,angle并未同步更新,下一帧会强制把刚体拉回angle对应的位置,导致穿墙。
修改方案
核心是让angle与刚体实际位置同步,并将物理相关操作移到FixedUpdate(Unity物理更新的专用回调),输入逻辑留在Update:
- 拆分输入与物理操作:
Update只处理输入和地面检测,FixedUpdate处理角度更新和位置同步 - 在
FixedUpdate开头,根据刚体当前位置反向计算angle,保证角度与实际位置一致 - 用
rb.MovePosition替代直接赋值rb.position,让物理系统正确处理碰撞
修改后的代码
private float horizontalInput; void Update() { // 地面检测 RaycastHit hit; isGrounded = Physics.Raycast(transform.position, Vector3.down, out hit, raycastDist, groundLayer); // 输入处理(Update中捕获输入更及时) horizontalInput = Input.GetAxis("Horizontal"); // 跳跃(Input.GetKeyDown在Update中检测更准确) if (Input.GetKeyDown(KeyCode.Space) && isGrounded) { Debug.Log("Jumping"); rb.AddForce(Vector3.up * jumpForce, ForceMode.Impulse); } } void FixedUpdate() { // 从刚体当前位置反向计算angle,同步物理碰撞后的位置变化 Vector3 localPos = transform.InverseTransformPoint(rb.position); angle = Mathf.Atan2(localPos.x, localPos.z) * Mathf.Rad2Deg; // 更新角度 angle -= horizontalInput * angleSpeed * Time.fixedDeltaTime; // 计算目标位置 Vector3 targetPosition = Quaternion.Euler(0, angle, 0) * new Vector3(0, 0, radius); targetPosition.y = rb.position.y; // 使用MovePosition让物理系统处理碰撞 rb.MovePosition(targetPosition); // 更新旋转 transform.rotation = Quaternion.Euler(0, angle, 0); }
关键修改说明
- 同步angle与物理位置:通过
InverseTransformPoint将刚体世界坐标转成局部坐标,再用Atan2计算当前角度,确保碰撞后角度不会脱节 - 物理操作移到FixedUpdate:Unity的物理引擎在
FixedUpdate中更新,这里处理位置和角度能避免抖动,保证物理交互正确 - 使用rb.MovePosition:替代直接赋值
rb.position,让物理系统参与位置更新,碰撞检测会生效,不会强制穿墙
内容的提问来源于stack exchange,提问作者7F7cc
相关产品推荐
相关产品推荐

