物理引擎的碰撞分組,適用2D和3D

2021-10-14 04:01:53 字數 4146 閱讀 1593

我們在運用物理碰撞的業務邏輯時,尤其是複雜的碰撞需求時,就需要設定碰撞組,以及指定碰撞組可以與哪些碰撞組進行碰撞。而這些,需要用到位運算的知識,有一些開發者對此不太理解。為了降低開發者上手的門檻,今天就來講一講,如何通過位運算來理解碰撞組的碰撞關係。

設定碰撞組

2d物理的碰撞組是設定剛體的category(碰撞類別)屬性。

3d物理的碰撞組是設定碰撞器的collisiongroup(所屬碰撞組)屬性。

無論是2d還是3d,設定碰撞組的共同規則就是採用2的n次冪作為碰撞分組的值。

所以,設定碰撞組,比較容易理解,只要是2的n次冪值,都可以用於設定碰撞組,成為區分不同碰撞組的id。

指定可碰撞的組

2d物理通過設定剛體的mask(掩碼)屬性來指定可與哪些組進行碰撞。

3d物理通過設定碰撞器的cancollidewith(能碰撞的組)屬性來指定可與哪些組進行碰撞。

指定碰撞組,通常有三種情況:指定單個要碰撞的組,指定多個要碰撞的組,指定不可碰撞的組。

所以,我們設定指定碰撞組的值,從這三種情況分別介紹如何進行設定。

指定單個要碰撞的組

指定單個要碰撞的組最容易理解,就是你想和哪個組碰撞,就指定哪個組的id。

例如你的組id是2,想與碰撞組值為8的碰撞,那mask(2d)或cancollidewith(3d)的值設定為8即可。

這樣,碰撞組2就只會與碰撞組8發生物理碰撞。

指定多個要碰撞的組

如果我們想與多個碰撞組發生碰撞,那就需要運用到按位或的運算。

3d物理處理起來比較簡單,由於通常是在**裡設定值,所以,我們可以直接使用按位或的運算表示式即可。

例如,我想與8、32、128這幾個碰撞組發生碰撞。

那麼,直接在**裡用 8|32|128 表示即可。如下面的**示例所示:

//指定***碰撞器可以與其發生碰撞的碰撞組

***.cancollidewith =8 | 32 | 128;

而2d物理,開發者需要直接在ide的剛體mask屬性裡填寫按位或運算結果,比如剛才的8|32|128的按位或運算結果是168。mask屬性值裡要輸入168,才會與8、32、128這幾個碰撞組發生碰撞。

所以,我們可以借助第三方工具來進行按位或運算,例如chrome的除錯工具,下圖就是在chrome中進行按位或運算。

為了便於直觀計算,mask值可以理解為要碰撞的類別category十進位制數值的求和。

但要理解,實質是二進位制的按位或位運算。

既然講到按位或運算,這裡再囉嗦幾句,展開說一下按位或運算的基礎。位運算底子紮實可跳過此處,閱讀下個部分。

按位或運算是二進位制的按位相或運算,我們填寫的十進位制數值,需要先轉換為二進位制,然後對每一位進行相或運算。

即兩個二進位制值相或的時候,只要對應的二進位制位中有1,那結果位就為1,否則結果位為0。

如果說兩個十進位制轉成兩個二進位制後,位數不一樣怎麼相或?補0即可。

例如十進位制的1與2進行相或的位運算,十進位制的2轉換為二進位制是10,十進位制的1轉換為二進位制是1,那麼1補為01即可。為了讓大家更直觀的理解,可以參考下圖進行理解。

通過上圖的示意說明,我們可以看到,對應起來按位或運算得到的值是11,二進位制11的十進位制值為3。

所以2d剛體的mask屬性值為3的時候,是1與2的按位或運算結果,也就mask為3可以與1和2的碰撞分組進行碰撞。

需要了解的是,

按位或運算雖然可以計算出碰撞多個組的對應值,但物理引擎中真正決定能不能進行碰撞的,其實是按位與運算。了解完按位與的物理碰撞原理,我們就可以進一步掌握除了按位或以外的碰撞指定技巧。

下面,我們再聊聊碰撞關係的形成,

物理引擎會用碰撞組的值與指定的可碰撞組的值進行按位與運算,按位與的計算結果非0,就可以碰撞;為0,就不可以碰撞。

剛才我們將剛體的mask值設定為3,現在我們用按位與來驗證一下,指定為3能否與碰撞組2發生碰撞。

首先我們將十進位制的3轉換成二進的11,十進位制的2轉換為二進位制的10。當我們每一位進行相與計算時,只有當兩個計算位都為1的時候,結果位才為1,否則結果位為0。我們繼續用參考圖輔助理解。

通過上圖的示意說明,我們可以看到,11與10的二進位制按位與運算結果為10,而10的十進位制對應的值是2,上文講過,非0就可以碰撞。所以,當mask值為3,category值為2的時候,就可以發生碰撞。

舉一反三,如下圖所示,當按位與運算結果為0的時候,就不可以碰撞。

指定不可碰撞的組

通過上文,我們了解到按位與運算才是決定碰撞的判斷條件。那麼我們只要通過位運算,達成這個條件,是不是就可以指定與誰碰撞了。順著這個思路,我們嘗試一下二進位制異或運算。

首先,我們需要了解,-1與任何2的n次冪值按位與運算,都是冪值本身,是非0的,可以碰撞的。也就是說-1可以與所有組(2的n次冪值)進行碰撞。

那麼我們用-1去異或運算任何2的n次冪值,得到的結果再與該冪值進行按位與運算,一定是為0,也就是不可以碰撞的。驗證測試的過程,如下圖所示。

轉換為二進位制的異或運算過程就不截圖了,過程與之前按位與和按位或一樣,只是異或運算的規則為:參與運算的兩個數,對應位為「異」(值不同),則該位結果為1,否則為 0。

通過上圖的驗證流程,我們可以看到,通過-1去異或運算我們想排除的組,那該結果值就可以指定不想去碰撞的組。除了這些指定的組(例如上圖的8和16組),其它組都是可碰撞的,如下圖所示。

在專案使用的時候,3d物理,和指定多個可碰撞組一樣,指定不可碰撞組,也是直接使用位運算表示式即可。例如直接在**裡用 -1^8^16 表示。如下面的**示例所示:

//指定***碰撞器不可以與其發生碰撞的碰撞組,本例為8和16

***.cancollidewith = -1 ^ 8 ^ 16;

2d物理,還是要直接在layaair ide中,為剛體mask屬性輸入結果。為了便於直觀計算,mask值可以理解為不想碰撞的類別category十進位制數值求和+1,再取負。但要理解,實質是二進位制的異或位運算。

寫在最後

end

引擎案例分享:

推薦閱讀:

Unity 3D 物理引擎之碰撞器

碰撞器非為很多種,在這就不一一介紹了,值得注意的物體間碰撞的忽略有兩種方法,一種是通過指令碼裡的 實現兩個物體不發生碰撞,方法為 作用是設定遊戲物體ball a不與當前指令碼掛到的物體發生碰撞,注意,引數是遊戲物體的collider元件 physics.ignorecollision ball a....

關於2d物理引擎box2d與ape的評論

ape不行,做點簡單的撞球,撞球之類遊戲還行。我最開始用他實驗性做了個簡單的基於物理引擎的泡泡龍類遊戲,發現稍微多一點的幾何體堆疊在一起就會產生滲透現象,沒辦法只好更改最初的設計。要專注做物理遊戲,還是要精通box2d才行,而且box2d幾乎任何主流語言都有它的版本。所以建議不要學ape,除非你只是...

自己動手寫2D物理引擎 初級篇 1

第一章 框架設計 總體的類如下圖所表示。shape作為形狀基類。儲存了與形狀有關的物理量 class shape rectangle和circle派生於shape,儲存了實際的形狀資訊。class rectangle public shape class circle public shape ph...