Cocos Creator 3D 物理模塊介紹

爲提升閱讀體驗,[參考鏈接]統一放在文末!

設計思路

簡單易用

爲了讓遊戲開發更加簡單、友好和高效,Cocos Creator 3D 在研習和摸索中設計了一套比較基礎的物理組件,並且還在持續完善中。儘管當前的組件功能還十分有限,但是相信在有了之前的組件設計經驗後,很快就可以有更多強大且易用的物理組件。

另外,我們還對物理模塊設計了一套抽象層,這是物理組件能夠發揮其功能的底層支持,也是我們爲多物理後端打下的基礎。

多物理後端

用於接入不同的物理引擎,目標是能夠在開發時,切換到不同的物理引擎後端中,滿足對於不同遊戲所需要的不同物理功能。

多物理後端的設計,可以使遊戲包體更靈活,但主要的考慮是不同遊戲要求的物理功能是不同的,例如:
  • 有些遊戲只需要檢測系統
  • 有些遊戲需要支持基本功能並且包體小的物理
  • 有些遊戲需要功能齊全的物理

對於不同的物理引擎後端,抽象層也將致力於提供簡單統一的 API 使用,並且將盡力保障相同的參數在每個後端的實際表現達到統一一致。當然,這裏針對的是所有後端都支持的功能。我們爲多物理後端打下的基礎。

目前的狀況及後續發展

目前 Cocos Creator 3D 的物理模塊已經支持僅碰撞檢測的 builtin 和輕量功能的 cannon.js 物理引擎。未來,我們將持續完善已接入 cannon.js 的更多功能特性,並且還將接入功能更加強大齊全的 ammo.js。

使用示例

在介紹使用方法之前,爲了更好地展示目前的物理功能,以便更好地結合具體使用與具體情境,我將通過一些示例來進行講解,文末參考鏈接[Demo]可以獲取完整示例。

吞噬與吸引效果

640?wx_fmt=gif


上方的動圖中,藍色圈可以看作是一個洞,並具有吸引物體的能力,一個完整的洞效果可以分爲物理和渲染兩個方面的內容,這裏主要介紹的是物理方面。

首先,看一下它們的物理結構:

方塊(球類似,區別爲碰撞器是球形狀的,地面是隻有碰撞器的結構)   

640?wx_fmt=png

藍色圈      

640?wx_fmt=png

通過上面的節點樹層級關係,可以知道 Hole 節點負責的是物理的功能,而它的子節點負責的是渲染的功能。當然,這裏的層級關係也可以改變,例如,把渲染元素所需要的組件掛載到 Hole 節點上。

在 Hole 節點上,主要體現物理元素的是它掛載的兩個球碰撞器組件,並且都是觸發器的類型。這裏可以分別看作內外圈,它們負責的功能分別爲“洞”和“吸引”。

“吸引”的實現:監聽外圈的觸發器進入的事件,當物體進入時,對其施加向洞中心方向的力,這樣就可以實現洞的吸引效果。

“洞”的實現:同樣監聽內圈的觸發器進入事件,當物體進入時,修改物體碰撞器的掩碼,使得物體不會與地面產生碰撞,物體的剛體由於受到重力和吸引力的影響,就會掉落下去,這也可以看做“吞噬”的效果。

車輛模擬的效果

640?wx_fmt=gif


物理模擬是爲了表現真實世界,所以使用物理的最佳實踐,就是把實物結構用基礎的元素表達出來,再調整每個基礎元素的屬性,這樣一般都可以模擬出期望的效果。

但物理模擬始終是模擬,在遊戲中這類需要實時交互的場景裏,需要將表現力和實時交互能力平衡。如果需要更佳的實時性能,那麼可以嘗試對物理結構簡化。

需要注意的是,本文介紹的車輛模擬,是基於現有的物理功能製作的,並不是嚴格的真實車輛模擬,只是一種取巧的方式,而實現此車輛模擬的主要內容是車輛的結構:    

640?wx_fmt=png

上圖結構也是通過真實車的結構簡化而來的,設計好結構後,還需要調整每個部分的屬性:

重心: 車的重心應該要低一些,否則可能會很容易翻車;

車身和車輪:車輛運動應該是很平穩的,可以把摩擦力系數都設置爲 0,另外車輪要比車身低一些,這樣在碰到障礙物後車輛會有晃動的效果,用來模擬避震;

擋板:因爲車身摩檫力設置爲 0 了,爲了防止車滑起來,加一個摩檫力不爲 0 的擋板;

剛體:默認質量爲 10,這裏可以改成 200;因爲摩檫力都爲 0,避免車一直滑動,將阻力(damping)設置爲 0.9;角速度因子 x 軸向設置成 0.5,減低車在 x 軸向的旋轉抖動。


使用簡介

根據所需物理功能,選擇不同物理

在開發前,可以先想好大致需要什麼樣的物理功能,根據不同的功能,選擇不同的物理,以下條件可供參考:
  • 只需要規則的運動模擬,例如轉動風扇、簡單的跳躍,可以通過造型方程進行模擬,例如通過圓的方程進行圓周運動。
  • 只需要碰撞檢測,可以考慮使用 builtin + collider 組件或者使用 gemotry 模塊中的 intersect 相交性檢測 API。
  • 需要物理模擬,目前可以考慮使用 cannon + 物理相關組件,或者通過直接獲取引擎底層的物理進行開發。
  • 更加複雜的物理,如複雜約束、車量模擬、布娃娃模擬等,目前組件還未提供,但可以考慮在自己項目中嵌入第三方物理。

在使用物理之前,建議先閱讀[物理文檔]、物理[測試例]和簡單的[Demo],在這些參考文檔中,你可以瞭解到一些簡單 API 的功能和使用方式,建議文檔和測試例同時查看,會更助於理解物理模塊。

選擇好相應的物理後,接下來通過以下情況做一個簡單演示。

規則的運動模擬

在 Cocos Creator 3D 中,可以通過節點 Transform 數據(即 position、rotation、scale 等屬性)對節點進行變換,這也同樣會驅動其節點鏈上的模型、粒子、剛體等組件的矩陣信息,以下腳本將通過修改節點的 Transform 信息進行橢圓方程的運動:
    // 這裏演示節點以橢圓方程進行運動	
    // 注:橢圓的參數方程 x = a*cosθ, y = b*sinθ。	
    const _v3_0 = new Vec3();	
    update (deltaTime: number) {	
        const now = performance.now() / 1000;	
        _v3_0.x = this.a * Math.cos(now);	
        _v3_0.z = this.b * Math.sin(now);	
        this.node.setPosition(_v3_0);	
    }

builtin 物理檢測

builtin 碰撞檢測,底層實際調用的就是[intersect]提供的接口。首先選擇物理模塊爲 builtin ,如下圖:

640?wx_fmt=jpeg

然後,爲需要進行檢測的節點,加上碰撞體並調整大小,最後根據註冊的觸發事件來做出相應的行爲。
    // 觸發事件分三種類型,Enter\Stay\Exit,需要通過 ColliderComponent 組件註冊	
    start () {	
        const collider = this.getComponent(ColliderComponent);	
        collider.on('onTriggerEnter', this.onTriggerEnter, this);	
        collider.on('onTriggerStay', this.onTriggerStay, this);	
        collider.on('onTriggerExit', this.onTriggerExit, this);	
    }	
    onTriggerEnter (event: ITriggerEvent) { /* TODO */ }	
    onTriggerStay (event: ITriggerEvent) { }	
    onTriggerExit (event: ITriggerEvent) { }
    
cannon.js 物理模擬

選擇物理模塊爲 cannon.js,爲需要模擬的節點加上 RigidBodyComponent 組件,這樣該節點就會進行物理模擬。再加上相應的 ColliderComponent,該節點的剛體就會增加相應的碰撞體,這會用於檢測是否與其它碰撞體產生碰撞。

剛接觸物理模擬,遇到最大的問題,大概是不知道如何控制剛體,建議各位開發者先熟悉剛體的每個參數所代表的物理意義,在[官方文檔]中有詳細介紹。

這裏將根據一些簡單例子來介紹一些可採用的做法:

模擬跳躍行爲:由於運動是可以分解的,所以跳躍和移動等可以看作是一類問題,只要讓相應的軸向擁有速度,剛體就會運動起來了。

在 cannon.js 物理中改變速度有多種方式,比如可以通過  setLinearVelocity 直接設置線性速度,以及通過 setAngularVelocity 直接設置角速度,這種方式將會使得物體由最大的速度開始往上。但由於受重力影響,物體 Y 軸向的速度將時間變化減小至 0;

也可以通過施加力或者衝量的方式, applyForce 或 applyImpluse,這種方式是根據公式定律計算得出的速度,以 applyForce 舉例:
  • F=M·a 
    F 是剛體的受力,M 是質量,a 是加速度
  • v=a·t 
    v 是瞬時速度,a 是加速度,t 是時間

這種方式需要理解一些參數去實現效果,如施加力時需要考慮剛體的質量,以及對剛體施加的時間(在這裏可以說是施加次數或幀數)。

限制剛體在 Y 軸旋轉:這類問題可以看作是對剛體的約束,目前在剛體組件裏面提供了對線性速度和角速度的縮放屬性,即 linearFactor 與 angularFactor (可以看作是與剛體速度執行分量積),將 angularFactor 的 y 分量設置成 0 ,就可以達到這個效果。理解這些屬性,並靈活的使用它們,可以實現非常多的效果。

目前的 cannon.js 支持情況:
  • 剛體
  • box\sphere 形狀
  • 支持觸發、碰撞事件,分別爲:enter\stay\exit
  • 物理材質
  • 射線檢測
 
更多功能
組件層服務的是所有的開發者,穩定性、通用性是首要的目標,Cocos 將在這個基礎上持續不斷的加入更多的功能。

對於一些暫不清晰的功能需求,我們將會提供實驗性的組件,例如 mesh collider(沒有發佈正式組件的主要原因是目前的底層支持不夠)

訪問底層接口

對於某些暫未提供組件化服務的功能,各位開發者可以考慮在現有的框架之下直接使用底層的物理接口(例如現有的 cannon.js)。以下步驟將會介紹如何在項目工程中直接訪問到底層的物理接口:

1. 校驗,在預覽頁面的控制檯中輸入 CANNON,判斷其是否存在,若存在,則不用執行下列子步驟;

(1)將 CANNON 暴露到 Window 中,這裏需要改動引擎代碼:首先點擊編輯器右上角的安裝目錄按鈕,在相對路徑 \resources\3d\engine\cocos\physics\cannon\cannon-world.ts 下,打開該文件;在合適位置加上此行代碼 window.CANNON = CANNON;然後點擊編輯器的開發者選項欄的編譯引擎的選項(快捷鍵 Ctrl +F7),最後刷新編輯器(快捷鍵 Ctrl+R)

(2)重複步驟 1 ,確保 CANNON 可以被訪問到。

2. 將 CANNON 的類型聲明文件複製到項目工程當中 (下載[聲明文件],後綴爲 .d.ts  的文件)

3. 在腳本中用命名空間的方式訪問 CANNON 提供的接口(注意不要使用模塊的方式,即 import CANNON from 'cannon')

通過以上步驟就可以在項目工程中直接獲取底層的接口進行開發了,需要注意的是,模塊需要設置成相應的物理底層。

注:暴露其他的模塊是類似的方式。

結合現有框架

目前的框架還沒有暴露底層的對象,如果要和現有框架結合起來,哪麼需要通過 hack 的方式去訪問。這裏以獲取物理系統中的底層世界對象爲例子:

首先可以通過控制檯打印出 PhysicsSystem.instance 對象,查看他的屬性列表,如下圖:

640?wx_fmt=jpeg

通過對象的層級就可以找到底層對象的實體(上圖中紅色框標註的),即  cc.PhysicsSystem.instance._world._world。

這種方式雖然可以達到目的,但仍需要注意以下幾點:
  • 只是提供一種方案,這種方式是不推薦的,更希望大家一起參與討論和設計;
  • 爲滿足上層框架,底層物理可能存在一些 API 改動;
  • 未來結構可能會變化,對於這種方式需要自己去維護。

參考文檔
[物理文檔]
https://docs.cocos.com/creator3d/manual/zh/physics/physics.html
[測試例]
https://github.com/cocos-creator/test-cases-3d
[Demo]
https://github.com/cocos-creator/example-3d
[intersect]
https://github.com/cocos-creator/engine/blob/3d-v1.0.0/cocos/core/geom-utils/intersect.ts
[聲明文件]
https://github.com/cocos-creator/cannon.js/blob/cocos-master


以上就是今天 jiaxin 帶來的物理模塊介紹,有什麼疑惑和見解,您可以點擊【閱讀原文】前往 Cocos 中文社區 Creator 3D 版塊與我們進行交流!

640?wx_fmt=png

640?wx_fmt=jpeg

640?wx_fmt=png

我就知道你“在看”640?wx_fmt=png

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章