Unity蜘蛛侠游戏摆荡功能异常:玩家穿墙穿地求助
蜘蛛侠摆荡穿模问题解决思路
我正在制作一款蜘蛛侠游戏,已实现摆荡功能,但玩家在摆荡过程中会穿过墙体和地面。
摆荡功能实现代码
using System.Collections; using System.Collections.Generic; using UnityEngine; [System.Serializable] public class Pendulum { public Transform bob_tr; public Tether tether; public Arm arm; public Bob bob; public bool Swinging; Vector3 previousPosition; public GameObject Player; public void Initialize() { bob_tr.transform.position = Player.transform.position; bob_tr.transform.parent = tether.tether_tr; Swinging = false; } public Vector3 MoveBob(Vector3 pos , float time) { if (Input.GetMouseButtonDown(0)) { Swinging = true; } else if (Input.GetMouseButtonUp(0)) { Swinging = false; } if(Swinging == false) { arm.length = Vector3.Distance(bob_tr.transform.localPosition, tether.position); } bob.velocity += GetConstrainedVelocity(pos , previousPosition , time); bob.ApplyGravity(); bob.ApplyDamping(); bob.CapMaxSpeed(); pos += bob.velocity * time; if(Vector3.Distance(pos , tether.position) < arm.length) { pos = Vector3.Normalize(pos - tether.position) * arm.length; return pos; } previousPosition = pos; return pos; } public Vector3 MoveBob(Vector3 pos , Vector3 prevPos , float time) { if (Input.GetMouseButtonDown(0)) { Swinging = true; } else if (Input.GetMouseButtonUp(0)) { Swinging = false; } if(Swinging == false) { arm.length = Vector3.Distance(bob_tr.transform.localPosition, tether.position); } bob.velocity += GetConstrainedVelocity(pos , prevPos , time); bob.ApplyGravity(); bob.ApplyDamping(); bob.CapMaxSpeed(); pos += bob.velocity * time; previousPosition = pos; return pos; } public Vector3 GetConstrainedVelocity(Vector3 currentPos, Vector3 previousPosition , float time) { float distanceToTether; Vector3 constrainedPosition; Vector3 predictedPosition; distanceToTether = Vector3.Distance(currentPos , tether.position); if(distanceToTether > arm.length) { constrainedPosition = Vector3.Normalize(currentPos - tether.position) * arm.length; predictedPosition = (constrainedPosition - previousPosition) / time; return predictedPosition; } return Vector3.zero; } public Vector3 Fall(Vector3 pos , float time) { arm.length = Vector3.Distance(bob_tr.transform.localPosition, tether.position); bob.ApplyGravity(); bob.ApplyDamping(); bob.CapMaxSpeed(); pos += bob.velocity * time; return pos; } }
问题核心分析
当前代码仅处理了摆荡的绳索距离约束逻辑,完全未加入碰撞检测逻辑,玩家位置直接通过速度累加更新,导致穿透场景碰撞体。
解决方案
- 添加路径碰撞检测
在更新玩家位置后,检测上一位置到目标位置的路径是否有障碍物,若有则修正位置并调整速度:
// 在pos += bob.velocity * time;之后插入 Vector3 direction = pos - previousPosition; float distance = direction.magnitude; // 用CapsuleCast更贴合角色碰撞体积,需传入角色胶囊体的上下点和半径 if (Physics.CapsuleCast(previousPosition + Vector3.up, previousPosition - Vector3.up, 0.5f, direction.normalized, out RaycastHit hit, distance)) { pos = hit.point; // 可选:添加碰撞反弹效果 bob.velocity = Vector3.Reflect(bob.velocity, hit.normal) * 0.6f; }
- 改用Unity物理组件处理碰撞
- 若使用
CharacterController:替换直接位置更新为controller.Move(bob.velocity * time),利用内置碰撞逻辑自动阻挡穿透。 - 若使用
Rigidbody:将摆荡计算的速度赋值给rigidbody.velocity,开启碰撞检测并冻结不必要的旋转轴,让物理引擎处理碰撞交互。
- 绳索路径碰撞检测
在GetConstrainedVelocity方法中,添加Physics.Linecast检测锚点到玩家当前位置的连线是否被阻挡,若阻挡则终止摆荡,避免玩家被绳索拉进障碍物内部。
内容的提问来源于stack exchange,提问作者GhostPlays74
相关产品推荐
相关产品推荐

