【Unity基础详解】(6)Unity核心:物理系统
目录
1 碰撞器和触发器
1.1 Box Collider
1.2 Sphere Collider
1.3 Capsule Collider
1.4 Mesh Collider
1.5 Wheel Collider
1.6 碰撞检测
1.6.1 OnCollisionEnter(Collision collision)
1.6.2 OnCollisionStay(Collision collision)
1.6.3 OnCollisionExit(Collision collision)
1.7 触发检测
1.7.1 OnTriggerEnter
1.7.2 OnTriggerExit
1.7.3 OnTriggerStay
1.8 碰撞器和触发器的异同
2 Rigidbody刚体
2.1 Mass质量
2.2 Drag阻力
2.3 Angular Drag角阻力
2.4 Use Gravity使用重力
2.5 Is Kinematic是否遵循动力学
2.6 Interpolate插值
2.7 Collision Detection碰撞检测
2.8 Constraints约束条件
3 Character Controller
4 物体移动大全
4.1 Transform
4.1.1 Transform.position
4.1.2 Transform.Translate
4.1.2.1 Input输入移动
4.1.2.2 GetAxis输入移动
4.2 Rigidbody
4.2.1 Rigidbody.AddForce
4.2.2 Rigidbody.MovePosition
4.2.3 Rigidbody.Velocity
4.3 Character Controller
4.3.1 CharacterController.SimpleMove
4.3.2 CharacterController.Move
Unity 中内置了一套完成的物理引擎,能够完成现实世界的近似模拟。而在 Unity 物理引擎中,刚体组件和碰撞体组件则是无法避开的,刚体组件是让物体产生物理行为的组件,而碰撞体组件则是让刚体与物体产生碰撞的组件。
1 碰撞器和触发器
为物体添加碰撞体组件后,该组件会默认阻挡其他刚体的运动。碰撞体用于定义物体的物理边界形状,虽然本身不可见(类似于空气墙的概念)。例如创建Cube对象时,系统会自动为其添加Box Collider组件。
在基本几何体中:
- 立方体默认配备Box Collider
 - 球体自动带有Sphere Collider
 - 胶囊体则拥有Capsule Collider
 
这些基础碰撞体具有最优的计算性能。通过组合多个碰撞体组件,可以构建更复杂的碰撞形状。
重要说明:要使碰撞生效,刚体必须绑定在被碰撞物体上,而碰撞体本身则不强制要求绑定刚体组件。
1.1 Box Collider

Box Collider是最基础的碰撞体类型,采用立方体外形设计。它广泛应用于游戏中的各类物体,如墙壁、门窗、平台等静态场景元素。此外,Box Collider也适用于角色躯干、载具外壳等动态物体,尤其适合为方形物体(如箱子)提供精确的碰撞检测。
|   参 数  |   含义  |   描述  | 
|   Is Trigger  |   触发器  |   勾选,则该碰撞体可用于触发事件,并被物理引擎忽略  | 
|   Material  |   材质  |   为碰撞体设置不同类型的材质  | 
|   Center  |   中心  |   碰撞体在对象局部坐标中的位置  | 
|   Size  |   大小  |   碰撞体在X、Y、Z方向上的大小  | 
当勾选 Is Trigger 选项时,该对象在发生碰撞动作后将发送三种碰撞信息至脚本参数,分别为:OnTriggerEnter(进入触发)、OnTriggerExit(退出触发)和 OnTriggerStay(持续触发)。
Physics Material 用于设置物理材质属性,支持多种预设类型,包括冰面、金属、塑料和木材等材质选项。
1.2 Sphere Collider

Sphere Collider 是一种球体形状的碰撞组件。其三维尺寸只能按统一比例缩放,无法单独调整单个轴向的尺寸,具体参数如下表所示。
|   参 数  |   含义  |   描述  | 
|   Is Trigger  |   触发器  |   勾选,则该碰撞体可用于触发事件,并被物理引擎忽略  | 
|   Material  |   材质  |   为碰撞体设置不同类型的材质  | 
|   Center  |   中心  |   碰撞体在对象局部坐标中的位置  | 
|   Radius  |   半径  |   设置球形碰撞体的大小  | 
当游戏对象的物理形状为球体时(如落石、乒乓球等),应使用球体碰撞体组件。
1.3 Capsule Collider

Capsule Collider由一个圆柱体和两个半球体组成,其半径和高度均可独立调节。该碰撞体适用于角色控制器,也可与其他不规则形状的碰撞体配合使用。通常会被添加至角色或NPC等游戏对象的碰撞属性中。
|   参 数  |   含义  |   描述  | 
|   Is Trigger  |   触发器  |   勾选,则该碰撞体可用于触发事件,并被物理引擎忽略  | 
|   Material  |   材质  |   为碰撞体设置不同类型的材质  | 
|   Center  |   中心  |   碰撞体在对象局部坐标中的位置  | 
|   Radius  |   半径  |   设置胶囊体形碰撞体的大小  | 
|   Height  |   局度  |   控制碰撞体中圆柱的高度  | 
|   Direction  |   方向  |   设置在对象的局部坐标中胶囊体的纵向所对应的坐标轴,默认是Y轴  | 
1.4 Mesh Collider

Mesh Collider(网格碰撞体)根据Mesh形状产生碰撞体,比起 Box Collider、Sphere Collider和Capsule Collider,Mesh Collider更加精确,但会占用更多的系统资源。专门用于复杂网格所生成的模型。
|   参 数  |   含义  |   描述  | 
|   Convex  |   凸起  |   勾选,则Mesh Collider将会与其他的Mesh Collider发生碰撞  | 
|   Material  |   材质  |   为碰撞体设置不同类型的材质  | 
|   Mesh  |   网格  |   获取游戏对象的网格并将其作为碰撞体  | 
1.5 Wheel Collider
Wheel Collider(车轮碰撞体)是一种针对地面车辆的特殊碰撞体,自带碰撞侦测、轮胎物理现象和轮胎模型,专门用于处理轮胎。

|   参 数  |   含义  |   描述  | 
|   Mass  |   质量  |   用于设置 Wheel Collider 的质量  | 
|   Radius  |   半径  |   用于设置碰撞体的半径大小  | 
|   Wheel Damping Rate  |   车轮减震率  |   用于设置碰撞体的减震率  | 
|   Suspension Distance  |   悬挂距离  |   该项用于设置碰撞体悬挂的最大伸长距离,按照局部坐标来计算, 悬挂总是通过其局部坐标的 Y 轴延伸向下  | 
|   Center  |   中心  |   用于设置碰撞体在对象局部坐标的中心  | 
|   Suspension Spring  |   悬挂弹簧  |   用于设置碰撞体通过添加弹簧和阻尼外力使得悬挂达到目标位置  | 
|   Forward Friction  |   向前摩擦力  |   当轮胎向前滚动时的摩擦力属性  | 
|   Sideways Friction  |   当轮胎侧向滚动时的摩擦力属性  | |
|   Wheel Damping Rate  |   车轮减震率  |   用于设置碰撞体的减震率  | 
|   Wheel Damping Rate  |   车轮减震率  |   用于设置碰撞体的减震率  | 
1.6 碰撞检测
1.6.1 OnCollisionEnter(Collision collision)
触发时机:物体首次与其他物体发生碰撞时
 参数说明:
collision.gameObject:碰撞对象
碰撞点、碰撞法线、接触点等碰撞信息
典型应用:
播放碰撞音效/动画
首次碰撞伤害计算
根据碰撞对象标签/层级执行特定逻辑
1.6.2 OnCollisionStay(Collision collision)
触发时机:碰撞持续期间每帧调用
 参数说明:与OnCollisionEnter参数相同
典型应用:
持续伤害处理
摩擦力/滑动效果实现
碰撞状态持续检测
适用场景:需要持续作用的碰撞效果或状态维护
1.6.3 OnCollisionExit(Collision collision)
触发时机:碰撞关系解除时
参数说明:包含碰撞结束时的相关信息
典型应用:
特效终止
状态恢复
触发后续事件
适用场景:碰撞结束后的清理工作或事件触发
1.7 触发检测
Unity中的触发类回调(Trigger-based)是通过将碰撞体(Collider)设置为触发器(Trigger)来实现的。当碰撞体被设为触发器时,不会产生物理碰撞效果,而是通过触发事件来处理交互。系统提供了三个主要的触发回调方法:OnTriggerEnter、OnTriggerStay和OnTriggerExit,分别用于处理物体进入、停留和离开触发区域时的逻辑,适用于各种需要检测区域交互的场景。
1.7.1 OnTriggerEnter
- 在物体首次进入触发区域时调用
 - 典型应用:触发任务、播放音效、拾取物品等一次性事件
 
1.7.2 OnTriggerExit
在物体离开触发区域时调用 典型应用:
- 结束持续效果(如停止伤害)
 - 恢复原有状态(如解除减速)
 - 终止特定交互行为
 
1.7.3 OnTriggerStay
在物体停留在触发区域内时每帧调用 典型应用:
- 持续伤害效果(如火焰或毒气区域)
 - 持续状态影响(如减速、增益等)
 - 需要持续检测的交互状态
 
1.8 碰撞器和触发器的异同
|   特性  |   碰撞器(Collider)  |   触发器(Trigger)  | 
|   物理反应  |   产生物理碰撞(阻挡物体运动)  |   无物理碰撞,仅触发事件  | 
|   事件函数  |   OnCollisionEnter/Stay/Exit  |   OnTriggerEnter/Stay/Exit  | 
|   配置方式  |   默认状态  |   需勾选Collider的Is Trigger选项  | 
|   必要条件  |   至少一个物体带有Rigidbody  |   至少一个物体带有Rigidbody  | 
2 Rigidbody刚体
Unity 提供了两种刚体组件:Rigidbody 和 Rigidbody2D。本文主要探讨前者。要让游戏对象具备真实的物理特性(如受重力影响),就需要为其添加 Rigidbody 组件,这是实现物理行为的基础组件。通过它,我们可以设置物体的质量、摩擦系数以及碰撞参数等常见物理属性。
从物理学的角度来看,刚体是一种理想模型:在外力作用下,物体能保持形状和尺寸不变,且内部各部分的相对位置始终恒定。
添加该组件的方法很简单:选中目标对象后,在 Inspector 面板中点击"Add Component"按钮,搜索"Rigidbody"即可完成添加。

2.1 Mass质量
设置物体的质量属性,默认值为1千克(kg)。根据物理原理,当物体质量为1kg时,施加9.8N的力即可抵消重力作用;若力值略大于9.8N,物体将产生向上的运动。
2.2 Drag阻力
设置物体的线性运动阻力,默认值为0(无阻力)。阻力方向始终与运动方向相反,数值越大则阻力越强,运动速度衰减越快。当阻力极大时,物体会瞬间停止运动。
2.3 Angular Drag角阻力
设置物体的旋转阻力,默认值为0.05。该阻力作用于物体的所有旋转方向,数值越大则旋转速度衰减越快。若设为0,物体在无重力环境下将持续旋转(无衰减)。
2.4 Use Gravity使用重力
控制物体是否受重力影响。选中时将模拟真实世界中的自由落体运动;未选中时则模拟无重力环境下的运动状态。
2.5 Is Kinematic是否遵循动力学
决定物体是否参与物理模拟。选中后,物体将不受质量、重力、阻力等物理参数影响,仅通过脚本或动画驱动。此选项可降低性能消耗,但需注意:
- 虽然不受物理模拟影响,仍可通过脚本移动其Transform来碰撞其他刚体
 - 只对刚体产生碰撞影响
 
2.6 Interpolate插值
用于解决物理模拟与画面渲染的同步问题。当物体移动出现抖动时,建议调整此选项:
- Interpolate:基于前一帧数据进行平滑处理
 - Extrapolate:基于下一帧预测数据进行平滑处理
 
2.7 Collision Detection碰撞检测
控制高速运动物体的碰撞检测方式:
- Discrete:离散检测(默认,性能最优)
 - Continuous:连续检测(适用于被高速撞击的物体)
 - Continuous Dynamic:动态连续检测(适用于高速运动的物体)
 - Continuous Speculative:扫描式连续检测
 
2.8 Constraints约束条件
限制物体在特定方向上的移动或旋转自由度。默认不施加任何约束,由物理系统完全控制各轴向运动。

我们冻结了这扇门在 XYZ 轴上的移动以及 XZ 轴上的旋转。现在通过物体推动就能实现基本的门效果。如果需要单扇门推动效果(虽然使用物理关节实现会更简便)。
3 Character Controller
Character Controller是Unity中专门用于角色移动和碰撞处理的组件。相比基础的Rigidbody组件,它提供了更高级的控制方式,能够简化角色行走、跳跃等动作的实现流程。
核心功能
基础移动控制
- 提供
 Move()函数实现精确位移- 通过
 SimpleMove()自动处理重力效果- 使用
 isGrounded属性检测地面接触状态
碰撞系统
- 自动处理环境碰撞(包括斜坡和楼梯)
 - 支持多层碰撞检测
 - 可自定义碰撞参数(半径、高度等)
 
物理特性
- 避免Rigidbody的物理副作用(如滑落斜坡)
 - 保持移动稳定性
 - 支持射线检测和触发器交互
 
适用场景
该组件特别适合第三人称游戏中的角色移动系统,包括:
- 基础位移(行走/奔跑)
 - 跳跃动作
 - 简单的环境交互
 
对于需要复杂物理模拟的场景,建议结合Rigidbody组件使用。Character Controller开箱即用,添加后无需额外配置Rigidbody即可实现完整的碰撞检测功能。

Slope Limit:斜坡角度上限,超过该角度角色无法攀爬。
Step Offset:台阶高度阈值(单位:米),仅当台阶低于该值时角色才能跨越。该值不可超过角色控制器高度。
Skin Width:碰撞体穿透深度,决定两个碰撞体间最大允许穿透距离。较大的值可减少抖动,过小可能导致角色卡住,建议设置为碰撞体半径的10%。
Min Move Distance:最小移动距离,通常设为0。适当调高可改善抖动现象。
- 地面检测:isGrounded()
 - 受重力移动:SimpleMove()
 - 不受重力移动:Move()
 - 碰撞检测:OnControllerColliderHit(ControllerColliderHit hit)
 
4 物体移动大全
4.1 Transform
4.1.1 Transform.position
Transform.position是最基础的移动实现方式,其核心原理是逐帧直接更新物体的世界坐标位置。
直观可控:开发者通过代码直接指定物体在三维空间中的精确坐标值
帧同步机制:在Update()或LateUpdate()生命周期函数中更新位置,确保每帧渲染前完成坐标计算
适用场景
- 非物理相关的瞬移效果(如传送点)
 - 精确路径移动(如沿预定轨道运动)
 - UI元素的定位控制
 - 需要完全掌控运动轨迹的场合
 
性能考量:相比Rigidbody物理移动,直接修改position避免了物理计算开销,但需注意:
- 频繁修改可能触发OnTransformChanged事件
 - 与碰撞体配合时需使用Physics.SyncTransforms
 
代码示例:
public float speed = 5.0f;
void Update()
{transform.position += new Vector3(0, 0, speed * Time.deltaTime);
} 
这种移动方式如同在方格纸上绘制运动轨迹,每个坐标点都清晰可见,特别适合需要精确控制位移的初学者和特定场景开发。
4.1.2 Transform.Translate
在Unity游戏开发中,Transform.Translate方法是一种高效实现游戏对象平滑移动的常用工具。它通过每帧调用(如在Update或FixedUpdate函数中),每秒向指定方向移动固定距离。
例如:使用transform.Translate(Vector3.forward * speed * Time.deltaTime)可以让对象每秒沿其前方移动speed个单位距离。
这种方式与直接设置Transform.position属性(如transform.position += Vector3.forward * speed * Time.deltaTime)在移动效果上基本一致,两者都能实现对象的位移。
然而,两者在坐标处理上存在关键差异:当移动需要基于对象的局部坐标系时(例如,对象旋转后需沿自身朝向移动),Transform.Translate方法会自动处理从本地坐标到世界坐标的转换。这避免了手动转换的繁琐步骤,如使用Transform.position时需额外调用transform.TransformDirection来调整方向。因此,在涉及坐标转换的场景下,Transform.Translate不仅简化了代码,还提升了开发效率和可读性。
语法:
transform.Translate(Vector3向量,坐标系(默认为Space.Self));
4.1.2.1 Input输入移动
transform.Translate()是非物理移动使用的比较频繁的一种方式,无论是2D还是3D,适用范围都比较广,我们根据官方给出的函数结合Input类函数实现前后左右移动。
代码示例:
void Update() 
{if (Input.GetKey(KeyCode.W)){transform.Translate(Vector3.forward * speed * Time.deltaTime);}if (Input.GetKey(KeyCode.S)){transform.Translate(Vector3.back * speed * Time.deltaTime);}if (Input.GetKey(KeyCode.A)){transform.Translate(Vector3.left * speed * Time.deltaTime);}if (Input.GetKey(KeyCode.D)){transform.Translate(Vector3.right * speed * Time.deltaTime);}
} 
 
 
动作移动略显生涩,关键帧代码存在重复,且输入响应受帧率制约。
4.1.2.2 GetAxis输入移动
同样使用transform.Translate()方法,只是将Input.GetKey()替换为GetAxis()。
当把轴映射到键盘操作时,其数值范围会超出-1到1的区间。此时的实际值等于当前键盘增量乘以轴灵敏度参数。按照惯例,正值对应键盘向右或向前移动,负值则对应向左或向后移动。需要注意的是,这个数值是独立于帧率计算的,因此使用时无需考虑帧率波动的影响。
代码示例:
void Move2() 
{float h = Input.GetAxis("Horizontal") * speed * Time.deltaTime;float v = Input.GetAxis("Vertical") * speed * Time.deltaTime;Vector3 thisVec = new Vector3(h, 0, v);transform.Translate(thisVec);
} 
4.2 Rigidbody
Rigidbody 组件利用物理引擎来精确控制物体的位置。使用此组件移动物体时,建议在 FixedUpdate 方法中更新数据,因为该方法会在每次物理模拟前自动调用,比 Update 方法更能确保物理运算的准确性。
4.2.1 Rigidbody.AddForce
为刚体施加一个方向力,使其开始运动。此方法适合模拟外力作用下的刚体行为,如子弹发射。
注意事项:该力是累积作用的,不适合通过重复施加力来维持物体运动。
语法:AddForce(Vector3 force, ForceMode mode = ForceMode.Force);
ForceMode 参数说明:
- Force(默认):持续施加的力,受质量影响
 - Acceleration:持续施加的加速度,不受质量影响
 - Impulse:瞬间冲击力,受质量影响
 - VelocityChange:瞬间速度变化,不受质量影响
 
代码示例:使用WASD控制移动
private float speed = 10f;
public Rigidbody rig; //获取当前物体的刚体组件//WASD控制移动示例:
void Update() 
{float h = Input.GetAxis("Horizontal") * speed; //充当force力float v = Input.GetAxis("Vertical") * speed;rig.AddForce(new Vector3(h, 0, v));
} 
缺点:若要达到理想效果,还需额外配置速度控制与力度控制参数,且这些设置需与重量及角速度参数相互配合。
优点:能提供更真实的手感和视觉效果,若参数调节得当,可带来出色的使用体验。
4.2.2 Rigidbody.MovePosition
移动刚体到一个新的位置,移动的同时受到物理模拟的影响。
语法:Rigidbody.MovePosition(新的位置(Vector3));
代码示例1:
public Vector3 newPosition = new Vector3(0, 0, 1);
public Rigidbody rig; //获取当前物体的刚体组件
void FixedUpdate()
{rig.MovePosition(transform.position + newPosition * Time.deltaTime);
} 
代码示例2:使用WASD控制移动
public Rigidbody rig; //获取当前物体的刚体组件
void Update() 
{float h = Input.GetAxis("Horizontal");float v = Input.GetAxis("Vertical");rig.MovePosition(transform.position + new Vector3(h, 0, v) 	* speed * Time.deltaTime);
} 
4.2.3 Rigidbody.Velocity
Rigidbody.Velocity 可以立即赋予物体恒定速度并保持运动状态,特别适合实现跳跃功能。与 AddForce 相比,它能确保每次跳跃高度一致。使用时需要注意在每次跳跃后将速度归零。
代码示例:
public Vector3 high = new Vector3(0, 10, 0);
public Rigidbody rig; //获取当前物体的刚体组件
void Update() 
{if(Input.GetKeyDown(KeyCode.Space)){rig.velocity = high;}
} 
4.3 Character Controller
4.3.1 CharacterController.SimpleMove
以一定速度移动角色,以秒为单位,无需乘以时间,具备重力。
语法:CharacterController.SimpleMove(有方向的力(Vector3));
代码示例:
public float speed = 6;
public CharacterController myCC; //获取当前物体的刚体组件
void Update() 
{myCC.SimpleMove(transform.forward * speed);
} 
4.3.2 CharacterController.Move
以一定速度移动角色,不具备重力,需要自行计算下落。
语法:CharacterController.Move(有方向的力(Vector3));
代码示例:
public float speed = 5;
public CharacterController myCC; //获取当前物体的刚体组件
void Update() 
{myCC.Move(transform.forward * speed * Time.deltaTime);
} 
