从 SwiftUI 访问 SpriteKit 方法

问题描述 投票:0回答:1

我想使用 SwiftUI 按钮调用 SpriteKit 类中定义的方法。我在类上使用

@Observable
宏,并在 SwiftUI 内的类实例上使用
@State

一些类属性是可以访问的,但不是我想要使用的方法。调用它会抛出 3 个编译器错误:

  • 无法调用非函数类型“Binding”的值
  • 引用下标“subscript(dynamicMember:)”需要包装器“Binding”
  • “SKScene”类型的值没有使用根类型“SKScene”的键路径的动态成员“resetToInitialConditions”

使用

@Bindable
代替
@State
并不能解决问题。

我错过了什么?

SwiftUI 代码:

import SwiftUI
import SpriteKit

struct ActionReplay: View {
    @State var myActionScene: SKScene = ActionScene(size: CGSize(width: 1000, height: 1000))
    
    var body: some View {
        ZStack {
            SpriteView(scene: myActionScene, debugOptions: [.showsFPS, .showsNodeCount])
                .ignoresSafeArea()
            VStack {
                Spacer()
                HStack {
                    Button(action: {
                        myActionScene.resetToInitialConditions() // Errors here
                    }, label: {
                        Text("Reset")
                    })
                    .buttonStyle(.bordered)
                }
            }
        }
    }
}

数据和SpriteKit:

struct InitialConditions {
    var position: CGPoint = .zero
    var rotation: CGFloat = 5
    var velocity: CGVector = CGVector(dx: 0, dy: 0)
    var angularVelocity: CGFloat = 0
}

@Observable class ActionScene: SKScene {
    
    var initialConditions = InitialConditions()
    var baseObject: SKSpriteNode!
    var ground: SKSpriteNode!
    
    override init(size: CGSize) {
        super.init(size: size)
        self.scaleMode = .resizeFill
        self.anchorPoint = CGPoint(x: 0.5, y: 0.5)
    }
    
    required init(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    override func didMove(to view: SKView) {
        backgroundColor = .white
        createObjects()
    }
    
    func createObjects() {
        baseObject = SKSpriteNode(color: .red, size: CGSize(width: 60, height: 60))
        baseObject.anchorPoint = CGPoint(x: 0.5, y: 0.5)
        baseObject.position = initialConditions.position
        baseObject.zRotation = initialConditions.rotation
        baseObject.physicsBody = SKPhysicsBody(rectangleOf: baseObject.size)
        baseObject.physicsBody?.restitution = 1.1
        baseObject.physicsBody?.linearDamping = 0
        addChild(baseObject)
        
        ground = SKSpriteNode(color: .darkGray, size: CGSize(width: 370, height: 10))
        ground.position = CGPoint(x: .zero, y: -300)
        ground.physicsBody = SKPhysicsBody(rectangleOf: ground.size)
        ground.physicsBody?.affectedByGravity = false
        ground.physicsBody?.isDynamic = false
        addChild(ground)
    }
    
    func resetToInitialConditions() {
        baseObject.physicsBody?.velocity = initialConditions.velocity
        baseObject.physicsBody?.angularVelocity = initialConditions.angularVelocity
        baseObject.position = initialConditions.position
        baseObject.zRotation = initialConditions.rotation
    }
    
    // Testing the method I want to call
    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        resetToInitialConditions()
    }
}
swift swiftui sprite-kit observation
1个回答
0
投票

您已将

@State
定义为:

@State var myActionScene: SKScene = ActionScene(size: CGSize(width: 1000, height: 1000))

这告诉编译器

myActionScene
是一个
SKScene
。但是,实际上,您有一个 SKScene
子类
,称为
ActionScene

因为你告诉编译器它实际上只是一个

SKScene
(从技术上讲,它是
ActionScene
的超类),它认为唯一可用的方法/属性是在
SKScene
上定义的方法/属性。如果您想访问
ActionScene
上定义的内容,您必须告诉编译器它是什么:

@State var myActionScene: ActionScene = ActionScene(size: CGSize(width: 1000, height: 1000))

或者,编译器甚至会为你推断类型:

@State var myActionScene = ActionScene(size: CGSize(width: 1000, height: 1000))
最新问题
© www.soinside.com 2019 - 2024. All rights reserved.