前面的話
本文將簡要介紹 Cocos Creator 中的碰撞系統,Cocos Creator 內置了一個簡單易用的碰撞檢測系統,支持圓形、矩形以及多邊形相互間的碰撞檢測
編輯碰撞組件
當添加了一個碰撞組件后,可以通過點擊 inspector 中的 editing 來開啟碰撞組件的編輯

【多邊形】
如果編輯的是多邊形碰撞組件,會出現如下圖所示的多邊形編輯區域,區域中的這些點是可以拖動的,拖動的結果會反映到多邊形碰撞組件的 points 屬性中

當鼠標移動到兩點連成的線段上時,鼠標指針會變成添加樣式,這時點擊鼠標左鍵會在這個地方添加一個點到多邊形碰撞組件中
按住 ctrl 或 command 按鍵時,移動鼠標到多邊形頂點上,會發現頂點以及連接的兩條線條變成紅色,這時點擊鼠標左鍵將會刪除多邊形碰撞組件中的這個點

多邊形碰撞組件中有一個 Regenerate Points 功能,這個功能可以根據組件依附的節點上的 Sprite 組件的貼圖的像素點來自動生成相應輪廓的頂點
Threshold 指明生成貼圖輪廓頂點間的最小距離,值越大則生成的點越小,可根據需求進行調節

【圓形】
如果編輯的是圓形碰撞組件,則會出現下圖所示的圓形編輯區域

當鼠標懸浮在圓形編輯區域的邊緣線上時,邊緣線會變亮,這時點擊鼠標左鍵拖動將可以修改圓形碰撞組件的半徑大小

【矩形】
如果編輯的是矩形碰撞組件,則會出現如下圖所示的矩形編輯區域

當鼠標懸浮在矩形碰撞區域的頂點上時,點擊鼠標左鍵拖拽可以同時修改矩形碰撞組件的長寬;當鼠標懸浮在矩形碰撞區域的邊緣線上時,點擊鼠標左鍵拖拽將修改矩形碰撞組件的長或寬中的一個方向
按住 shift 鍵拖拽時,在拖拽過程中將會保持按下鼠標那一刻的長寬比例,按住 alt 鍵拖拽時,在拖拽過程中將會保持矩形中心點位置不變
【偏移】
以上所有的碰撞組件編輯中,都可以在各自的碰撞中心區域點擊鼠標左鍵拖拽來改變偏移量
碰撞分組
分組管理,需要打開項目設置面板進行設置,位置為 菜單欄 -> 項目 -> 項目設置
打開項目設置面板后,在分組管理一欄可以看到分組列表的配置項,如下圖所示

點擊添加分組按鈕后即可添加一個新的分組,默認會有一個 Default 分組
要注意的是,分組添加后不可以刪除,但可以任意修改分組的名字
【碰撞分組配對】
在分組列表下面可以進行碰撞分組配對表的管理,如下圖所示

這張表里的行與列分別列出了分組列表里面的項,分組列表里的修改將會實時映射到這張表里。可以在這張表里配置哪一個分組可以對其他的分組進行碰撞檢測,假設 a 行 b 列被勾選上,那么表示 a 行上的分組將會與 b 列上的分組進行碰撞檢測
運行時修改節點的 group 之后,需要調用 Collider 的 apply,修改才會生效
根據上面的規則,在這張表里產生的碰撞對有:
Platform-Bullet、Collider-Collider、Actor-Wall、Actor-Platform
腳本控制
cocos creator 內置了一個簡單易用的碰撞檢測系統,根據添加的碰撞組件進行碰撞檢測
當一個碰撞組件被啟用時,這個碰撞組件會被自動添加到碰撞檢測系統中,並搜索能夠與之進行碰撞的其他已添加的碰撞組件來生成一個碰撞對
需要注意的是,一個節點上的碰撞組件,無論如何都是不會進行相互碰撞檢測的
【接口】
獲取碰撞檢測系統
const manager = cc.director.getCollisionManager();
默認碰撞檢測系統是禁用的,如果需要使用則需要使用以下方法來開啟碰撞檢測系統
manager.enabled = true;
默認碰撞檢測系統的 debug 繪制是禁用的,如果需要使用則使用以下方法開啟 debug 繪制
manager.enableDebugDraw = true;
開啟后在運行時可顯示碰撞組件的碰撞檢測范圍,如下所示
如果需要顯示碰撞組件的包圍盒,可以通過以下接口來進行設置
manager.enabledDrawBoundingBox = true;
結果如下所示
【回調】
當碰撞系統檢測到有碰撞產生時,將會以回調的方式通知使用者,如果產生碰撞的碰撞組件依附的節點下掛的腳本中有實現以下函數,則會自動調用以下函數,並傳入相關參數
/** * 當碰撞產生的時候調用 * @param {Collider} other 產生碰撞的另一個碰撞組件 * @param {Collider} self 產生碰撞的自身的碰撞組件 */ onCollisionEnter: function (other, self) { console.log('on collision enter'); // 碰撞系統會計算出碰撞組件在世界坐標系下的相關的值,並放到 world 這個屬性里面 var world = self.world; // 碰撞組件的 aabb 碰撞框 var aabb = world.aabb; // 節點碰撞前上一幀 aabb 碰撞框的位置 var preAabb = world.preAabb; // 碰撞框的世界矩陣 var t = world.transform; // 以下屬性為圓形碰撞組件特有屬性 var r = world.radius; var p = world.position; // 以下屬性為 矩形 和 多邊形 碰撞組件特有屬性 var ps = world.points; },
/** * 當碰撞產生后,碰撞結束前的情況下,每次計算碰撞結果后調用 * @param {Collider} other 產生碰撞的另一個碰撞組件 * @param {Collider} self 產生碰撞的自身的碰撞組件 */ onCollisionStay: function (other, self) { console.log('on collision stay'); },
/** * 當碰撞結束后調用 * @param {Collider} other 產生碰撞的另一個碰撞組件 * @param {Collider} self 產生碰撞的自身的碰撞組件 */ onCollisionExit: function (other, self) { console.log('on collision exit'); }
【觸發】
properties: { collider: cc.BoxCollider }, start () { // 開啟碰撞檢測系統,未開啟時無法檢測 cc.director.getCollisionManager().enabled = true; // cc.director.getCollisionManager().enabledDebugDraw = true; this.collider.node.on(cc.Node.EventType.TOUCH_START, function (touch, event) { // 返回世界坐標 let touchLoc = touch.getLocation(); // https://docs.cocos.com/creator/api/zh/classes/Intersection.html 檢測輔助類 if (cc.Intersection.pointInPolygon(touchLoc, this.collider.world.points)) { console.log("Hit!"); } else { console.log("No hit"); } }, this); }
collider 組件
點擊屬性檢查器下面的添加組件按鈕,然后從添加碰撞組件中選擇需要的 Collider 組件,即可添加 collider 組件到節點上
【屬性】
tag: 標簽。當一個節點上有多個碰撞組件時,在發生碰撞后,可以使用此標簽來判斷是節點上的哪個碰撞組件被碰撞了
editing: 是否編輯此碰撞組件,只在編輯器中有效
一個節點上可以掛多個碰撞組件,這些碰撞組件之間可以是不同類型的碰撞組件
碰撞組件目前包括了 Polygon(多邊形)、Circle(圓形)、Box(矩形)這幾種碰撞組件,這些組件都繼承自 Collider 組件
【多邊形 Polygon】
offset 組件相對於節點的偏移量
points 組件的頂點數組
【圓形 circle】
offset 組件相對於節點的偏移量
radius 組件的半徑
【矩形 box】
offset 組件相對於節點的偏移量
size 組件的長寬