Unity物理系统由浅入深第一节:Unity 物理系统基础与应用

Unity物理系统由浅入深第一节:Unity 物理系统基础与应用
Unity物理系统由浅入深第二节:物理系统高级特性与优化
Unity物理系统由浅入深第三节:物理引擎底层原理剖析
Unity物理系统由浅入深第四节:物理约束求解与稳定性

Unity 引擎内置了一套强大且易用的物理系统,它基于 NVIDIA 的 PhysX 物理引擎。这个系统能让你在游戏中模拟真实的物理效果,比如重力、碰撞、摩擦、弹跳等,极大地提升游戏的沉浸感和交互性。本篇教程将带你了解 Unity 物理系统的核心组件和常用 API,让你能够快速地在项目中应用物理效果。


1. Rigidbody(刚体)组件:赋予物体物理属性

在 Unity 中,任何想要受到物理系统影响的 GameObject 都必须附加一个 Rigidbody 组件。Rigidbody 赋予了 GameObject 质量、速度、角速度等物理属性,并使其能够响应重力、力、碰撞等物理事件。

核心属性:
  • Mass (质量):物体的质量,以千克(kg)为单位。质量越大,受到相同力的作用时加速度越小。
  • Drag (阻力):线性阻力,模拟空气阻力或液体阻力。值越大,物体运动减速越快。
  • Angular Drag (角阻力):角阻力,模拟物体旋转时的阻力。值越大,物体旋转减速越快。
  • Use Gravity (使用重力):勾选后,物体将受到 Unity 全局重力设置的影响(默认向下)。
  • Is Kinematic (是否运动学)
    • 如果勾选,Rigidbody 将不再受物理引擎控制,你需要通过代码(Transform.positionTransform.rotation)手动控制它的位置和旋转。运动学刚体通常用于门、电梯等受脚本控制的物体。
    • 重要提示: 运动学刚体不会受到碰撞影响而移动或旋转,但它仍然可以影响其他非运动学刚体,并且会触发碰撞回调。
  • Collision Detection (碰撞检测模式)
    • Discrete (离散):默认模式,在每个物理步长(Fixed Update)只检测一次碰撞。适用于大多数情况,性能开销低,但高速移动的物体可能会“穿透”其他物体。
    • Continuous (连续):适用于高速移动的物体,会进行更频繁的检测以防止穿透。性能开销比 Discrete 高。
    • Continuous Dynamic (连续动态):适用于高速移动且相互之间都需要进行连续碰撞检测的 Rigidbody。性能开销最高。
  • Constraints (约束):可以冻结刚体的特定轴向上的位置或旋转,例如,只允许物体在 X 轴上移动,或者不允许它旋转。
常用操作:
  • Rigidbody.AddForce(Vector3 force, ForceMode mode = ForceMode.Force):给刚体施加一个力。
    • ForceMode.Force: 持续力,以物体的质量计算加速度。
    • ForceMode.Impulse: 瞬间冲量,不考虑时间,直接改变物体的速度。常用于爆炸或打击效果。
    • ForceMode.VelocityChange: 瞬间速度变化,忽略质量。
    • ForceMode.Acceleration: 持续加速度,忽略质量。
  • Rigidbody.AddTorque(Vector3 torque, ForceMode mode = ForceMode.Force):给刚体施加一个扭矩,使其旋转。
  • Rigidbody.velocity: 获取或设置刚体的线性速度。
  • Rigidbody.angularVelocity: 获取或设置刚体的角速度。
using UnityEngine;public class BallController : MonoBehaviour
{public float moveForce = 10f;public float jumpForce = 5f;private Rigidbody rb;void Start(){rb = GetComponent<Rigidbody>();}void FixedUpdate() // 物理计算应该在 FixedUpdate 中进行{// 施加持续力,模拟移动if (Input.GetKey(KeyCode.W)){rb.AddForce(Vector3.forward * moveForce, ForceMode.Force);}if (Input.GetKey(KeyCode.S)){rb.AddForce(Vector3.back * moveForce, ForceMode.Force);}// 施加瞬间冲量,模拟跳跃if (Input.GetKeyDown(KeyCode.Space)){rb.AddForce(Vector3.up * jumpForce, ForceMode.Impulse);}}
}

2. Collider(碰撞体)组件:定义物体的形状

Collider 组件定义了 GameObject 在物理世界中的形状,用于检测与其他物体的碰撞。没有 Collider 的 Rigidbody 无法与其他物体发生物理交互(除了重力)。

常见碰撞体类型:
  • Box Collider (盒碰撞体):最常用的碰撞体,适用于立方体、矩形等规则形状。性能开销低。
  • Sphere Collider (球碰撞体):适用于球体或近似球体的物体。性能开销低。
  • Capsule Collider (胶囊碰撞体):适用于人物角色、圆柱体等。性能开销低。
  • Mesh Collider (网格碰撞体)
    • 使用物体的网格数据作为碰撞形状。
    • 优点: 可以完美匹配复杂模型的形状。
    • 缺点: 性能开销高,特别是对于高多边形模型。
    • Convex (凸包) 选项:勾选后,Mesh Collider 将创建一个凸包形状作为碰撞体。凸包的性能远高于非凸包,并且可以与其他 Mesh Collider 发生碰撞。非凸包 Mesh Collider 只能与 Box、Sphere、Capsule 等原始碰撞体碰撞,不能与其他非凸包 Mesh Collider 碰撞。
    • 通常不建议用于移动的 Rigidbody,除非设置为 Convex。
  • Terrain Collider (地形碰撞体):专门用于 Unity 地形系统,自动与地形的形状匹配。
核心属性:
  • Is Trigger (是否触发器)
    • 如果勾选,这个 Collider 将不会产生物理碰撞响应(如反弹、滑动),而是仅仅检测到与其他 Collider 的重叠
    • 触发器常用于检测区域进入/离开,例如,当玩家进入一个区域时触发剧情或打开门。
    • 两个触发器之间不会产生碰撞回调,除非其中一个至少带有 Rigidbody。
    • 一个触发器和一个非触发器 Collider 之间的交互会触发回调。
  • Material (物理材质):关联一个 Physic Material(详见下一节)。

最佳实践: 尽量使用简单的原始碰撞体(Box、Sphere、Capsule)组合来近似复杂模型的形状,而不是直接使用 Mesh Collider,以获得更好的性能。


3. Physic Material(物理材质):定义交互特性

Physic Material 是一种资源(Asset),用于定义碰撞体之间的摩擦力和弹性(弹跳)。你可以创建不同的物理材质并将其分配给 Collider 组件。

核心属性:
  • Dynamic Friction (动态摩擦):当物体相对运动时产生的摩擦力。
  • Static Friction (静态摩擦):当物体静止时抵抗初始运动的摩擦力。通常应该略高于 Dynamic Friction。
  • Bounciness (弹跳):物体的弹性,0 表示完全不弹跳,1 表示完全弹性碰撞。
  • Friction Combine (摩擦组合模式)
    • Average (平均):取两个碰撞体物理材质的摩擦力平均值。
    • Minimum (最小):取两个碰撞体物理材质摩擦力的最小值。
    • Maximum (最大):取两个碰撞体物理材质摩擦力的最大值。
    • Multiply (相乘):取两个碰撞体物理材质摩擦力的乘积。
  • Bounce Combine (弹跳组合模式):同 Friction Combine,但作用于弹跳。

创建和使用:
在 Project 窗口右键 -> Create -> Physic Material,然后调整其属性,并将其拖拽到 Collider 组件的 “Material” 字段上。


4. 触发器与碰撞回调:响应物理事件

当 Rigidbody 与 Collider 发生交互时,Unity 会调用特定的回调函数。理解这些回调函数是实现游戏逻辑的关键。

碰撞回调 (Collision Callbacks):

适用于两个非触发器 Collider(至少一个带 Rigidbody)之间的物理碰撞。

  • OnCollisionEnter(Collision collision):当物体开始与其他物体碰撞时调用一次。
    • collision 参数包含了碰撞的详细信息,如碰撞点 (collision.contacts)、碰撞法线 (collision.contacts[0].normal)、对方的 GameObject (collision.gameObject) 和 Rigidbody (collision.rigidbody) 等。
  • OnCollisionStay(Collision collision):当物体持续与其他物体碰撞时,每物理帧调用一次。
  • OnCollisionExit(Collision collision):当物体停止与其他物体碰撞时调用一次。
触发器回调 (Trigger Callbacks):

适用于至少有一个 Collider 设置为 Is Trigger 的情况下,检测到物体进入/离开/停留在区域内。

  • OnTriggerEnter(Collider other):当物体开始进入触发器区域时调用一次。
    • other 参数是进入或离开触发器区域的 Collider。
  • OnTriggerStay(Collider other):当物体持续停留在触发器区域内时,每物理帧调用一次。
  • OnTriggerExit(Collider other):当物体离开触发器区域时调用一次。

重要规则:

  • 只有当一个 Collider 附加了 Rigidbody,或者它是一个 Kinematic Rigidbody 上的 Collider 时,它才能接收到碰撞/触发器回调。
  • 注意: 如果是静态(不带 Rigidbody)的 Collider 之间发生碰撞,虽然物理系统会处理它们之间的交互,但不会调用任何回调函数。
using UnityEngine;public class CollisionDetector : MonoBehaviour
{// 当发生碰撞时void OnCollisionEnter(Collision collision){Debug.Log("OnCollisionEnter: " + gameObject.name + " 撞到了 " + collision.gameObject.name);// 可以在这里获取碰撞点、法线等信息foreach (ContactPoint contact in collision.contacts){Debug.Log("碰撞点: " + contact.point + ", 法线: " + contact.normal);}}// 当进入触发器区域时void OnTriggerEnter(Collider other){Debug.Log("OnTriggerEnter: " + gameObject.name + " 进入了触发器区域 " + other.gameObject.name);if (other.CompareTag("Collectible")) // 假设我们有一个Tag为"Collectible"的物体{Debug.Log("拾取了物品!");Destroy(other.gameObject); // 销毁被拾取的物品}}
}

5. 射线检测(Raycast)与形状检测:非碰撞交互

除了碰撞体之间的物理交互,Unity 也提供了用于检测特定方向或形状是否存在物体的 API,这在很多游戏逻辑中非常有用,例如射击游戏中的子弹检测、角色控制器中的地面检测等。

射线检测 (Raycast):

从一个点发射一条射线,检测是否击中物体。

  • Physics.Raycast(Vector3 origin, Vector3 direction, out RaycastHit hitInfo, float maxDistance)
    • origin: 射线的起点。
    • direction: 射线的方向。
    • hitInfo: 一个 RaycastHit 结构体,用于存储击中物体的信息(如击中点、法线、被击中的 Collider 和 GameObject 等)。
    • maxDistance: 射线的最大检测距离。
  • 还可以指定 LayerMask 来过滤检测的层级。
using UnityEngine;public class RaycastExample : MonoBehaviour
{public LayerMask hitLayer; // 设置一个层级,只检测这个层级的物体void Update(){// 从摄像机向鼠标点击位置发射射线if (Input.GetMouseButtonDown(0)){Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);RaycastHit hit;if (Physics.Raycast(ray, out hit, 100f, hitLayer)) // 检测最远100米,只检测hitLayer层的物体{Debug.Log("射线击中了: " + hit.collider.gameObject.name + " 在位置: " + hit.point);// 可以在这里对被击中的物体进行操作hit.collider.gameObject.GetComponent<Renderer>().material.color = Color.red;}else{Debug.Log("射线未击中任何物体。");}}}
}
形状检测 (Shape Cast):

除了射线,你还可以发射一个球体、胶囊体或盒子来检测是否与场景中的 Collider 发生重叠或碰撞。这比 Raycast 更适合检测更大范围的障碍物。

  • Physics.SphereCast(Vector3 origin, float radius, Vector3 direction, out RaycastHit hitInfo, float maxDistance, LayerMask layerMask):发射一个球体。
  • Physics.BoxCast(Vector3 center, Vector3 halfExtents, Vector3 direction, out RaycastHit hitInfo, Quaternion orientation, float maxDistance, LayerMask layerMask):发射一个盒子。
  • Physics.CapsuleCast(...):发射一个胶囊体。

这些方法与 Raycast 类似,只是将线替换成了对应的形状,用于更精确或范围更大的检测。


总结

至此,你已经掌握了 Unity 物理系统的核心基础:

  • Rigidbody 是物体参与物理模拟的必备组件。
  • Collider 定义了物体的碰撞形状。
  • Physic Material 决定了碰撞时的摩擦和弹跳特性。
  • 碰撞回调和触发器回调 让你能够响应物理事件并执行游戏逻辑。
  • 射线检测和形状检测 提供了在不发生物理交互的情况下查询物理世界的能力。

熟练运用这些基础功能,你就能在 Unity 中构建出丰富多样的物理交互和游戏玩法。在下一篇文章中我们将进入更深层次的探索,了解如何利用高级特性实现复杂交互,并关注性能优化,让你的物理模拟既强大又流畅

Unity物理系统由浅入深第一节:Unity 物理系统基础与应用
Unity物理系统由浅入深第二节:物理系统高级特性与优化
Unity物理系统由浅入深第三节:物理引擎底层原理剖析
Unity物理系统由浅入深第四节:物理约束求解与稳定性

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/diannao/90897.shtml
繁体地址,请注明出处:http://hk.pswp.cn/diannao/90897.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

《[系统底层攻坚] 张冬〈大话存储终极版〉精读计划启动——存储架构原理深度拆解之旅》-系统性学习笔记(适合小白与IT工作人员)

&#x1f525; 致所有存储技术探索者笔者近期将系统攻克存储领域经典巨作——张冬老师编著的《大话存储终极版》。这部近千页的存储系统圣经&#xff0c;以庖丁解牛的方式剖析了&#xff1a;存储硬件底层架构、分布式存储核心算法、超融合系统设计哲学等等。喜欢研究数据存储或…

flutter鸿蒙版 环境配置

flutter支持开发鸿蒙,但是需要专门的flutter鸿蒙项目, Flutter鸿蒙化环境配置&#xff08;windows&#xff09;_flutter config --ohos-sdk-CSDN博客

Java 高级特性实战:反射与动态代理在 spring 中的核心应用

在 Java 开发中&#xff0c;反射和动态代理常被视为 “高级特性”&#xff0c;它们看似抽象&#xff0c;却支撑着 Spring、MyBatis 等主流框架的核心功能。本文结合手写 spring 框架的实践&#xff0c;从 “原理” 到 “落地”&#xff0c;详解这两个特性如何解决实际问题&…

Codeforces Round 855 (Div. 3)

A. Is It a Cat? 去重&#xff0c; 把所有字符看成大写字符&#xff0c; 然后去重&#xff0c; 观察最后结果是不是“MEOW” #include <bits/stdc.h> #define int long longvoid solve() {int n;std::cin >> n;std::string ans, t;std::cin >> ans;for (int…

Scrapy选择器深度指南:CSS与XPath实战技巧

引言&#xff1a;选择器在爬虫中的核心地位在现代爬虫开发中&#xff0c;​​选择器​​是数据提取的灵魂工具。根据2023年网络爬虫开发者调查数据显示&#xff1a;​​92%​​ 的数据提取错误源于选择器编写不当熟练使用选择器的开发效率相比新手提升 ​​300%​​同时掌握CSS…

Windos服务器升级MySQL版本

Windos服务器升级MySQL版本 1.备份数据库 windows下必须以管理员身份运行命令行工具进行备份&#xff0c;如果没有配置MySQL的环境变量&#xff0c;需要进入MySQL Server 的bin目录输入指令&#xff0c; mysqldump -u root -p --all-databases > backup.sql再输入数据库密码…

告别频繁登录!Nuxt3 + TypeScript + Vue3实战:双Token无感刷新方案全解析

前言 在现代 Web 应用中&#xff0c;身份认证是保障系统安全的重要环节。传统的单 Token 认证方式存在诸多不足&#xff0c;如 Token 过期后需要用户重新登录&#xff0c;影响用户体验。本文将详细介绍如何在 Nuxt3 TypeScript Vue3 项目中实现无感刷新 Token 机制&#xff…

Linux——Redis

目录 一、Redis概念 1.1 Redis定义 1.2 Redis的特点 1.3 Redis的用途 1.4 Redis与其他数据库的对比 二、Redis数据库 三、Redis五个基本类型 3.1 字符串 3.2 列表(list) ——可以有相同的值 3.3 集合(set) ——值不能重复 3.4 哈希(hash) ——类似于Map集合 3.5 有序…

【AI大模型】部署优化量化:INT8压缩模型

INT8&#xff08;8位整数&#xff09;量化是AI大模型部署中最激进的压缩技术&#xff0c;通过将模型权重和激活值从FP32降至INT8&#xff08;-128&#xff5e;127整数&#xff09;&#xff0c;实现4倍内存压缩2-4倍推理加速&#xff0c;是边缘计算和高并发服务的核心优化手段。…

LFU 缓存

题目链接 LFU 缓存 题目描述 注意点 1 < capacity < 10^40 < key < 10^50 < value < 10^9对缓存中的键执行 get 或 put 操作&#xff0c;使用计数器的值将会递增当缓存达到其容量 capacity 时&#xff0c;则应该在插入新项之前&#xff0c;移除最不经常使…

检查输入有效性(指针是否为NULL)和检查字符串长度是否为0

检查输入有效性&#xff08;指针是否为NULL&#xff09;和检查字符串长度是否为0 这两个检查针对的是完全不同的边界情况&#xff0c;都是必要的防御性编程措施&#xff1a; 1. 空指针检查 if(!src) 目的&#xff1a;防止解引用空指针场景&#xff1a;当调用者传入 NULL 时风险…

Apache POI 的 HSSFWorkbook、SXSSFWorkbook和XSSFWorkbook三者的区别

HSSFWorkbook 专用于处理Excel 97-2003&#xff08;.xls&#xff09;格式的二进制文件。基于纯Java实现&#xff0c;所有数据存储在内存中&#xff0c;适合小规模数据&#xff08;通常不超过万行&#xff09;。内存占用较高&#xff0c;但功能完整&#xff0c;支持所有旧版Exce…

冷冻电镜重构的GPU加速破局:从Relion到CryoSPARC的并行重构算法

点击 “AladdinEdu&#xff0c;同学们用得起的【H卡】算力平台”&#xff0c;H卡级别算力&#xff0c;按量计费&#xff0c;灵活弹性&#xff0c;顶级配置&#xff0c;学生专属优惠。 一、冷冻电镜重构的算力困局 随着单粒子冷冻电镜&#xff08;cryo-EM&#xff09;分辨率突破…

算法学习笔记:16.哈希算法 ——从原理到实战,涵盖 LeetCode 与考研 408 例题

在计算机科学中&#xff0c;哈希算法&#xff08;Hash Algorithm&#xff09;是一种将任意长度的输入数据映射到固定长度输出的技术&#xff0c;其输出称为哈希值&#xff08;Hash Value&#xff09;或散列值。哈希算法凭借高效的查找、插入和删除性能&#xff0c;在数据存储、…

16018.UE4+Airsim仿真环境搭建超级详细

文章目录 1 源码下载2 下载安装软件2.1 安装 UE4 软件2.2 安装visual studio 20223 编译airsim源码4 进入AirSim工程,打开工程5 UE4 工程创建5.1 下载免费场景 CityPark,并创建工程5.2 工程编译5.2.1 将airsim 插件拷贝到 UE4工程路径中5.2.2 修改工程配置文件5.2.3 创建c++类…

Python 实战:构建 Git 自动化助手

在多项目协作、企业级工程管理或开源社区维护中&#xff0c;经常面临需要同时管理数十甚至上百个 Git 仓库的场景&#xff1a;多仓库需要统一 pull 拉取更新定期向多个项目批量 commit 和 push自动备份 Git 项目批量拉取私有仓库并管理密钥为解决这类高频、重复、机械性工作&am…

【PTA数据结构 | C语言版】出栈序列的合法性

本专栏持续输出数据结构题目集&#xff0c;欢迎订阅。 文章目录题目代码题目 给定一个最大容量为 m 的堆栈&#xff0c;将 n 个数字按 1, 2, 3, …, n 的顺序入栈&#xff0c;允许按任何顺序出栈&#xff0c;则哪些数字序列是不可能得到的&#xff1f;例如给定 m5、n7&#xf…

【LangGraph】create_react_agent 方法详细解释

create_react_agent 方法详细解释 create_react_agent 方法是一个在 LangGraph 中创建 React 代理的核心函数,接下来我们将一起探讨这个函数的作用、参数、返回值以及工作原理。 @_convert_modifier_to_prompt def create_react_agent(model: Union[str, LanguageModelLike]…

【时间之外】尘封的智能套件复活记

目录 尘封的奖品 初次触网的挫败 客服只会诱导消费 意外发现的生机 真相与反思 尘封的奖品 五年前那个蝉鸣阵阵的夏日&#xff0c;我抱着创新比赛特等奖的奖品礼盒走下领奖台时&#xff0c;绝对想不到这份荣誉会衍生出如此曲折的故事。礼盒里静静躺着的智能家居套装&…

从零开始学前端html篇1

1基本结构<!DOCTYPE html> <html><head><title>this is a good website</title></head><body><h1>hello!</h1></body> </html>运行效果如下&#xff08;编辑器提示waings:"缺少所需的 lang 特性"…