• <nav id="yisao"><rt id="yisao"></rt></nav>
  • Cocos Creator 3D 物理模塊介紹

    2019.10.17 cocos 技術干貨 by Cocos

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

    設計思路

    簡單易用?

    為了讓游戲開發更加簡單、友好和高效,Cocos Creator 3D 在研習和摸索中設計了一套比較基礎的物理組件,并且還在持續完善中。盡管當前的組件功能還十分有限,但是相信在有了之前的組件設計經驗后,很快就可以有更多強大且易用的物理組件。
    另外,我們還對物理模塊設計了一套抽象層,這是物理組件能夠發揮其功能的底層支持,也是我們為多物理后端打下的基礎。

    多物理后端


    用于接入不同的物理引擎,目標是能夠在開發時,切換到不同的物理引擎后端中,滿足對于不同游戲所需要的不同物理功能。
    多物理后端的設計,可以使游戲包體更靈活,但主要的考慮是不同游戲要求的物理功能是不同的,例如:

    • 有些游戲只需要檢測系統
    • 有些游戲需要支持基本功能并且包體小的物理
    • 有些游戲需要功能齊全的物理

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

    目前的狀況及后續發展

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

    使用示例

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

    吞噬與吸引效果

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

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

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

    藍色圈      

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

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

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

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

    車輛模擬的效果

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

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

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

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

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

    車身和車輪:車輛運動應該是很平穩的,可以把摩擦力系數都設置為 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 ,如下圖:

    然后,為需要進行檢測的節點,加上碰撞體并調整大小,最后根據注冊的觸發事件來做出相應的行為。

        // 觸發事件分三種類型,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 對象,查看他的屬性列表,如下圖:

    通過對象的層級就可以找到底層對象的實體(上圖中紅色框標注的),即? 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 版塊與我們進行交流!

    女人脱裤子让男生桶爽免费看,久青草无码视频在线播放,精品国产人成亚洲区,久久精品国产亚洲一区二区