
物理模擬(Physics Simulation)主要用來實現(xiàn):
- 將動態(tài)行為添加到場景中的對象
- 檢測碰撞并響應物體之間的接觸
- 模擬真實的物理效應,如重力,彈力和 汽車模擬
1. 物理體(Physics Bodies)
1.1 SCNPhysicsBody 類
添加到節(jié)點上的物理模擬屬性。
當SceneKit準備渲染新的一幀時,它會對連接到場景中節(jié)點的物理實體執(zhí)行物理計算。 這些計算包括重力,摩擦以及與其他物體的碰撞。 你也可以將自己的力量和沖動應用于身體。 SceneKit完成這些計算后,它會在渲染幀之前更新節(jié)點對象的位置和方向。
要將物理模擬添加到節(jié)點,請創(chuàng)建并配置一個 SCNPhysicsBody 對象,然后將其賦給 SCNNode對象 的 physicsBody 屬性。 在對其施加力或沖擊之前,物理體必須與節(jié)點對象相關聯(lián)。
planeNode.physicsBody = SCNPhysicsBody(type:.kinematic, shape: nil)
1.1.1 一個對象的物理特征
SCNPhysicsBody 類在場景模擬時定義身體的物理特征。 有三個重要的屬性:
type屬性,用于確定對象在模擬中如何與力和其他物體進行交互:① 靜態(tài)物體(static)不受力量和碰撞的影響,不能移動;② 動態(tài)物體(dynamic)受到力量和與其他身體類型碰撞的影響;③ 運動物體(kinematic)不受力或碰撞的影響,但通過直接移動它們,可能會導致影響動態(tài)物體的碰撞。physicsShape屬性,它定義用于碰撞檢測目的的三維形體。 使用簡單形狀代替節(jié)點的可見幾何體的精細細節(jié)時,物理模擬運行速度更快。 通常,您將一個物體的物理形狀設置為與其節(jié)點的可見內容大致相匹配的邊界框,球體或原始形狀。 有關創(chuàng)建物理形狀的詳細信息,請參閱 SCNPhysicsShape。kinematic()屬性, 對動力體(dynamic body)施加力或力矩會導致與其質量成比例的加速度(或角加速度)。
1.1.2 定義一個物體的類別和碰撞(Category and Collisions)
當你設計使用物理效果的游戲時,你可以按需在場景中定義不同類別的物理體。一個物理體可以分配到多個類別中。 除了聲明對象自己的類別之外,它還會聲明它可以與哪些類別的物理體進行交互。
使用 categoryBitMask 和 collisionBitMask 屬性來定義對象的碰撞行為。 SCNPhysicsCollisionCategory中列出的常量為這些屬性提供默認值。 另外,通過 contactTestBitMask 屬性,實現(xiàn) SCNPhysicsContactDelegate 的協(xié)議方法,可以獲取到發(fā)生碰撞的對象 。
關于碰撞和類別,另外有一篇博客專門講解。
1.1.3 與之相關的類
”物理場”會產生影響某個區(qū)域所有物體的力量,例如渦旋和引力吸引力。 有關可用字段類型的詳細信息和列表,后面 SCNPhysicsField類 會詳細講解。
你可以添加更高級別的行為來控制多個物體之間的交互,例如關節(jié)和輪式車輛。 有關可用行為的詳細信息和列表,后面 SCNPhysicsBehavior會詳細講解。
場景的physicsWorld屬性包含一個 SCNPhysicsWorld 對象,用于管理影響整個場景的物理特性。
1.1.4 物理模擬和渲染循環(huán)
SceneKit 將物理模擬作為渲染循環(huán)的一部分,遵守 SCNSceneRendererDelegate 協(xié)議,在每次渲染循環(huán)的時候,SceneKit 確定每個添加在每個節(jié)點上的物理模擬,并且同步計算出物理模擬對物體的影響。
例如,基于速度更新物體的位置,SceneKit將物理模擬的結果應用到場景中進行顯示。
不僅可以通過物理模擬為 SceneKit 內容創(chuàng)建動畫,還可以通過動作(action)來隱式或顯式定義的動畫。
注意, SceneKit并不是將物理模擬的結果應用于場景中的 SCNNode 對象,而是應用于表示其當前顯示狀態(tài)的每個節(jié)點的表示對象。因此,改變受物理影響的節(jié)點的屬性需要特別考慮。
如果更改變 transform 屬性或者transform 屬性中的某個值(如物理位置或旋轉),則 SceneKit 將重置該節(jié)點的物理模擬。
如果只想更改變換 transform 中的某個值,請在進行更改之前復制該演示節(jié)點的transform ,如下所示:
// Copy the presentation node's transform to the model node.
node.transform = node.presentationNode.transform
// Change one component of the new transform
node.eulerAngles.z = newRollValue
SCNPhysicsShape 類
對物理體的外觀的抽象,用于調整碰撞檢測。
當SceneKit為場景中的 SCNPhysicsBody對象 執(zhí)行接觸檢測和其他模擬時,它將使用 SCNPhysicsShape 描述的物理形狀,而不是可見對象的渲染幾何體。 這種方法既提高了仿真性能,又可讓你更輕松地設計玩家可與之互動的場景元素周圍的游戲玩法。
2. 碰撞和接觸檢測
SCNPhysicsContactDelegate 協(xié)議
當場景中兩個物理實體之間發(fā)生接觸或碰撞(Contact)時,可以使用這些方法進行響應。
要接收 Contact 消息,請設置 SCNPhysicsWorld 對象的 contactDelegate 屬性。 當 Contact 開始,Contact 信息發(fā)生變化以及 Contact結束時,SceneKit 會調用委托方法。
SCNPhysicsContact 類
兩個物理體之間接觸的詳細信息。
開發(fā)者不直接創(chuàng)建 SCNPhysicsContact 實例; 無論何時發(fā)生contact ,SceneKit都會自動創(chuàng)建這些對象。
要接收 contact 消息,設置 SCNPhysicsWorld 對象的 contactDelegate 屬性后,實現(xiàn) SCNPhysicsContactDelegate 協(xié)議方法。 接下來,對于場景中的每個物理實體,設置 categoryBitMask和 collisionBitMask屬性以定義哪些交互應生成contact 消息。
這一塊剛開始不好理解,三言兩語難講清楚,詳細請參考 SceneKit中的物理模擬 | Bit-masks 。
3. 物理場景( Physics in a Scene )
SCNPhysicsWorld
全局模擬場景中的碰撞,重力,關節(jié)和其他物理效應。
不要直接創(chuàng)建SCNPhysicsWorld對象; 相反,參考請 SCNScene對象的physicsWorld 屬性。 使用物理世界對象來執(zhí)行以下任務:
- 管理物理模擬的全局屬性,例如其速度和恒定的引力(為了更精確地控制重力和類似的效果,請參閱 SCNPhysicsField 類)
- 注冊修改場景中物理實體(如關節(jié)和車輛)之間交互的行為。 有關更多詳細信息,請參閱 SCNPhysicsBehavior
- 當兩個物理體彼此接觸時,指定一個委托對象來接收消息
SCNPhysicsField 類
SCNPhysicsField 對象可以將引力、電磁和氣流等外力應用于物理體的特定區(qū)域上。
您可以創(chuàng)建許多類型的場效應,例如引力,電磁和氣流。 要將場效應添加到場景中,請創(chuàng)建要使用的類型的物理場,然后將其附加到場景中節(jié)點的physicsField 屬性。
物理場可以影響 SCNPhysicsBody對象 和 SCNParticleSystem對象產生的粒子。

SCNPyhsicsBehavior 類
包含多個物理體的的關節(jié)、車輛模擬和其他高級行為的抽象父類。
SCNPhysicsBehavior對象定義一個或多個物理體的高級行為,修改物理模擬的結果。 這些高級行為包括連接多個物體的關節(jié),以便它們一起移動;車輛定義,使物體像汽車一樣滾動。 你從不直接使用這個類; 相反,你實例化了一個定義你想添加到物理世界中的行為類型的子類。
4. 關節(jié)(Joints)
SCNPhysicsHingeJoint 類
連接兩個物體并允許它們在一個軸上相互轉動的物理行為。
鉸鏈(Hinge)具有單一的自由度(旋轉)。 你還可以使用鉸鏈連接來固定物體,以便它只能通過圍繞包含它的節(jié)點的坐標空間中的特定軸旋轉來移動。

SCNPhysicsSliderJoint 類
連接兩個物體并允許它們相互滑動并圍繞其連接點旋轉的物理行為。
根據(jù)滑塊(Slider)關節(jié)是否允許滑動或旋轉,滑塊關節(jié)可以具有零個,一個或兩個自由度。 您還可以使用滑塊接頭固定一個物體,以便只能通過在包含該物體的節(jié)點的坐標空間中滑動特定的軸來移動物體。 您也可以使用滑塊接頭作為電機,對連接的物體施加力或扭矩。

SCNPhysicsBallSocketJoint 類
連接兩個物理體并允許它們在任何方向上相互轉動的物理行為。

動圖來自 Physics Joints in Unity 2D 一文中。
5. 汽車模擬(Vehicle Simulation)

SCNPhysicsVehicle類
一種物理行為,修改一個物理體的行為,像汽車,摩托車或其他輪式車輛。
要搭建一輛車,請將 SCNPhysicsBody對象 指定為底盤,并將SCNPhysicsVehicleWheel對象作為其車輪。 對于每個車輪,您可以定義懸架和牽引力等物理特征,并將場景中的節(jié)點關聯(lián)起來以提供車輪的大小和視覺表示。 在構建車輛后,可以通過加速,制動和轉向來控制它。
盡管也可以使用一組物理體和關節(jié)來共同模擬輪式車輛,但 SCNPhysicsVehicle類實現(xiàn)了更高級別的仿真,可以提供逼真的車輛行為和更高效的仿真性能。
SCNPhysicsVehicleWheel 類
上面已經提到了,SCNPhysicsVehicleWheel是與物理車輛行為相關的單個車輪的外觀和物理特征。
