3、2D 物理系统入门:Rigidbody 2D组件、Collider 2D组件、物理材质、重力与碰撞检测
好,咱们今天来聊聊2D物理系统。说实话,这是很多新手觉得「玄学」的地方——明明代码没写错,角色就是穿墙了,或者跳起来像踩了棉花。别急,我带你把这些组件一个一个捋清楚。
3.1 Rigidbody 2D:让物体动起来的核心
Rigidbody 2D,说白了就是给游戏对象加上「物理身份」。没有它,你的精灵就是个静态图片;加上它,Unity的物理引擎就开始接管了。
关键属性:
- Body Type:有三种模式——Dynamic(动态)、Kinematic(运动学)、Static(静态)。我个人习惯把玩家和怪物设成Dynamic,把移动平台设成Kinematic,墙壁和地面设成Static。
- Gravity Scale:重力倍数。设为0就是失重状态,我做过一个太空跳跃的小游戏,就把这个值调成了0.3。
- Linear Drag / Angular Drag:线性阻力和角阻力。数值越大,物体停得越快。嗯,这里要注意,阻力太大角色会像在泥浆里走路。
避坑指南:我曾经犯过一个低级错误——把玩家的Rigidbody 2D的Body Type设成了Static,结果角色怎么按键盘都不动。后来排查了半天才发现,Static物体是不受力和速度影响的。记住:要移动,就用Dynamic或Kinematic。
3.2 Collider 2D:碰撞的「边界」
Collider 2D定义了物体的碰撞形状。没有它,两个Rigidbody 2D就会互相穿透,像幽灵一样。
常用类型:
- Box Collider 2D:矩形碰撞体,适合墙壁、箱子、平台。
- Circle Collider 2D:圆形碰撞体,适合球类、角色头部。
- Polygon Collider 2D:多边形碰撞体,适合不规则形状。我建议慎用,因为顶点太多会消耗性能。
- Edge Collider 2D:边缘碰撞体,适合悬崖、斜坡边缘。
你想想看,如果一个角色明明是个圆形,你却用Box Collider,那它卡在墙角时就会显得很别扭。所以选对形状很重要。
小技巧:在Inspector面板里,点击Collider组件上的「Edit Collider」按钮,可以手动拖拽调整碰撞体的大小和偏移。我经常用这个功能来微调,让碰撞体比实际图片小一圈,这样玩家操作时手感会更「宽容」。
3.3 物理材质:控制摩擦与弹性
物理材质(Physics Material 2D)决定了物体表面的物理特性。说白了,就是让冰面更滑,让橡胶更有弹性。
两个核心参数:
| 参数 | 作用 | 取值范围 |
|---|---|---|
| Friction | 摩擦力,值越大越难滑动 | 0 ~ 1 |
| Bounciness | 弹性,值越大反弹越高 | 0 ~ 1 |
创建方法很简单:在Project窗口右键 → Create → Physics Material 2D。然后拖拽到Collider组件的Material槽里。
我记得有一次做弹球游戏,把Bounciness设成了1,结果球弹起来越弹越高,根本停不下来。后来才意识到,现实中没有完美的弹性,设成0.8左右比较合理。
3.4 重力:让世界有「重量」
重力在Unity 2D中默认是向下的,数值是-9.81。你可以通过Edit → Project Settings → Physics 2D来调整全局重力。
常见调整场景:
- 平台跳跃游戏:重力设大一点(比如-15),跳跃感更干脆。
- 水下关卡:重力设小一点(比如-3),配合高阻力,模拟水的浮力。
- 太空主题:重力设为0,所有物体漂浮。
注意:每个Rigidbody 2D的Gravity Scale是乘数,不是绝对值。比如全局重力是-9.81,某个物体的Gravity Scale是0.5,那它受到的重力就是-4.905。我曾经在调整跳跃手感时,同时改了全局和单个物体的重力,结果角色飞出了屏幕——嗯,从那以后我学会了先调全局,再微调单个物体。
3.5 碰撞检测:OnCollisionEnter 与 OnTriggerEnter
碰撞检测是物理系统的「眼睛」。Unity提供了两种检测方式:
1. 物理碰撞(Collision):
两个物体发生碰撞后,会互相弹开。常用回调函数:
void OnCollisionEnter2D(Collision2D collision)
{
// 碰撞发生时调用一次
Debug.Log("撞到了:" + collision.gameObject.name);
}
void OnCollisionStay2D(Collision2D collision)
{
// 碰撞持续期间每帧调用
}
void OnCollisionExit2D(Collision2D collision)
{
// 碰撞结束时调用
}
2. 触发器(Trigger):
勾选Collider组件上的「Is Trigger」后,物体可以穿透,但会触发事件。适合检测区域、收集物品、陷阱等。
void OnTriggerEnter2D(Collider2D other)
{
// 进入触发器时调用
if (other.CompareTag("Coin"))
{
Destroy(other.gameObject);
score++;
}
}
核心区别:Collision需要两个物体都有Rigidbody 2D(至少一个是Dynamic),而Trigger只需要一个Collider 2D勾选了Is Trigger。我建议:需要物理反馈的用Collision,只需要逻辑判断的用Trigger。
3.6 实战:搭建一个简单的物理场景
咱们动手试试。创建一个2D场景,放一个地面(Sprite + Box Collider 2D),再放一个球(Sprite + Circle Collider 2D + Rigidbody 2D)。
运行一下,球会掉下来,落在地面上。嗯,这就是最基础的物理模拟。
接下来,给球添加一个物理材质,把Bounciness设为0.6。再运行,球会弹跳几下才停。如果你把地面的Friction设为0,球落地后会滑出去很远。
我个人习惯在调试物理时,打开Scene视图的「Gizmos」开关,这样能看到碰撞体的绿色线框。如果线框和精灵对不上,就手动调整一下。
3.7 常见问题与避坑
- 物体穿透:速度太快,碰撞检测来不及响应。解决方案:把Rigidbody 2D的Collision Detection设为Continuous。
- 角色抖动:刚体被频繁修改位置。解决方案:用AddForce或velocity来控制移动,而不是直接修改transform.position。
- 触发器不触发:检查是否勾选了Is Trigger,以及两个物体中至少有一个有Rigidbody 2D。
我的经验:如果你发现物理表现和预期不符,先检查物体的Layer Collision Matrix(Edit → Project Settings → Physics 2D → Layer Collision Matrix)。我曾经花了两个小时找bug,最后发现是玩家层和敌人层忘了勾选碰撞——嗯,这种低级错误,犯过一次就记住了。
好了,2D物理系统的基础就这些。下一章咱们会深入聊「碰撞检测的进阶用法」,包括射线检测和区域检测。到时候你会发现,物理系统远比你想象的强大。