SwiftUI+SpriteKit踩坑-調用SKScene對象函數不生效

問題重現

點擊按鈕,調用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對象函數的。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章