概述 入门系列第 07-08 篇介绍了 PhysX 引擎的基础——Rigidbody、Collider、碰撞事件。当游戏需要 非标准碰撞形状 、自定义物理材质 、大规模碰撞检测 、或 超越 PhysX 的功能 时,内置物理引擎就不够了。
本篇覆盖:物理查询高级用法、CCD(连续碰撞检测)、Physics Scene、以及用 Job System 实现自定义物理。
1. 物理查询进阶 1.1 批量查询 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 public class AdvancedPhysicsQuery : MonoBehaviour { private readonly RaycastHit[] _results = new RaycastHit[32 ]; private readonly Collider[] _overlapResults = new Collider[32 ]; private int BatchRaycast (Vector3 origin, Vector3 direction, float distance ) { return Physics.RaycastNonAlloc(origin, direction, _results, distance); } private int OverlapSphere (Vector3 center, float radius ) { var layerMask = LayerMask.GetMask("Enemy" , "Obstacle" ); return Physics.OverlapSphereNonAlloc(center, radius, _overlapResults, layerMask); } }
1.2 使用 LayerMask 过滤 1 2 3 4 5 6 7 8 9 10 public class LayerMaskFilter : MonoBehaviour { public void FilteredQuery () { var playerMask = LayerMask.GetMask("Player" ); var playerAndEnemy = LayerMask.GetMask("Player" , "Enemy" ); Physics.Raycast(transform.position, transform.forward, out var hit, 100f , playerAndEnemy); } }
2. CCD(连续碰撞检测) 默认 PhysX 使用离散碰撞检测——物体移动过快时会穿透薄物体。CCD 解决这个问题:
1 2 3 4 5 6 7 8 9 public class CCDSetup : MonoBehaviour { private void Start () { var rb = GetComponent<Rigidbody>(); rb.collisionDetectionMode = CollisionDetectionMode.ContinuousDynamic; } }
CCD 模式
性能开销
防穿透效果
Discrete
最低
高速穿透
Continuous
中等
对静态物体有效
Continuous Dynamic
最高
所有物体
3. 自定义物理场景 3.1 独立物理场景 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 public class CustomPhysicsScene : MonoBehaviour { private PhysicsScene _physicsScene; private void Start () { var parameters = new CreateSceneParameters(LocalPhysicsMode.Physics3D); var scene = SceneManager.CreateScene("PhysicsScene" , parameters); _physicsScene = scene.GetPhysicsScene(); } private void FixedUpdate () { if (_physicsScene.IsValid()) _physicsScene.Simulate(Time.fixedDeltaTime); } }
3.2 手动控制模拟 1 2 3 4 5 6 7 8 9 10 11 12 public class ManualPhysics : MonoBehaviour { private void Start () { Physics.autoSimulation = false ; } private void Update () { Physics.Simulate(Time.fixedDeltaTime); } }
4. Job System 自定义物理 当 Unity 物理引擎成为瓶颈时,用 Job System 实现轻量级自定义物理:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 [BurstCompile ] public struct CustomPhysicsJob : IJobParallelFor{ public NativeArray<float3> positions; public NativeArray<float3> velocities; public NativeArray<float > radii; public float deltaTime; public float3 gravity; public void Execute (int index ) { velocities[index] += gravity * deltaTime; positions[index] += velocities[index] * deltaTime; if (positions[index].y < 0 ) { positions[index].y = 0 ; velocities[index].y = -velocities[index].y * 0.5f ; } } }
4.1 球体碰撞 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 [BurstCompile ] public struct SphereCollisionJob : IJobParallelFor{ public NativeArray<float3> positions; public NativeArray<float3> velocities; [ReadOnly ] public NativeArray<float > radii; public void Execute (int index ) { var pos = positions[index]; var vel = velocities[index]; var rad = radii[index]; for (int j = index + 1 ; j < positions.Length; j++) { var delta = positions[j] - pos; var dist = math.length(delta); if (dist < rad + radii[j]) { var normal = delta / dist; var overlap = (rad + radii[j]) - dist; positions[index] -= normal * overlap * 0.5f ; positions[j] += normal * overlap * 0.5f ; var relVel = velocities[j] - vel; var velAlongNormal = math.dot(relVel, normal); if (velAlongNormal > 0 ) continue ; var impulse = normal * velAlongNormal; velocities[index] += impulse; velocities[j] -= impulse; } } } }
5. 物理稳定性提升 1 2 3 4 5 6 7 8 9 10 public class PhysicsStability : MonoBehaviour { private void Awake () { Physics.defaultSolverIterations = 10 ; Physics.defaultSolverVelocityIterations = 4 ; Physics.defaultMaxAngularSpeed = 50f ; Physics.defaultContactOffset = 0.01f ; } }
总结
物理查询 :批量 NonAlloc 版本避免 GC,LayerMask 精确过滤
CCD :高速物体开启 Continuous 防穿透
自定义物理场景 :隔离物理计算
Job System 物理 :简单碰撞可以完全绕过 PhysX 自己实现
空间分区 :Grid / QuadTree / Octree 减少 O(n^2) 碰撞对
下一篇是最后一篇 完整项目框架搭建 ,综合运用本系列所有知识构建可扩展的游戏架构。