從第3單元開始,就介紹過什麼是非同步事件(簡稱「事件」),舉凡網路連線(URLSession)、互動手勢(Gesture)、按鍵(Button)…等,都會觸發非同步事件,當事件發生時,會回頭呼叫我們寫的函式(或匿名函式)— 稱為事件處理函式(event handler)。

事件處理是每位程式設計師必須熟悉的重要觀念。

在 Swift 中,事件處理大多採用「發布者-訂閱者」(Publisher-Subscriber)溝通模式,要先有程式在事件發生時發布訊息,我們才能訂閱。在本課程中,發布者大多是作業系統或框架底層,我們寫的程式作為訂閱者。

在前一課6-10e其實就用過事件處理:

// 6-10e 動畫控制器
OrbitEntityAction.subscribe(to: .paused) { 事件 in
   ...
}

這行程式會訂閱公轉動作(OrbitEntityAction)的暫停事件,RealityKit 框架是發布者,當動作暫停時,會發布資料(稱為訊息或通知)給每個訂閱者。此例中,資料會以參數「事件」(名稱可自訂)帶進我們所寫的匿名函式 — 即事件處理函式。

上一節6-11c手勢互動也同樣用到事件處理:

// 6-11c
var 手勢: some Gesture {
    TapGesture()
        .targetedToAnyEntity()
        .onEnded { 事件 in
           ...
        }
}

事件處理的應用很廣,到處都看得到。

RealityKit 提供哪些事件可供訂閱呢?根據原廠文件,包括以下幾大類別:

# 事件類別 說明 相關事件
1 AccessibilityEvents 無障礙輔助事件
2 AnimationEvents 動畫事件 .PlaybackCompleted 播放結束
.PlaybackLooped 循環播放
.PlaybackStarted 開始播放
.PlaybackTerminated 播放終止
.SkeletalPoseUpdateComplete
3 AudioEvents 音效播放事件 .PlaybackCompleted 播放結束
4 CollisionEvents 碰撞事件 .Began 碰撞開始
.Ended 碰撞結束
.Updated 持續碰撞
5 ComponentEvents 元件事件 .DidActivate 元件已啟用
.DidAdd 元件已加入
.DidChange 元件已變更
.WillDeactivate 元件將失效
.WillRemove 元件將移除
6 PhysicsSimulationEvents 物理模擬事件 .DidSimulate 模擬已開始
.WillSimulate 模擬即將開始
7 SceneEvents 場景事件 .AnchoredStateChanged 錨點變更
.DidActivateEntity 個體已啟用
.DidAddEntity 個體已加入
.DidReparentEntity 變更父個體
.Update 場景更新
.WillDeactivateEntity 個體將失效
.WillRemoveEntity 個體將移除
8 SynchronizationEvents 網路同步事件
9 VideoPlayerEvents 影片播放事件

這些類別表明在什麼時間點,可以插入我們寫的程式碼,例如「場景更新」(SceneEvents.Update)預設每1/60秒更新一次,每次就會呼叫一次事件處理函式,用得好的話,可以給畫面帶來驚奇的效果。

對物理模擬來說,最常用的是碰撞事件,共有三個,分別是碰撞開始、碰撞結束、持續碰撞中,本節將利用碰撞開始事件(CollisionEvents.Began),在炸彈與上升氣泡碰撞時發出響聲,並讓氣泡消失。