3.3 物理引擎 (Physics)


文档摘要

3.3 物理引擎 (Physics) 三、Unity 核心模块父章节领域 3.3 物理引擎 (Physics) 物理引擎是游戏开发中至关重要的核心模块,它负责模拟真实世界中的物理规律,例如重力、碰撞、摩擦力等,为游戏世界带来生动性和交互性。在 Unity3D 中,物理引擎扮演着举足轻重的角色,它使得开发者能够轻松地创建具有真实物理行为的游戏对象,而无需从头开始编写复杂的物理计算代码。 本章节将深入探讨 Unity3D 的物理引擎系统,从基础概念到高级应用,结合代码实践和详细解释,帮助您全面掌握 Unity 物理引擎的使用技巧,为您的游戏开发项目打下坚实的物理基础。 3.3.

3.3 物理引擎 (Physics)

三、Unity 核心模块父章节领域

3.3 物理引擎 (Physics)

物理引擎是游戏开发中至关重要的核心模块,它负责模拟真实世界中的物理规律,例如重力、碰撞、摩擦力等,为游戏世界带来生动性和交互性。在 Unity3D 中,物理引擎扮演着举足轻重的角色,它使得开发者能够轻松地创建具有真实物理行为的游戏对象,而无需从头开始编写复杂的物理计算代码。

本章节将深入探讨 Unity3D 的物理引擎系统,从基础概念到高级应用,结合代码实践和详细解释,帮助您全面掌握 Unity 物理引擎的使用技巧,为您的游戏开发项目打下坚实的物理基础。

3.3.1 物理引擎概述

Unity3D 默认集成了强大的物理引擎,它允许您为游戏对象赋予物理属性,使其能够响应各种物理事件,例如碰撞、受力等。物理引擎的核心目标是模拟真实世界的物理现象,使游戏中的物体运动和交互更加自然和可信。

主要功能:

  • 碰撞检测 (Collision Detection): 检测游戏对象之间是否发生碰撞,并提供碰撞信息。

  • 刚体动力学 (Rigidbody Dynamics): 模拟刚体在力、扭矩和碰撞作用下的运动。

  • 关节 (Joints): 连接多个刚体,模拟铰链、弹簧等物理连接效果。

  • 物理材质 (Physics Materials): 定义物体的表面物理属性,例如摩擦力和弹性。

  • 射线投射 (Raycasting): 模拟发射射线,用于检测场景中的物体,常用于实现射击、点击等交互功能。

  • 物理模拟参数控制 (Physics Simulation Settings): 允许开发者调整物理模拟的全局参数,例如重力、时间步长等。

Unity 物理引擎类型:

Unity 提供了两种主要的物理引擎:

  • Built-in 3D 物理引擎: 基于 PhysX 3.x 版本,是 Unity 默认的 3D 物理引擎,功能全面,性能优秀,适用于大多数 3D 游戏项目。

  • Built-in 2D 物理引擎: 专为 2D 游戏设计,提供 Box2D 物理引擎的封装,优化了 2D 物理模拟的性能和功能。

本章节主要关注 Built-in 3D 物理引擎

mermaid 图表 - 物理引擎在 Unity 中的角色:

图表解释:

  • 物理引擎 (Physics) 是 Unity 游戏引擎的核心模块之一。

  • 它与渲染引擎、输入系统、音频系统和脚本系统等模块紧密协作。

  • 脚本系统 (Scripting) 通过 API 与物理引擎交互,控制物理行为和处理物理事件。

  • 物理引擎提供碰撞检测、刚体动力学、关节、物理材质、射线投射和物理模拟参数控制等核心功能。

3.3.2 刚体 (Rigidbody)

刚体 (Rigidbody) 是 Unity 物理引擎的核心组件,它赋予游戏对象物理属性,使其能够受到物理引擎的控制,参与物理模拟。任何想要受到重力影响、发生碰撞、受力运动的游戏对象,都必须添加 Rigidbody 组件。

Rigidbody 组件的主要属性:

  • Mass (质量): 刚体的质量,影响其惯性和受力后的加速度。质量越大,惯性越大,越难改变其运动状态。

  • Drag (阻力): 模拟空气阻力或流体阻力,减缓刚体的线速度。

  • Angular Drag (角阻力): 模拟旋转阻力,减缓刚体的角速度。

  • Use Gravity (使用重力): 控制刚体是否受到重力影响。

  • Is Kinematic (是否运动学): 设置为 True 时,刚体不受物理引擎控制,只能通过脚本直接控制其 Transform 组件进行运动。常用于角色控制或动画驱动的物体。

  • Interpolate (插值模式): 用于平滑刚体的运动,减少抖动。常见的选项有 None (不插值)、Interpolate (线性插值) 和 Extrapolate (外插值)。

  • Collision Detection (碰撞检测模式): 设置刚体的碰撞检测模式,影响碰撞检测的精度和性能。常见的选项有 Discrete (离散检测)、Continuous (连续检测) 和 Continuous Dynamic (连续动态检测)。

  • Constraints (约束): 限制刚体在特定轴向上的运动和旋转。例如,可以冻结刚体在 Y 轴上的位置,使其只能在 XZ 平面上移动。

代码实践 - 添加和配置 Rigidbody 组件:

using UnityEngine; public class AddRigidbody : MonoBehaviour { void Start() { // 获取当前游戏对象的 Rigidbody 组件,如果不存在则添加一个新的 Rigidbody rb = GetComponent<Rigidbody>(); if (rb == null) { rb = gameObject.AddComponent<Rigidbody>(); } // 配置 Rigidbody 的属性 rb.mass = 10f; // 设置质量为 10kg rb.drag = 0.5f; // 设置阻力为 0.5 rb.useGravity = true; // 启用重力 rb.interpolation = RigidbodyInterpolation.Interpolate; // 启用线性插值 rb.collisionDetectionMode = CollisionDetectionMode.ContinuousDynamic; // 设置为连续动态检测 rb.constraints = RigidbodyConstraints.FreezeRotationX | RigidbodyConstraints.FreezeRotationZ; // 冻结 X 和 Z 轴的旋转 } }

代码解释:

  1. GetComponent<Rigidbody>(): 尝试获取当前游戏对象已有的 Rigidbody 组件。

  2. gameObject.AddComponent<Rigidbody>(): 如果 Rigidbody 组件不存在,则使用 AddComponent 方法添加一个新的 Rigidbody 组件。

  3. rb.mass = 10f;: 设置刚体的质量为 10 公斤。

  4. rb.drag = 0.5f;: 设置刚体的阻力系数为 0.5。

  5. rb.useGravity = true;: 启用刚体的重力效果。

  6. rb.interpolation = RigidbodyInterpolation.Interpolate;: 设置刚体的插值模式为线性插值,使运动更平滑。

  7. rb.collisionDetectionMode = CollisionDetectionMode.ContinuousDynamic;: 设置碰撞检测模式为连续动态检测,提高高速运动物体的碰撞检测精度。

  8. rb.constraints = RigidbodyConstraints.FreezeRotationX | RigidbodyConstraints.FreezeRotationZ;: 通过位运算设置约束,冻结刚体在 X 轴和 Z 轴上的旋转,使其只能绕 Y 轴旋转。

mermaid 图表 - Rigidbody 组件:

图表解释:

  • Rigidbody 组件附加到 GameObject 上,赋予其物理属性。

  • 图中列出了 Rigidbody 组件的主要属性,例如 Mass, Drag, Use Gravity 等。

3.3.3 碰撞器 (Collider)

碰撞器 (Collider) 是定义游戏对象物理形状的组件,物理引擎使用碰撞器来检测物体之间的碰撞。没有碰撞器的 Rigidbody 将无法与其他物体发生碰撞。

常见的碰撞器类型:

  • Box Collider (盒子碰撞器): 立方体形状的碰撞器,适用于大多数方块状物体。

  • Sphere Collider (球形碰撞器): 球体形状的碰撞器,适用于球形物体。

  • Capsule Collider (胶囊碰撞器): 胶囊形状的碰撞器,适用于角色或圆柱形物体。

  • Mesh Collider (网格碰撞器): 基于游戏对象网格形状的碰撞器,可以精确地匹配物体的复杂形状,但性能消耗较高。

  • Terrain Collider (地形碰撞器): 用于地形对象的碰撞器,针对地形数据进行了优化。

  • Wheel Collider (车轮碰撞器): 专为车辆车轮设计的碰撞器,模拟车轮的滚动和摩擦。

  • Composite Collider 2D (复合碰撞器 2D): 2D 物理引擎中的复合碰撞器,可以将多个简单碰撞器组合成复杂的形状。

碰撞检测事件:

当两个带有 Rigidbody 和 Collider 的游戏对象发生碰撞时,会触发一系列碰撞检测事件,脚本可以通过监听这些事件来处理碰撞逻辑。

  • OnCollisionEnter (碰撞开始): 当碰撞开始时调用一次。

  • OnCollisionStay (碰撞持续): 当碰撞持续期间,每帧调用一次。

  • OnCollisionExit (碰撞结束): 当碰撞结束时调用一次。

触发器 (Trigger):

触发器是一种特殊的碰撞器,它用于检测物体进入或离开某个区域,但不会产生物理碰撞效果。触发器常用于实现区域检测、道具拾取等功能。

  • Is Trigger (是否触发器): Collider 组件的属性,设置为 True 时,该碰撞器变为触发器。

  • OnTriggerEnter (触发器进入): 当其他物体进入触发器区域时调用一次。

  • OnTriggerStay (触发器持续): 当其他物体在触发器区域内时,每帧调用一次。

  • OnTriggerExit (触发器离开): 当其他物体离开触发器区域时调用一次。

代码实践 - 添加 Collider 和处理碰撞事件:

using UnityEngine; public class CollisionDetection : MonoBehaviour { void Start() { // 添加 Box Collider 组件,如果不存在则添加一个新的 BoxCollider boxCollider = GetComponent<BoxCollider>(); if (boxCollider == null) { boxCollider = gameObject.AddComponent<BoxCollider>(); boxCollider.size = new Vector3(2f, 2f, 2f); // 设置 Box Collider 的尺寸 } } void OnCollisionEnter(Collision collision) { Debug.Log("碰撞开始! 与物体: " + collision.gameObject.name + " 碰撞"); // 处理碰撞逻辑,例如播放碰撞特效、扣血等 } void OnCollisionStay(Collision collision) { //Debug.Log("碰撞持续! 与物体: " + collision.gameObject.name + " 持续碰撞"); } void OnCollisionExit(Collision collision) { Debug.Log("碰撞结束! 与物体: " + collision.gameObject.name + " 碰撞结束"); // 处理碰撞结束逻辑,例如物体分离等 } void OnTriggerEnter(Collider other) { Debug.Log("触发器进入! 进入物体: " + other.gameObject.name + " 进入触发器"); // 处理触发器进入逻辑,例如道具拾取、区域检测等 } void OnTriggerExit(Collider other) { Debug.Log("触发器离开! 离开物体: " + other.gameObject.name + " 离开触发器"); // 处理触发器离开逻辑 } }

代码解释:

  1. GetComponent<BoxCollider>(): 尝试获取当前游戏对象已有的 Box Collider 组件。

  2. gameObject.AddComponent<BoxCollider>(): 如果 Box Collider 组件不存在,则添加一个新的 Box Collider 组件。

  3. boxCollider.size = new Vector3(2f, 2f, 2f);: 设置 Box Collider 的尺寸为 2x2x2。

  4. OnCollisionEnter(Collision collision): 碰撞开始事件处理函数,collision 参数包含碰撞信息,例如碰撞点、碰撞法线、碰撞物体等。

  5. OnCollisionStay(Collision collision): 碰撞持续事件处理函数。

  6. OnCollisionExit(Collision collision): 碰撞结束事件处理函数。

  7. OnTriggerEnter(Collider other): 触发器进入事件处理函数,other 参数是被触发器触发的 Collider 组件。

  8. OnTriggerExit(Collider other): 触发器离开事件处理函数。

mermaid 图表 - Collider 组件和碰撞事件:

图表解释:

  • Collider 组件附加到 GameObject 上,定义其物理形状。

  • 图中列出了常见的 Collider 类型,以及碰撞事件和触发器事件。

3.3.4 力和运动 (Forces and Motion)

物理引擎的核心功能之一是模拟物体在力作用下的运动。Unity 提供了多种方法来给 Rigidbody 施加力,控制物体的运动。

常用的施力方法:

  • AddForce (添加力): 向刚体施加一个力,使其产生加速度。

    • AddForce(Vector3 force, ForceMode mode = ForceMode.Force)

    • force: 力的方向和大小。

    • mode: 力模式,影响力的应用方式。

      • ForceMode.Force: 持续施力,模拟持续推力或拉力 (默认模式)。

      • ForceMode.Impulse: 瞬时施力,模拟冲击力或爆炸力。

      • ForceMode.Acceleration: 施加速度,忽略质量,直接改变物体的加速度。

      • ForceMode.VelocityChange: 瞬时改变速度,忽略质量,直接设置物体的速度变化量。

  • AddTorque (添加扭矩): 向刚体施加一个扭矩,使其产生旋转。

    • AddTorque(Vector3 torque, ForceMode mode = ForceMode.Force)

    • torque: 扭矩的方向和大小。

    • mode: 力模式,与 AddForce 的力模式相同。

  • AddExplosionForce (添加爆炸力): 向刚体施加一个爆炸力,模拟爆炸效果。

    • AddExplosionForce(float explosionForce, Vector3 explosionPosition, float explosionRadius, float upwardsModifier = 0.0F, ForceMode mode = ForceMode.Force)

    • explosionForce: 爆炸力的大小。

    • explosionPosition: 爆炸中心位置。

    • explosionRadius: 爆炸半径。

    • upwardsModifier: 向上方向的力修正系数。

    • mode: 力模式,与 AddForce 的力模式相同。

直接控制速度:

除了施加力,还可以直接控制 Rigidbody 的速度和角速度。

  • velocity (线速度): 获取或设置刚体的线速度。

    • rb.velocity = new Vector3(10f, 0f, 0f); // 设置水平速度为 10m/s
  • angularVelocity (角速度): 获取或设置刚体的角速度。

    • rb.angularVelocity = new Vector3(0f, 1f, 0f); // 设置绕 Y 轴旋转的角速度为 1rad/s

代码实践 - 施加力控制物体运动:

using UnityEngine; public class ForceMovement : MonoBehaviour { public float moveSpeed = 10f; public float jumpForce = 500f; private Rigidbody rb; void Start() { rb = GetComponent<Rigidbody>(); } void Update() { // 获取水平方向的输入 float horizontalInput = Input.GetAxis("Horizontal"); // 计算水平方向的力 Vector3 moveForce = new Vector3(horizontalInput * moveSpeed, 0f, 0f); // 施加力,使用 ForceMode.Force 模式 rb.AddForce(moveForce); // 检测空格键按下,进行跳跃 if (Input.GetKeyDown(KeyCode.Space)) { // 施加瞬时向上的力,使用 ForceMode.Impulse 模式 rb.AddForce(Vector3.up * jumpForce, ForceMode.Impulse); } } }

代码解释:

  1. moveSpeedjumpForce: 可调节的移动速度和跳跃力参数。

  2. rb = GetComponent<Rigidbody>();: 获取 Rigidbody 组件。

  3. Input.GetAxis("Horizontal"): 获取水平方向的输入,范围为 -1 到 1。

  4. moveForce: 计算水平方向的力向量。

  5. rb.AddForce(moveForce): 使用 AddForce 函数施加水平方向的力,使用默认的 ForceMode.Force 模式,模拟持续的推力。

  6. Input.GetKeyDown(KeyCode.Space): 检测空格键是否按下。

  7. rb.AddForce(Vector3.up * jumpForce, ForceMode.Impulse): 使用 AddForce 函数施加向上的跳跃力,使用 ForceMode.Impulse 模式,模拟瞬时的冲击力。

mermaid 图表 - 力和运动:

图表解释:

  • Rigidbody 组件可以通过 AddForce, AddTorque, AddExplosionForce 等方法施加力。

  • 可以直接控制 Rigidbody 的 velocityangularVelocity 属性来改变其运动状态。

  • AddForceAddTorque 方法可以使用不同的 ForceMode 参数来控制力的应用方式。

3.3.5 关节 (Joints)

关节 (Joints) 组件用于连接多个 Rigidbody,约束它们之间的相对运动,模拟各种物理连接效果,例如铰链、弹簧、绳索等。

常见的关节类型:

  • Fixed Joint (固定关节): 将两个刚体固定在一起,使其相对位置和旋转保持不变。

  • Hinge Joint (铰链关节): 模拟铰链连接,允许两个刚体绕一个轴旋转。

  • Spring Joint (弹簧关节): 模拟弹簧连接,使两个刚体之间存在弹力。

  • Distance Joint (距离关节): 保持两个刚体之间的距离恒定。

  • Character Joint (角色关节): 专为角色动画设计的关节,用于 Ragdoll 效果。

  • Configurable Joint (可配置关节): 功能最强大的关节,可以配置各种自由度和约束,模拟复杂的关节行为。

代码实践 - 创建 Hinge Joint 模拟门:

using UnityEngine; public class HingeDoor : MonoBehaviour { public GameObject doorHandle; // 门把手 GameObject,作为铰链连接点 void Start() { // 获取门把手的 Rigidbody 组件 Rigidbody handleRb = doorHandle.GetComponent<Rigidbody>(); // 获取门的 Rigidbody 组件 Rigidbody doorRb = GetComponent<Rigidbody>(); // 创建 Hinge Joint 组件 HingeJoint hingeJoint = gameObject.AddComponent<HingeJoint>(); // 连接两个 Rigidbody hingeJoint.connectedBody = handleRb; // 设置 Anchor 和 Connected Anchor,定义铰链轴的位置 hingeJoint.anchor = Vector3.zero; // 门上的铰链点,相对于门自身 hingeJoint.connectedAnchor = Vector3.up; // 门把手上的铰链点,相对于门把手自身,向上偏移 // 设置 Axis,定义铰链轴的方向 hingeJoint.axis = Vector3.up; // 绕 Y 轴旋转 // 启用限制角度,限制门的旋转范围 hingeJoint.useLimits = true; JointLimits limits = hingeJoint.limits; limits.min = -90f; // 最小角度 -90 度 limits.max = 0f; // 最大角度 0 度 hingeJoint.limits = limits; } }

代码解释:

  1. doorHandle: 公共变量,用于在 Inspector 面板中指定门把手 GameObject。

  2. handleRb = doorHandle.GetComponent<Rigidbody>();: 获取门把手的 Rigidbody 组件。

  3. doorRb = GetComponent<Rigidbody>();: 获取门的 Rigidbody 组件。

  4. HingeJoint hingeJoint = gameObject.AddComponent<HingeJoint>();: 添加 Hinge Joint 组件到门 GameObject 上。

  5. hingeJoint.connectedBody = handleRb;: 设置连接的 Rigidbody 为门把手的 Rigidbody。

  6. hingeJoint.anchor = Vector3.zero;: 设置铰链点在门上的位置,相对于门的局部坐标系,设置为原点 (0,0,0)。

  7. hingeJoint.connectedAnchor = Vector3.up;: 设置铰链点在门把手上的位置,相对于门把手的局部坐标系,向上偏移 (0,1,0)。

  8. hingeJoint.axis = Vector3.up;: 设置铰链轴的方向为 Y 轴,门将绕 Y 轴旋转。

  9. hingeJoint.useLimits = true;: 启用角度限制。

  10. JointLimits limits = hingeJoint.limits;: 获取关节的限制角度属性。

  11. limits.min = -90f; limits.max = 0f;: 设置最小角度为 -90 度,最大角度为 0 度,限制门的旋转范围。

  12. hingeJoint.limits = limits;: 将设置好的角度限制应用到关节上。

mermaid 图表 - Joints 组件:

图表解释:

  • Joints 组件用于连接多个 Rigidbody,约束它们之间的运动。

  • 图中列出了常见的 Joint 类型,以及 Joint 组件的通用属性,例如 Connected Body, Anchor, Axis, Limits 等。

3.3.6 物理材质 (Physics Materials)

物理材质 (Physics Materials) 用于定义游戏对象的表面物理属性,例如摩擦力 (Friction) 和弹性 (Bounciness)。通过调整物理材质,可以模拟不同材质的表面效果,例如冰面、橡胶、木材等。

Physics Material 组件的属性:

  • Static Friction (静态摩擦力): 物体静止时,阻止其开始滑动的摩擦力。

  • Dynamic Friction (动态摩擦力): 物体滑动时,阻碍其滑动的摩擦力。

  • Bounciness (弹性): 物体碰撞时的弹性系数,范围 0 到 1,0 表示完全无弹性,1 表示完全弹性。

  • Friction Combine (摩擦力组合模式): 当两个物体碰撞时,如何组合它们的摩擦力。

    • Average: 取平均值。

    • Minimum: 取最小值。

    • Maximum: 取最大值。

    • Multiply: 相乘。

  • Bounce Combine (弹性组合模式): 当两个物体碰撞时,如何组合它们的弹性。

    • Average: 取平均值。

    • Minimum: 取最小值。

    • Maximum: 取最大值。

    • Multiply: 相乘。


作者与出处
原作者: 灏天文库
来源:灏天文库
整理: 灏天文库整理
由灏天文库平台收录,内容或由平台用户上传,仅供学习交流
发布者: 作者: 灏天文库 转发
评论区 (0)
U