问题重现
点击按钮,调用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对象函数的。