問題重現
點擊按鈕,調用GameScene對象的函數,分別是向左跑動,停止,向右跑動。
SwiftUI代碼如下(GameScene.swift代碼略):
var scene: GameScene {
let scene = SKScene(fileNamed: "GameScene") as! GameScene
scene.scaleMode = .aspectFill
return scene
}
struct ContentView: View {
var body: some View {
ZStack {
SpriteView(scene: scene)
VStack {
Spacer()
HStack {
Button("<<<") {
scene..runAnim(.L)
}
Button("xxx") { scene.runToStopAnim() }
Button(">>>") {scene.runAnim(.R)}
}
}
}
}
}
排查經過
發現點擊按鈕後,界面沒有出現跑動動畫。
在GameScene的runAnim函數打上斷點,運行後發現斷點觸發,表明確實是調用到函數了。
又在GameScene裏重寫touchesBegan函數,在裏面直調用用runAnim函數,運行,點擊界面,有發生動畫了。
可以確定 GameScene的代碼是沒有問題的。
於是猜想,是不是因爲存在某些機制,SwiftUI不能直接調用SKScene裏面的函數?
網上一頓搜索,“Swiftui 如何控制 SpriteView” 之類的問題,下載了一些Demo,找到的資料,實現方式都是,從SwiftUI傳遞變量到SKScene裏面,然後SKScene在update函數裏判斷變量並更新界面。
差點就掉進坑裏了。
午休後,看到一個stackoverflow的一個回答[這裏],發現自己犯了一個跟該問題一樣的低級錯誤。
解決
原來一不注意,我把 scene 寫成了計算屬性,導致每次使用scene時,都是重新創建對象。
正確寫法是:
var scene: GameScene = {
let scene = SKScene(fileNamed: "GameScene") as! GameScene
scene.scaleMode = .aspectFill
return scene
}()
實踐證明,是可以直接在SwiftUI裏面調用SpriteKit對象函數的。