🚀 Unity物理引擎:刚体与碰撞体详解
📖 一、物理引擎简介
1.1 核心定义
物理引擎是模拟现实世界物体运动规律的组件系统,能够真实再现各种物理现象。
物理引擎 刚体运动 碰撞检测 重力模拟 摩擦力计算 关节约束
1.2 主要特点
| 特性 | 描述 | 应用场景 |
|---|---|---|
| 功能强大 | 支持复杂的物理模拟 | 游戏开发、虚拟现实 |
| 实时计算 | 帧率同步的物理更新 | 实时交互应用 |
| 高度可配置 | 参数可调节满足不同需求 | 从休闲到硬核游戏 |
| 跨平台一致 | 在不同设备上表现一致 | 多平台发布 |
1.3 应用领域
- 🎮 游戏开发:角色移动、物体交互、特效模拟
- 🎬 电影制作:特效动画、物理模拟
- 🔬 虚拟仿真:工程模拟、科学可视化
- 🏗️ 建筑可视化:结构力学演示
⚖️ 二、刚体(Rigidbody)详解
2.1 刚体基础概念
刚体是使游戏对象受物理引擎控制的组件,能够响应力、碰撞和重力。
csharp
// 为物体添加刚体组件
Rigidbody rb = gameObject.AddComponent<Rigidbody>();
2.2 关键属性说明
| 属性 | 类型 | 功能描述 | 默认值 |
|---|---|---|---|
| Mass | float | 物体质量(千克) | 1.0 |
| Drag | float | 空气阻力系数 | 0.0 |
| Angular Drag | float | 旋转阻力系数 | 0.05 |
| Use Gravity | bool | 是否受重力影响 | true |
| Is Kinematic | bool | 是否为运动学刚体 | false |
2.3 重要属性深度解析
🔧 Drag(空气阻力)
csharp
public class DragExample : MonoBehaviour
{
void Start()
{
Rigidbody rb = GetComponent<Rigidbody>();
// 低阻力 - 物体移动更远
rb.drag = 0.1f;
// 高阻力 - 物体快速停止
rb.drag = 2.0f;
}
}
⚡ Is Kinematic(运动学控制)
csharp
public class KinematicExample : MonoBehaviour
{
public Rigidbody rb;
void Start()
{
rb = GetComponent<Rigidbody>();
rb.isKinematic = true; // 不受物理力影响
}
void Update()
{
// 手动控制运动学刚体的位置
if (rb.isKinematic)
{
float moveSpeed = 5f;
float horizontal = Input.GetAxis("Horizontal");
transform.Translate(Vector3.right * horizontal * moveSpeed * Time.deltaTime);
}
}
// 动态切换运动学状态
void ToggleKinematic()
{
rb.isKinematic = !rb.isKinematic;
}
}
🔒 Constraints(运动约束)
csharp
public class ConstraintsExample : MonoBehaviour
{
void Start()
{
Rigidbody rb = GetComponent<Rigidbody>();
// 冻结X轴位置和Z轴旋转
rb.constraints = RigidbodyConstraints.FreezePositionX |
RigidbodyConstraints.FreezeRotationZ;
// 常用约束组合
rb.constraints = RigidbodyConstraints.FreezeAll; // 完全冻结
rb.constraints = RigidbodyConstraints.None; // 无约束
}
}
🎯 三、碰撞体(Collider)全面解析
3.1 碰撞体基础
碰撞体定义物体的物理形状,用于碰撞检测,但不直接参与运动。
3.2 碰撞体类型对比
| 类型 | 形状 | 性能 | 适用场景 |
|---|---|---|---|
| Box Collider | 长方体 | ⭐⭐⭐⭐⭐ | 箱子、建筑物 |
| Sphere Collider | 球体 | ⭐⭐⭐⭐⭐ | 球体、圆形物体 |
| Capsule Collider | 胶囊体 | ⭐⭐⭐⭐ | 角色、柱状物 |
| Mesh Collider | 任意网格 | ⭐⭐ | 复杂形状物体 |
| Terrain Collider | 地形 | ⭐⭐⭐ | 游戏地形 |
| Wheel Collider | 车轮 | ⭐⭐⭐ | 车辆系统 |
3.3 碰撞体代码示例
csharp
public class ColliderSetup : MonoBehaviour
{
void Start()
{
// 添加盒子碰撞体
BoxCollider boxCollider = gameObject.AddComponent<BoxCollider>();
boxCollider.size = new Vector3(1, 1, 1);
boxCollider.center = Vector3.zero;
// 添加球形碰撞体
SphereCollider sphereCollider = gameObject.AddComponent<SphereCollider>();
sphereCollider.radius = 0.5f;
}
}
3.4 复合碰撞体
csharp
public class CompoundCollider : MonoBehaviour
{
void Start()
{
// 为复杂物体添加多个简单碰撞体
AddBoxCollider(new Vector3(0, 0.5f, 0), new Vector3(1, 1, 0.2f));
AddCapsuleCollider(new Vector3(0, 1.5f, 0), 0.3f, 1f);
}
void AddBoxCollider(Vector3 center, Vector3 size)
{
BoxCollider collider = gameObject.AddComponent<BoxCollider>();
collider.center = center;
collider.size = size;
}
void AddCapsuleCollider(Vector3 center, float radius, float height)
{
CapsuleCollider collider = gameObject.AddComponent<CapsuleCollider>();
collider.center = center;
collider.radius = radius;
collider.height = height;
}
}
🔄 四、刚体与碰撞体组合应用
4.1 场景组合分析
场景1:主模型有刚体和碰撞体,目标物体只有碰撞体
csharp
public class Scenario1 : MonoBehaviour
{
public GameObject targetObject; // 只有碰撞体的目标
void Start()
{
// 主模型配置
Rigidbody rb = gameObject.AddComponent<Rigidbody>();
BoxCollider collider = gameObject.AddComponent<BoxCollider>();
// 目标物体只有碰撞体(如静态场景)
if (targetObject != null)
{
targetObject.AddComponent<BoxCollider>();
// 没有刚体,所以不会被撞动
}
}
}
适用场景:墙壁、地面等静态环境物体
场景2:主模型只有刚体,目标物体只有碰撞体
csharp
public class Scenario2 : MonoBehaviour
{
void Start()
{
// 主模型只有刚体
Rigidbody rb = gameObject.AddComponent<Rigidbody>();
rb.useGravity = true;
// 没有碰撞体 → 直接穿过其他物体
Debug.Log("物体会直接掉落穿过地面!");
}
}
问题:缺少碰撞检测,物理交互失效
场景3:双方都有刚体和碰撞体
csharp
public class Scenario3 : MonoBehaviour
{
public GameObject otherObject;
void Start()
{
// 双方都有完整的物理组件
SetupPhysics(gameObject);
SetupPhysics(otherObject);
}
void SetupPhysics(GameObject obj)
{
obj.AddComponent<Rigidbody>();
obj.AddComponent<BoxCollider>();
}
}
效果:完美的物理交互,模拟真实碰撞
4.2 实际应用案例
csharp
public class BallGame : MonoBehaviour
{
public GameObject player;
public GameObject ball;
public GameObject goal;
void Start()
{
// 玩家:刚体 + 胶囊碰撞体
SetupPlayer(player);
// 球:刚体 + 球形碰撞体
SetupBall(ball);
// 球门:只有碰撞体(静态)
SetupGoal(goal);
}
void SetupPlayer(GameObject playerObj)
{
Rigidbody rb = playerObj.AddComponent<Rigidbody>();
CapsuleCollider collider = playerObj.AddComponent<CapsuleCollider>();
rb.mass = 70f; // 玩家质量
}
void SetupBall(GameObject ballObj)
{
Rigidbody rb = ballObj.AddComponent<Rigidbody>();
SphereCollider collider = ballObj.AddComponent<SphereCollider>();
rb.mass = 0.5f; // 球的质量
}
void SetupGoal(GameObject goalObj)
{
// 球门是静态的,只有碰撞体
BoxCollider collider = goalObj.AddComponent<BoxCollider>();
collider.isTrigger = true; // 设置为触发器
}
}
🛠️ 五、最佳实践与优化建议
5.1 性能优化技巧
| 技巧 | 说明 | 效果 |
|---|---|---|
| 使用简单碰撞体 | 优先使用Box/Sphere/Capsule | 提升性能30-50% |
| 合理设置质量 | 根据物体大小设置质量 | 物理模拟更稳定 |
| 分层碰撞检测 | 使用Layer减少不必要的检测 | 减少计算量 |
| 休眠机制 | 静止物体进入休眠状态 | 节省CPU资源 |
5.2 常见问题解决
csharp
public class PhysicsDebug : MonoBehaviour
{
void FixedUpdate()
{
// 检测物理相关问题
DebugPhysics();
}
void DebugPhysics()
{
Rigidbody rb = GetComponent<Rigidbody>();
// 检查刚体是否休眠
if (rb.IsSleeping())
{
Debug.Log("刚体处于休眠状态");
}
// 检查碰撞体是否生效
Collider collider = GetComponent<Collider>();
if (!collider.enabled)
{
Debug.LogWarning("碰撞体未启用!");
}
}
}
5.3 物理材质应用
csharp
public class PhysicsMaterialExample : MonoBehaviour
{
void Start()
{
// 创建物理材质
PhysicMaterial bouncyMaterial = new PhysicMaterial();
bouncyMaterial.bounciness = 0.8f; // 弹性
bouncyMaterial.dynamicFriction = 0.1f; // 动态摩擦力
// 应用物理材质
Collider collider = GetComponent<Collider>();
collider.material = bouncyMaterial;
}
}
🎯 六、实战练习项目
项目1:弹珠台物理模拟
csharp
public class PinballMachine : MonoBehaviour
{
public GameObject ball;
public GameObject[] bumpers;
public GameObject flipperLeft;
public GameObject flipperRight;
void Start()
{
SetupBall();
SetupBumpers();
SetupFlippers();
}
void SetupBall()
{
Rigidbody rb = ball.AddComponent<Rigidbody>();
SphereCollider collider = ball.AddComponent<SphereCollider>();
rb.mass = 0.1f;
}
void SetupBumpers()
{
foreach (GameObject bumper in bumpers)
{
// bumper只有碰撞体,产生反弹效果
SphereCollider collider = bumper.AddComponent<SphereCollider>();
PhysicMaterial material = new PhysicMaterial();
material.bounciness = 1.0f;
collider.material = material;
}
}
void SetupFlippers()
{
// flipper有刚体和碰撞体,可以运动
AddFlipperPhysics(flipperLeft);
AddFlipperPhysics(flipperRight);
}
void AddFlipperPhysics(GameObject flipper)
{
Rigidbody rb = flipper.AddComponent<Rigidbody>();
BoxCollider collider = flipper.AddComponent<BoxCollider>();
rb.isKinematic = false;
}
}
项目2:车辆物理系统
csharp
public class VehiclePhysics : MonoBehaviour
{
public WheelCollider[] wheelColliders;
public float motorTorque = 200f;
public float brakeTorque = 100f;
void FixedUpdate()
{
// 车辆物理控制
float vertical = Input.GetAxis("Vertical");
float horizontal = Input.GetAxis("Horizontal");
// 驱动轮设置
for (int i = 0; i < 2; i++) // 前轮驱动
{
wheelColliders[i].motorTorque = vertical * motorTorque;
wheelColliders[i].brakeTorque = Input.GetKey(KeyCode.Space) ? brakeTorque : 0;
}
// 转向轮设置
wheelColliders[0].steerAngle = horizontal * 30f;
wheelColliders[1].steerAngle = horizontal * 30f;
}
}
💡 总结要点
关键知识点回顾
- ✅ 物理引擎:模拟现实物理规律的组件系统
- ✅ 刚体:使物体受物理力影响,控制运动
- ✅ 碰撞体:定义物体形状,用于碰撞检测
- ✅ 组合应用:不同组合产生不同的物理交互效果
学习建议
- 🎯 循序渐进:从简单场景开始,逐步增加复杂度
- 🔧 实践验证:在Unity中实际测试各种组合效果
- 📊 性能意识:注意物理计算的性能影响
- 🐛 调试技巧:学会使用物理调试工具
🚀 下一步学习:掌握物理材质、关节组件、射线检测等高级物理特性!
版权声明 :本文采用 CC BY-NC-SA 4.0 协议
实践建议:在Unity中创建测试场景,亲自体验不同物理组合的效果差异!