进入SKScene时Swift值变为静态

ih99xse1  于 2023-02-28  发布在  Swift
关注(0)|答案(1)|浏览(125)

我有一个SwiftUI视图包含一个SpriteView。这个SpriteView从一个位于导体类中的合并变量成功接收到一个Double值:

var passThrough = PassthroughSubject<Double, Never>()

这是正确接收PassthroughSubject的SwiftUI视图。

struct SpriteKitView: View {
    
    @ObservedObject var sharedViewModel: SharedViewModel
    var scene = GameScene()
    
    init(sharedViewModel:SharedViewModel){
        let width = UIScreen.main.bounds.width
        let height = UIScreen.main.bounds.height
        scene.size = CGSize(width: width, height: height)
        scene.scaleMode = .fill
        self.sharedViewModel = sharedViewModel
    }
    
    var body: some View {
        
        SpriteView(scene: scene, options: [.allowsTransparency])
            .onReceive(sharedViewModel.conductor.passThrough){ ( value ) in
                
                print("Received Double: \(value)")
                
                scene.scaleVar = CGFloat(value)
            }
    }
}

游戏场景只是一个画成SKShapeNode的圆。在更新中你可以看到passThrough是这样输入的:

class GameScene: SKScene {
        
    var scaleVar: Double = 0
    var myObject: SKShapeNode!
    
    override func didMove(to view: SKView) {
        let node = SKShapeNode(circleOfRadius: 100)
        node.position = CGPoint(x: size.width/2, y: size.height/2)
        node.fillColor = SKColor.orange
        myObject = node
        addChild(myObject)
    }
    
    override func update(_ currentTime: TimeInterval) {
        
        print("Update Double: \(scaleVar)")
        
        myObject.setScale(CGFloat(scaleVar))
        
        print("Update CGFloat: \(CGFloat(scaleVar))")
                
    }
}

从SwiftUI到SpriteKit,该值被转换为一个随机数。请参见代码中打印的控制台输出:
收到双倍:0.9631603454475357〈-正确值
更新双精度:0.0356531249999999〈-随机静态??
更新CGFloat:0.0356531249999999〈-随机静态??
更新双精度:0.0356531249999999〈-随机静态??
更新CGFloat:0.0356531249999999〈-随机静态??
为什么更新没有接收到发送的Double。当我在发送之前转换成CGFloat时也发生了同样的事情。

2o7dmzc5

2o7dmzc51#

我把你的代码放到一个新的iOS应用项目中,用你的SpriteKitView和下面的SharedViewModel实现替换默认的“ContentView”。我无法重现你报告的结果。在每种情况下,双精度值都按预期发布。你的代码中可能有其他解释吗?

import SwiftUI
import SpriteKit
import Combine

class SharedViewModel: NSObject, ObservableObject {
    var passThrough = PassthroughSubject<Double, Never>()

    override init() {
        super.init()
        self.sendDoubles()
    }

    private func sendDoubles() {
        Task {
            var angle = 0.0
            while(true) {
                guard !Task.isCancelled else { break }
                angle = fmod(angle + 0.1, 2 * Double.pi)
                passThrough.send(sin(angle))
                try await Task.sleep(nanoseconds: UInt64(1.0e8))
            }
        }
    }
}

class GameScene: SKScene {
    var scaleVar: Double = 0
    var myObject: SKShapeNode!

    override func didMove(to view: SKView) {
        let node = SKShapeNode(circleOfRadius: 100)
        node.position = CGPoint(x: size.width/2, y: size.height/2)
        node.fillColor = SKColor.orange
        myObject = node
        addChild(myObject)
    }

    override func update(_ currentTime: TimeInterval) {

        print("Update Double: \(scaleVar)")

        myObject.setScale(CGFloat(scaleVar))

        print("Update CGFloat: \(CGFloat(scaleVar))")

    }
}

struct ContentView: View {
    @ObservedObject var sharedViewModel: SharedViewModel
    var scene = GameScene()

    init(sharedViewModel:SharedViewModel){
        let width = UIScreen.main.bounds.width
        let height = UIScreen.main.bounds.height
        scene.size = CGSize(width: width, height: height)
        scene.scaleMode = .fill
        self.sharedViewModel = sharedViewModel
    }

    var body: some View {
        SpriteView(scene: scene, options: [.allowsTransparency])
            .onReceive(sharedViewModel.passThrough.receive(on: DispatchQueue.main)){ ( value ) in

                print("Received Double: \(value)")

                scene.scaleVar = CGFloat(value)
            }
    }
}

相关问题