去(2024)年更新的 RealityView 讓 iOS/iPadOS/macOS 也能像 visionOS 一樣,輕鬆寫出空間運算或AR程式,其中關鍵之一,就是能與 SwiftUI 緊密結合,尤其在手勢控制,比原先的 ARView + UIKit 好用多了。
所有App遊戲都會有些物體或角色讓使用者控制,這也是遊戲之所以好玩的關鍵:讓使用者能參與互動。而SwiftUI 的優勢之一,就是易用的控制視圖與手勢 。
設想一幕遊戲場景:當看到怪物從海底漂浮上來時,用手勢釋放深水炸彈將它炸死。
此處先借用上一節模型,將正十二面體當作炸彈,一開始放在上方靜止氣泡裡面,當滑鼠或手勢點選氣泡時,釋放正十二面體,讓它往下掉,與下方漂浮上來的氣泡碰撞(碰撞後的處理,待下一節介紹)。
效果如下,為了方便觀察,將上升氣泡的速度從原來0.6m/sec降為0.3m/sec:
影片後半段,當滑鼠游標移到靜止氣泡時,會稍微變亮,這是另一個元件,「懸浮效果元件」(HoverEffectComponent)的功能,只對 macOS 有效,從影片中可看出,這個元件也會影響子個體,當游標移到正十二面體時,同樣會變亮。
氣泡模型.components.set(HoverEffectComponent()) // 游標偵測
...
氣泡模型.addChild(模型) // 將正十二面體綁到氣泡中
至於影片一開始,當游標或手勢點選靜止氣泡時,就會釋放正十二面體往下掉落,這個功能怎麼做到的呢?這是本節的重點。
第一步,在設定手勢之前,要被點選的個體須載入「輸入標定元件」(InputTargetComponent),否則手勢無效;而輸入標定元件需要碰撞偵測元件,才知道點選位置是否在個體範圍內,因此至少須載入兩個元件:
氣泡模型.components.set(InputTargetComponent()) // 手勢偵測
氣泡模型.generateCollisionShapes(recursive: false) // 碰撞偵測
第二步是設定手勢:
var 手勢: some Gesture {
TapGesture()
.targetedToAnyEntity()
.onEnded { 事件 in
print(事件.entity)
if let 炸彈 = 事件.entity.findEntity(named: "炸彈") as? ModelEntity {
炸彈.physicsBody = .init(mode: .dynamic)
炸彈.generateCollisionShapes(recursive: false)
}
}
}