剛剛加上的模型就像是個投象,並沒有實體。他們是有可能互相穿透的,而為了防止這樣的破綻,這個範例就是要用來防止碰撞。
一個模型都會有一個把它包起來個邊界框,可以使用intersectsMesh方法檢查網格相交的狀況:
mesh1.intersectsMesh(mesh2);
為了防止人車碰撞,因此建了一個長方形盒子來感應車子交疊的時候,並且路人沒有跟這個盒子交疊的時候,就讓路人停下腳步來避免碰撞穿越。所以主要是以下這段利用控制實體的位置來防止互相的碰撞穿越,那如果我想要加上物理引擎來讓他碰撞呢?
scene.onBeforeRenderObservable.add(() => {
if (carReady) {
// 重點在這段判斷
if (!dude.getChildren()[1].intersectsMesh(hitBox) && scene.getMeshByName("car").intersectsMesh(hitBox)) {
return;
}
}
dude.movePOV(0, 0, step);
distance += step;
if (distance > track[p].dist) {
dude.rotate(BABYLON.Axis.Y, BABYLON.Tools.ToRadians(track[p].turn), BABYLON.Space.LOCAL);
p +=1;
p %= track.length;
if (p === 0) {
distance = 0;
dude.position = new BABYLON.Vector3(1.5, 0, -6.9);
dude.rotationQuaternion = startRotation.clone();
}
}
})
物理引擎 (Physics Engine)是一個把你的物體,依據材質(質量﹑彈性﹑摩擦力),根據物理計算出他的重力與碰撞、跟使用者互動、力與運動等的幫手。與動畫設計每一幀不同,你設定規則,他模擬結果。Babylon.js內建了對多種物理引擎的插件支援,整合度非常高。
以下有主要常見的三個引擎的比較:
物理引擎 | 主要特點 | 優點 | 缺點/注意事項 |
---|---|---|---|
Havok | 官方合作、最高效能。由 Microsoft 維護,是專業遊戲(如《上古卷軸》、《最後一戰》)使用的物理引擎的 Web 版本。 | 效能極佳,穩定且功能強大,是 Babylon.js 官方推薦的未來方向。 | 授權注意:在客戶端(瀏覽器)使用是免費的。但若要在伺服器端進行物理運算,則需要商業授權。 |
Ammo.js | 功能強大、社群成熟。它是廣受歡迎的 C++ Bullet 物理引擎透過 Emscripten 編譯到 WebAssembly (WASM) 的版本。 | 效能優於 Cannon.js,功能非常完整,社群支援良好。在 Havok 出現前是最高效能的選擇。 | 檔案體積相對較大。 |
Cannon.js | 純 JavaScript、最易上手。完全用 JavaScript 寫成,不需要編譯過程。 | 輕量,易於除錯和理解,非常適合簡單的專案或學習物理概念。 | 效能是三者中最差的,且已多年未更新,可能存在一些 bug。 |
關於引用物理引擎的方法, 在playground可以試試看加上Havok:
比較關鍵的是這一段 :
// 使用plugin
var hk = new BABYLON.HavokPlugin();
/**
* enablePhysics是要讓場景啟用物理引擎, 並加上重力, 重力的方向是y軸,
* -9.8是模擬地球標準的重力加速度
* 並告訴要用hk也就是上面一行宣告的Havok引擎來計算效果
*/
scene.enablePhysics(new BABYLON.Vector3(0, -9.8, 0), hk);
// Create a sphere shape and the associated body. Size will be determined automatically.
/**
* PhysicsAggregate 是一個輔助物件讓模型和對應的物理實體綁在一起,
* 所以用這個方式建立的球體就有物力的實體不能隨意變穿透過去
* mass是物體的質量,質量越大受重力影響越大
* restitution是彈性的恢復係數,通常是0-1間, 0.75代表碰撞後保留 75% 的能量反彈
*/
var sphereAggregate = new BABYLON.PhysicsAggregate(sphere, BABYLON.PhysicsShapeType.SPHERE, { mass: 1, restitution:0.75}, scene);
// 在這行我們建立的地板, mass要為0才不會受到這個場景的重力影響,單純作為一個障礙物待在原地
var groundAggregate = new BABYLON.PhysicsAggregate(ground, BABYLON.PhysicsShapeType.BOX, { mass: 0 }, scene);
因此,在使用PhysicsAggregate 建立兩個有物理實體的物體-地面跟球體,他們就會互相碰撞而不會穿越過去了。
他真的整合得很好只需要幾行程式碼就可以達到很優秀的效果!