那么接下来就让我来了解了解什么是 Unity 的物理系统,认识 Rigidbody 和 Collider,搞清楚触发器和碰撞器的区别,并且在此
一、什么是物理系统?
Unity 内置了一套 PhysX 物理引擎,可以模拟真实世界的物理行为:重力、碰撞、摩擦、弹力......
物理系统的两个核心组件:
| 组件 | 作用 | 类比 |
|---|---|---|
| Rigidbody | 让物体受物理规律控制 | 给物体装上"物理大脑" |
| Collider | 定义物体的碰撞形状 | 给物体装上"身体轮廓" |
只有 Collider 没有 Rigidbody → 静止障碍物(墙壁、地板) 有 Rigidbody 有 Collider → 会动的物体(小球、角色、箱子)
基础上实现一个碰到墙壁就会反弹的小球。
二、Rigidbody --- 物理大脑
1. 什么是 Rigidbody?
Rigidbody(刚体)是让 Unity 接管物体运动的组件。挂上它之后,物体就会受重力、力、碰撞等物理影响,不再需要你手动改位置。

2. Inspector 参数详解
| 参数 | 说明 | 建议值 |
|---|---|---|
| Mass | 质量(kg),影响碰撞力度 | 默认 1 |
| Drag | 空气阻力,越大减速越快 | 0 = 无阻力 |
| Angular Drag | 旋转阻力 | 默认 0.05 |
| Use Gravity | 是否受重力 | 地面物体勾选 |
| Is Kinematic | 开启后不受物理力影响,只能用代码控制 | 需要手动控制时开启 |
| Constraints | 冻结某个轴的位移或旋转 | 防止物体乱转时用 |
3. 常用 API
cs
// --- 获取组件 ---
private Rigidbody rb;
void Awake()
{
rb = GetComponent<Rigidbody>();
}
// --- 施加力(最常用) ---
rb.AddForce(Vector3.forward * 10f); // 普通力(持续加速)
rb.AddForce(Vector3.up * 5f, ForceMode.Impulse); // 瞬间冲量(跳跃用)
rb.AddForce(Vector3.right * 3f, ForceMode.VelocityChange);// 直接改速度(不考虑质量)
// --- 速度控制 ---
rb.velocity = new Vector3(0, 0, 5f); // 直接设置速度
rb.velocity = Vector3.zero; // 立刻停止
// --- 物理移动(比直接改position更稳定)---
rb.MovePosition(rb.position + dir * speed * Time.fixedDeltaTime);
4. ForceMode 四种模式对比
| ForceMode | 说明 | 适合场景 |
|---|---|---|
| Force | 持续力,受质量影响 | 引擎推力、风力 |
| Impulse | 瞬间冲量,受质量影响 | 跳跃、爆炸 |
| Acceleration | 持续加速,不受质量影响 | 重力系统 |
| VelocityChange | 直接改速度,不受质量影响 | 急停、传送带 |
三、Collider --- 碰撞体轮廓
1. 什么是 Collider?
就像你走路撞到墙:
- 你 = 带 Rigidbody 的物体(小球)
- 墙 = 带 Collider 的物体
- 撞上去的感觉 = 物理碰撞
你伸手穿过一束红外线:
- 红外线是 Trigger(触发器)
- 你感觉没东西挡着,但红外线"知道"你穿过了
Collider(碰撞器)定义了物体在物理世界中的形状边界,决定了"哪里能碰到"。
(这里展示的是胶囊体)

2. Collider 的六种类型
Unity 提供了 6 种基础 Collider,分别对应不同形状:
| 类型 | 适用场景 | 形状 | 特点 |
| Box Collider | 箱子、门、墙、建筑 | 方形 | 最常用,效率高 |
| Sphere Collider | 球、圆形物体、炮弹 | 球形 | 圆滚滚的东西 |
| Capsule Collider | 角色、柱子、管道 | 胶囊形 | Unity 角色默认用这个 |
| Mesh Collider | 复杂形状的物体 | 任意形状 | 最精确但最慢 |
| Wheel Collider | 车辆轮子 | 特殊圆形 | 专用于汽车 |
| Terrain Collider | 地形 | 地形高度图 | 配合 Terrain 地形 |
|---|
原则:能用简单形状就不要用 Mesh Collider,性能差很多!
Capsule Collider 胶囊体 Sphere Collider 球体 Box Collider 方体

3. 添加方式
Inspector → Add Component → 搜索 Collider → 选择对应类型


4.基本属性
| 属性 | 含义 | 常用值 |
|---|---|---|
| Center | 碰撞体中心点(相对于物体坐标) | (0, 0, 0) |
| Size | 碰撞体长宽高(米) | (1, 1, 1) |
| Material | 物理材质(弹性、摩擦力) | 可选 |
| Is Trigger | 是否为触发器 | ❌ 否 |
5.代码创建 Box Collider
cs
// 方式1:组件方式(推荐)
BoxCollider box = gameObject.AddComponent<BoxCollider>();
// 设置中心点
box.center = new Vector3(0, 0.5f, 0);
// 设置大小
box.size = new Vector3(2f, 1f, 1f);
// 获取已有的 BoxCollider
BoxCollider existingBox = GetComponent<BoxCollider>();
四、触发器与碰撞器 --- 最容易搞混的概念
1. 一句话区分
cs
Is Trigger = false(默认)→ 碰撞器 → 有物理阻挡,会反弹 → 触发 OnCollision
Is Trigger = true → 触发器 → 可以穿过,无阻挡 → 触发 OnTrigger
2. 直观类比
| 属性 | Is Trigger = false (默认) | Is Trigger = true |
| 物理效果 | 有碰撞,会被挡住 | 无碰撞,直接穿过去 |
| 回调函数 | OnCollision... | OnTrigger... |
| 用途 | 真实物理碰撞 | 检测、拾取、传送 |
|---|
3.何时用哪个?
| 场景 | 用碰撞器 ❌ | 用触发器 ✅ |
|---|---|---|
| 撞墙反弹 | ✅ | ❌ |
| 踩到地砖扣血 | ✅ | ❌ |
| 拾取金币 | ❌ | ✅ |
| 进入传送门 | ❌ | ✅ |
| 检测是否在安全区 | ❌ | ✅ |
4. 碰撞生效的必要条件
- 两个物体都有 Collider
- 至少一个物体有 Rigidbody
- 两个都不是 Is Trigger(碰撞)
- 或至少一个是 Is Trigger(触发)
缺任何一个条件 → 不触发回调!
4.1 对比总结表
| 对比项 | 碰撞器(Collision) | 触发器(Trigger) |
|---|---|---|
| Is Trigger | false | true |
| 物理阻挡 | ✅ 有 | ❌ 无,可穿过 |
| 回调前缀 | OnCollision |
OnTrigger |
| 参数类型 | Collision |
Collider |
| 能获取碰撞点 | ✅ col.contacts |
❌ 没有 |
| 典型用途 | 墙壁、地板、弹跳 | 道具拾取、区域检测 |
4.2 回调函数对比:
| 阶段 | 碰撞器回调 | 触发器回调 |
|---|---|---|
| 刚接触 | OnCollisionEnter(Collision) |
OnTriggerEnter(Collider) |
| 持续接触 | OnCollisionStay(Collision) |
OnTriggerStay(Collider) |
| 离开 | OnCollisionExit(Collision) |
OnTriggerExit(Collider) |
那么我们来试一试碰撞和触发的函数吧!
碰撞器回调:
首先是我们的碰撞回调函数:
- OnCollisionEnter(Collision):碰到另一个碰撞器时调用(触发一次)
- OnCollisionStay(Collision):与碰撞器持续接触时,每帧调用
- OnCollisionExit(Collision):碰撞器分离时调用(触发一次)
那么我们就先搭建一个场景吧,不需要太多东西,只需要一个地板和一个物体,名字自取。
弄好之后我们新建脚本CollisionDemo脚本,把脚本放在物体身上配置好碰撞体和刚体后我们就开始写脚本啦。
首先我们使用OnCollisionEnter()方法在我们两个碰撞体第一次碰撞时候调用:
通过Debug将我们碰撞到的对象的名字打印在控制台
cs
void OnCollisionEnter(Collision collision)
{
Debug.Log($"[碰撞-进入] 碰到了: {collision.gameObject.name}");
}
再用OnCollisionStay()方法在两个碰撞体持续接触时调用:
一样将名字打印在控制台
cs
void OnCollisionStay(Collision collision)
{
Debug.Log($"[碰撞-持续] 还贴着: {collider.gameObeject.name}");
}
最后是我们的一个OnCollisionExit()方法在我们两个碰撞体分离后调用:
cs
void CollisionExit(Collision collision)
{
Debug.Log($"[碰撞-退出] 离开了: {collision.gameObject.name}");
}
那么在运行后就可以在我们控制台发现我们获取到了我们平面Plane,因为我创建后没用修改名字所以就叫Plane。

触发器回调:
接着将我们的触发器回调函数:
-
OnTriggerEnter(Collider):刚接触触发区域时调用(触发一次) -
OnTriggerStay(Collider):待在触发区域内时,每帧调用 -
OnTriggerExit(Collider):从触发区域分离时调用(触发一次)
接着用我们的上一个场景,但是需要吧我们物体碰撞器的Is Tirgger勾上,为了防止下落我们还需要勾上刚体的Is Kinematic,好那么完成后我们开始编写。
首先我们使用OnTriggerEnter()方法在我们第一次进入触发区域的时候调用:
cs
void OnTirggerEnter(Collisoin other)
{
Debug.Log($"[触发-进入] 进入区域,碰到了: {other.gameObject.name}");
}
再用OnTriggerStay()方法在持续待在触发区域时调用:
cs
void OnTriggerStay(Collider other)
{
Debug.Log($"[触发-持续] 还待在区域内: {other.gameObject.name}");
}
最后是我们的一个OnTriggerExit()方法在退出触发区域后调用:
cs
void OnTriggerExit(Collision other)
{
Debug.Log($"[触发-退出] 离开了区域: {other.gameObject.name}")
}
那么写完后运行展示!可以看到我们也成功完成了我们触发器的回调函数,如果大家跟着我做到这里那么应该就已经算是明白了我们的刚体、碰撞器、触发器!

五、物理碰撞弹射实现
最后我们来实现我们今天的任务物理碰撞弹射吧!这个非常的简单。
首先我们先设置我们的刚体和一个碰撞弹射的速度

然后我们需要在初始化时需要获取刚体
最后在我们的碰撞方法中写上我们的一个逻辑,首先获取我们碰撞面的一个朝向,
再用AddForce((normal * shootForce)力向量,(ForceMode.Impulse)发力方式)来实现把球弹射出去

完整代码
cs
using UnityEngine;
public class CollisionDemo : MonoBehaviour
{
[Header("弹射力度")]
public float shootForce = 15f;
private Rigidbody rb;
void Awake()
{
rb = GetComponent<Rigidbody>();
}
void OnCollisionEnter(Collision collision)
{
Debug.Log($"[碰撞-进入] 碰到了: {collision.gameObject.name}");
// 获取碰撞面的朝向(法线方向)
Vector3 normal = collision.contacts[0].normal;
// 沿法线方向施加速度,把球弹射出去
// ForceMode.Impulse = 瞬时冲击力(适合弹射)
rb.AddForce(normal * shootForce, ForceMode.Impulse);
}
}
运行成果展示:
如果想要做的更好就需要规定一下到底谁才能来踢这个球,踢多少的力合适。

今天的内容就到这里! 接下来我将连续更新90天的Untiy教程从基础到一个网络部分,有兴趣的朋友们可以收藏关注,谢谢!如果有疑问,评论区见。