Unity物理系統由淺入深第三節:物理引擎底層原理剖析

Unity物理系統由淺入深第一節:Unity 物理系統基礎與應用
Unity物理系統由淺入深第二節:物理系統高級特性與優化
Unity物理系統由淺入深第三節:物理引擎底層原理剖析
Unity物理系統由淺入深第四節:物理約束求解與穩定性

Unity 物理系統底層使用的是 NVIDIA PhysX 引擎。理解 PhysX 或任何其他實時物理引擎(如 Havok, Bullet)的工作方式,對于一名進階的 Unity 開發者來說,是極其寶貴的知識。本篇我們將從宏觀到微觀,逐步了解物理引擎的核心概念和主要算法。


1. 物理引擎概述:一個模擬真實世界的機器

物理引擎本質上是一個復雜的軟件系統,它接收場景中所有具有物理屬性(剛體、碰撞體等)的物體信息,然后在一個固定時間步(Fixed Timestep)內,迭代計算這些物體在各種力(重力、推力、摩擦力等)和約束(碰撞、關節)作用下的位置、速度和旋轉,從而模擬出真實的物理行為。

一個典型的物理引擎循環(在每個 FixedUpdate 中執行)大致遵循以下步驟:

  1. 積分器 (Integrators): 根據當前的速度和受到的力,預測物體在下一個時間步的位置和速度。
  2. 寬相碰撞檢測 (Broad-Phase Collision Detection): 快速找出場景中所有可能發生碰撞的物體對。
  3. 窄相碰撞檢測 (Narrow-Phase Collision Detection): 對上一步篩選出的可能碰撞對,進行精確的碰撞檢測,計算出詳細的碰撞信息(接觸點、法線、穿透深度等)。
  4. 接觸生成 (Contact Generation): 根據窄相檢測的結果,生成接觸點(Contact Points)和接觸法線(Contact Normals)。
  5. 約束求解器 (Constraint Solver): 處理所有碰撞(以及關節)產生的約束。這是物理引擎最復雜的部分,它通過迭代計算來解決物體之間的相互作用,確保它們不會相互穿透,并且能正確反彈、滑動或連接。
  6. 更新狀態: 根據求解器的結果,更新所有剛體的位置和速度。

2. 剛體動力學基礎:物理引擎的語言

在深入算法之前,我們需要回顧一下物理學中的一些基本概念,它們是物理引擎的“語言”。

  • 力 (Force):改變物體運動狀態的原因。單位牛頓 (N)。
  • 質量 (Mass):物體慣性的量度。單位千克 (kg)。
  • 慣性 (Inertia):物體保持其運動狀態的特性。質量越大,慣性越大。
  • 慣性張量 (Inertia Tensor):描述剛體旋轉慣性的一個 3x3 矩陣。它表示了物體在不同軸上抵抗旋轉的能力。對于非球對稱的物體,其旋轉慣性在不同方向上是不同的。在 Unity 中,對于常見的原始碰撞體,PhysX 會自動計算好。對于 Mesh Collider,可能需要外部工具或手動計算。
  • 線速度 (Linear Velocity):物體直線運動的速度向量。
  • 角速度 (Angular Velocity):物體旋轉的速度向量。
  • 動量 (Momentum):物體的質量與其線速度的乘積。
    • P=mvP = mvP=mv
  • 角動量 (Angular Momentum):描述物體旋轉運動的量。
    • L=IωL = I\omegaL=Iω (其中 III 是慣性張量,ω\omegaω 是角速度)
  • 沖量 (Impulse):在短時間內施加的巨大力。它直接導致動量的瞬間變化。
    • ΔP=FΔt\Delta P = F \Delta tΔP=FΔt (力乘以時間,或直接視為動量變化量)
  • 扭矩 (Torque):使物體產生旋轉的力矩。它直接導致角動量的瞬間變化。
    • τ=r×F\tau = r \times Fτ=r×F (力臂與力的叉乘)

物理引擎通過這些概念來計算和更新物體的運動狀態。例如,當施加一個力時,引擎會根據牛頓第二定律 F=maF = maF=ma 來計算加速度,然后用積分器更新速度和位置。當發生碰撞時,引擎會計算一個沖量,施加到碰撞的物體上,使其反彈或滑動。


3. 積分器(Integrators):連接現在與未來

積分器是物理引擎的“時間旅行者”,它們負責根據當前的速度和力,預測物體在下一個微小時間步長后的位置和速度。這是物理模擬的核心,因為我們需要連續地更新物體的狀態。

  • 歐拉積分 (Euler Integration)

    • 原理: 最簡單也是最直觀的積分方法。它假設在整個時間步長內,速度或力是恒定的,并直接通過當前的速度和加速度來更新位置和速度。
    • 公式:
      • vnew=vcurrent+a?Δtv_{new} = v_{current} + a \cdot \Delta tvnew?=vcurrent?+a?Δt
      • xnew=xcurrent+vcurrent?Δtx_{new} = x_{current} + v_{current} \cdot \Delta txnew?=xcurrent?+vcurrent??Δt
    • 優點: 實現簡單,計算速度快。
    • 缺點: 精度最低,容易產生累積誤差,導致能量損失或增加(物體可能會越彈越低或越彈越高),特別是在較大的時間步長下,可能導致數值不穩定。
    • 示例: 在簡單場景中可以接受,但在需要高精度模擬(如車輛、關節鏈)時則不夠理想。
  • Verlet 積分 (Verlet Integration)

    • 原理: 一種更穩定且能更好地保持能量的積分方法。它不直接使用速度,而是利用當前位置和上一幀位置來計算新位置。速度是隱式包含的。
    • 公式(簡化版):
      • xnew=2xcurrent?xprevious+a?Δt2x_{new} = 2x_{current} - x_{previous} + a \cdot \Delta t^2xnew?=2xcurrent??xprevious?+a?Δt2
    • 優點: 能量守恒性好,數值穩定性強,即使在較大時間步長下也不太容易發散。
    • 缺點: 無法直接訪問速度,如果需要速度信息(例如用于碰撞響應),需要額外計算。
    • 示例: 常用于粒子系統、布料模擬等對穩定性要求高的場景。
  • 龍格-庫塔積分 (Runge-Kutta Integration - RK4)

    • 原理: 一系列更高階的積分方法,通過在時間步長內采樣多個點來計算加權平均值,從而提高精度。RK4 是最常用的一種。
    • 優點: 精度高,穩定性好,能夠更準確地模擬復雜的物理系統。
    • 缺點: 計算量遠大于歐拉積分,因為需要在每個時間步內進行多次求值。
    • 示例: 理論上最接近真實物理的積分方法,但在實時游戲中因性能開銷大而較少直接用于大量剛體,更常見于需要高精度模擬的特定場景或離線物理模擬。

Unity PhysX 采用的積分器: 盡管 PhysX 的具體實現是專有的,但它通常使用經過優化的隱式歐拉積分(Implicit Euler)或類似的半隱式積分。這種方法結合了歐拉的簡潔和一些穩定性優勢,通過在迭代求解器中同時考慮當前和下一幀的狀態來提高穩定性。它并不是單純的顯式歐拉積分。


4. 碰撞檢測(Collision Detection):尋找接觸點

碰撞檢測是物理引擎最核心、最耗性能的部分之一。它分為兩個階段:寬相檢測和窄相檢測。

4.1. 寬相檢測(Broad-Phase Collision Detection)
  • 目的: 快速排除場景中絕大多數不可能發生碰撞的物體對。這一步不需要精確的計算,只需要找出“可能”碰撞的候選對。
  • 核心思想: 使用粗略的包圍體(Bounding Volume),如 AABB (Axis-Aligned Bounding Box),來近似表示物體的空間范圍。如果兩個 AABB 不重疊,那么它們內部的物體肯定不碰撞。
  • 常用算法:
    • AABB 樹 (AABB Tree):一種層次化的數據結構。將場景中的所有 AABB 組織成一棵樹。檢測時,只需遍歷樹,如果父節點的 AABB 不重疊,則其子節點也不可能重疊,從而快速排除大量物體。這是 PhysX 廣泛使用的技術。
    • SAP (Sweep and Prune / Sort and Sweep):對所有物體在每個軸上的 AABB 投影進行排序。只有當兩個物體的 AABB 在所有軸上都重疊時,才可能發生碰撞。通過維護排序列表,可以高效地找出重疊對。適用于物體數量不太多且運動方向較固定的場景。
    • 網格/格子(Grids/Spatial Hashing):將空間劃分為規則的網格單元。每個單元存儲其中包含的物體。檢測時只檢查相鄰或同一單元格內的物體。適用于物體均勻分布的場景。
4.2. 窄相檢測(Narrow-Phase Collision Detection)
  • 目的: 對寬相檢測篩選出的“可能”碰撞對,進行精確的幾何測試,判斷它們是否真的發生了碰撞,并計算出詳細的碰撞信息(接觸點、法線、穿透深度等)。
  • 核心思想: 使用更精確的幾何算法來處理復雜形狀。
  • 常用算法:
    • GJK (Gilbert-Johnson-Keerthi Distance Algorithm)
      • 原理: GJK 算法并不是直接找到碰撞點,而是用來判斷兩個凸包(Convex Hull)是否相交。它通過迭代尋找兩個物體之間的最短距離向量。如果這個最短距離為零或指向內,則表示它們相交。
      • 優點: 效率高,適用于任意凸包形狀,是現代物理引擎的核心。
      • 缺點: 只能判斷是否相交,不能直接得到碰撞點和法線。
    • EPA (Expanding Polytope Algorithm)
      • 原理: EPA 通常緊接著 GJK 之后使用。當 GJK 判斷兩個物體相交后,EPA 會從 GJK 找到的“穿透方向”開始,在閔可夫斯基差集(Minkowski Difference)中擴展一個多面體,直到找到最接近原點的那個面。這個面就定義了最小穿透向量(法線和深度)。
      • 優點: 與 GJK 結合,可以準確地計算穿透深度和碰撞法線。
    • SAT (Separating Axis Theorem - 分離軸定理)
      • 原理: 對于兩個凸體,如果它們不相交,那么一定存在一個軸,使得它們在這條軸上的投影互不重疊。反之,如果找不到這樣的分離軸,則它們相交。對于多邊形,需要測試所有邊以及垂直于這些邊的軸。
      • 優點: 簡單易懂,對于多邊形(2D)和多面體(3D)非常有效。
      • 缺點: 對于復雜形狀,需要測試的軸可能很多,效率不如 GJK/EPA 組合。
4.3. 接觸生成 (Contact Generation)
  • 一旦窄相檢測確定了碰撞,下一步就是生成一個或多個接觸點 (Contact Point)。每個接觸點包含了:
    • 位置 (Position):碰撞發生在世界空間中的坐標。
    • 法線 (Normal):指向從一個物體到另一個物體的方向。這決定了碰撞后的反彈方向。
    • 深度 (Separation/Penetration Depth):物體之間相互穿透的距離。這個信息對于約束求解器至關重要,因為它需要將物體推開。
  • 對于復雜的碰撞,可能會生成多個接觸點(例如,一個盒子平躺在地面上)。這些接觸點會被收集起來,傳遞給下一步的約束求解器。

總結

至此,我們已經基本了解了 Unity 物理引擎的底層工作原理:從宏觀的物理循環,到驅動物體運動的剛體動力學基礎,再到連接過去與未來的積分器,以及尋找和確定碰撞點的寬相和窄相碰撞檢測算法。

我們現在應該對物理引擎如何“看”到和“理解”我們的游戲世界有了更清晰的認識。下一篇,我們將繼續深入物理引擎最復雜也是最精妙的部分:物理約束求解與穩定性,了解它是如何解決碰撞穿透、摩擦和關節限制等問題的。

Unity物理系統由淺入深第一節:Unity 物理系統基礎與應用
Unity物理系統由淺入深第二節:物理系統高級特性與優化
Unity物理系統由淺入深第三節:物理引擎底層原理剖析
Unity物理系統由淺入深第四節:物理約束求解與穩定性

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/88897.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/88897.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/88897.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Docker一鍵安裝中間件(RocketMq、Nginx、MySql、Minio、Jenkins、Redis)腳步

1、Docker安裝RocketMq 2、Docker安裝Nginx 3、Docker安裝MySql 4、Docker安裝Minio 5、Docker安裝jenkins 6、Docker安裝Redis 1、Docker安裝RocketMq #!/bin/bash# 定義變量 NAMESRV_CONTAINER"rocketmq-namesrv" BROKER_CONTAINER"rocketmq-broker&quo…

WPF學習筆記(27)科學計算器

科學計算器1. 前端界面2. 功能代碼3. 效果展示1. 前端界面 <Window x:Class"Cal.MainWindow"xmlns"http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x"http://schemas.microsoft.com/winfx/2006/xaml"xmlns:d"http:/…

【Linux系列】unzip file 命令

博客目錄掌握 unzip -o 命令&#xff1a;高效解壓并覆蓋文件的完整指南一、unzip 命令基礎二、-o 選項的核心作用三、典型應用場景四、與其他選項的組合使用五、注意事項與風險防范六、替代方案與高級技巧掌握 unzip -o 命令&#xff1a;高效解壓并覆蓋文件的完整指南 在日常的…

1965–2022年中國大陸高分辨率分部門用水數據集,包含:灌溉用水、工業制造用水、生活用水和火電冷卻

1965–2022年中國大陸高分辨率部門用水數據集 高質量用水數據集對推進變化環境下的水資源研究至關重要。然而&#xff0c;現有中國用水數據通常按行政區劃或流域匯總&#xff0c;時空分辨率不足&#xff0c;難以支撐人類用水模式及時空變化特征的精細化分析。為此&#xff0c;…

git中的指令解釋

在 Git 的 diff 輸出中&#xff0c;---、 和 ... 塊的含義如下&#xff1a; 1. --- a/1.py 和 b/1.py --- a/1.py&#xff1a;表示舊版本的文件路徑&#xff08;通常是工作目錄或上一次提交的版本&#xff09;。 b/1.py&#xff1a;表示新版本的文件路徑&#xff08;通常是暫存…

STM32實現四自由度機械臂(SG90舵機)多功能控制(軟件篇freertos)

書接上回的硬件篇STM32控制四自由度機械臂&#xff08;SG90舵機&#xff09;&#xff08;硬件篇&#xff09;&#xff08;簡單易復刻&#xff09;-CSDN博客 此時硬件平臺已經搭建完畢&#xff0c;軟件總共設計了三種模式&#xff0c;分別為 模式1&#xff1a;搖桿&藍牙模…

docker常用命令集(2)

接前一篇文章&#xff1a;docker常用命令集&#xff08;1&#xff09; 本文內容參考&#xff1a; Docker build 命令 | 菜鳥教程 docker基礎(二)之docker build-CSDN博客 Docker push 命令 | 菜鳥教程 Docker pull 命令 | 菜鳥教程 特此致謝&#xff01; 3. docker build …

舒爾特方格訓練小游戲流量主微信小程序開源

功能特點 游戲核心功能&#xff1a; 隨機生成55舒爾特方格 按順序點擊數字1-25 實時計時和嘗試次數統計 錯誤點擊反饋&#xff08;視覺和觸覺&#xff09; 數據統計&#xff1a; 記錄每次完成時間 保存歷史最佳成績 保存最近5次嘗試記錄 統計嘗試次數&#xff08;錯誤點擊&…

在Spring Boot 開發中 Bean 的聲明和依賴注入最佳的組合方式是什么?

在Spring Boot 開發中&#xff0c;社區和 Spring 官方已經形成了一套非常明確的最佳實踐。這個黃金組合就是&#xff1a; Bean 聲明&#xff1a;使用構造型注解&#xff08;Stereotype Annotations&#xff09;&#xff0c;如 Service, Repository, Component 等。依賴注入&…

Oxygen XML Editor 26.0編輯器

Oxygen XML Editor 26.0編輯器 歡迎使用Oxygen XML Editor 26.0編輯器準備工作安裝javajdk安裝jdk驗證Oxygen XML Editor 26.0安裝歡迎使用Oxygen XML Editor 26.0編輯器 準備工作安裝java Java官網下載地址:https://www.oracle.com/java/technologies/ Oxygen XML Editor 2…

AWS Lambda Container 方式部署 Flask 應用并通過 API Gateway 提供訪問

前言 一年前寫過一篇 Lambda 運行 Flask 應用的博文: https://lpwmm.blog.csdn.net/article/details/139756140 當時使用的是 ZIP 包方式部署應用代碼, 對于簡單的 API 開發用起來還是可以的, 但是如果需要集成到 CI/CD pipeline 里面就有點不太優雅. 本文將介紹使用容器方式…

React虛擬DOM的進化之路

引言 在Web前端開發中&#xff0c;用戶交互的流暢性和頁面性能一直是核心挑戰。早期&#xff0c;開發者直接操作真實DOM&#xff08;Document Object Model&#xff09;時&#xff0c;頻繁的重排&#xff08;reflow&#xff09;和重繪&#xff08;repaint&#xff09;導致性能…

(7)機器學習小白入門 YOLOv:機器學習模型訓練詳解

— (1)機器學習小白入門YOLOv &#xff1a;從概念到實踐 (2)機器學習小白入門 YOLOv&#xff1a;從模塊優化到工程部署 (3)機器學習小白入門 YOLOv&#xff1a; 解鎖圖片分類新技能 (4)機器學習小白入門YOLOv &#xff1a;圖片標注實操手冊 (5)機器學習小白入門 YOLOv&#xff…

初識MySQL(三)之主從配置與讀寫分離實戰

主重復制 主重復制原理master開啟二進制日志記錄slave開啟IO進程&#xff0c;從master中讀取二進制日志并寫入slave的中繼日志slave開啟SQL進程&#xff0c;從中繼日志中讀取二進制日志并進行重放最終&#xff0c;達到slave與master中數據一致的狀態&#xff0c;我們稱作為主從…

RabbitMQ面試精講 Day 2:RabbitMQ工作模型與消息流轉

【RabbitMQ面試精講 Day 2】RabbitMQ工作模型與消息流轉 開篇 歡迎來到"RabbitMQ面試精講"系列的第2天&#xff0c;今天我們將深入探討RabbitMQ的工作模型與消息流轉機制。這是面試中最常被問到的核心知識點之一&#xff0c;90%的RabbitMQ面試都會涉及消息流轉流程…

基于SpringBoot3集成Kafka集群

1. build.gradle依賴引入 implementation org.springframework.kafka:spring-kafka:3.2.02. 新增kafka-log.yml文件 在resource/config下面新增kafka-log.yml&#xff0c;配置主題與消費者組 # Kafka消費者群組 kafka:consumer:group:log-data: log-data-grouptopic:log-data: …

wpf Canvas 導出圖片

在WPF中將Canvas導出為圖片主要涉及以下關鍵步驟和注意事項: ?核心實現方法?使用RenderTargetBitmap將Canvas渲染為位圖,再通過PngBitmapEncoder保存為PNG文件。需注意臨時移除Canvas的布局變換(LayoutTransform)以避免渲染異常?1。示例代碼片段:CanvasExporter.cs pu…

lvs負載均衡實操模擬

目錄 一、配置準備 二、NET模式 修改LVS端 開啟路由 修改對內網卡 ens160 修改對外網卡 ens224 加載網卡配置文件 修改web1端 修改網卡信息 重啟網絡 檢測 配置web2 檢測 驗證配置是否正常 啟動nginx服務 驗證以上配置 添加lvs規則 驗證 三、DR模式 修改…

Spring Boot 是如何簡化 IoC 的配置的?

首先Spring Boot 并沒有發明新的 IoC 理論&#xff0c;它做的也不是替換掉 Spring IoC 容器。相反&#xff0c;Spring Boot 是 Spring IoC 思想的實踐者和簡化者。它通過**“約定優于配置”&#xff08;Convention over Configuration&#xff09;**的理念&#xff0c;將原本繁…

Go語言中的組合式接口設計模式

文章目錄Go語言中的組合式接口設計模式背景和需求組合式接口設計Go語言中的組合式接口設計模式 背景和需求 在微服務架構和復雜業務系統中&#xff0c;我們經常需要調用多個外部服務或內部模塊。傳統的做法是將所有方法都放在一個大接口中&#xff0c;但這種設計會導致接口臃…