Search code examples
classswiftuispriteview

pass / share class with SpriteView GameScene from a SwiftUi View


I am playing around with SpriteView, which works great. However I cannot figure out how to share a class with Spritekit GameScene,that is instantiated in one my views. Sharing my class with other views works like a charm. But how can I access my gameCenterManager class from spritekit's GameScene, how do I pass the class ? I don't have any clue how to do this. I considered making a global accessible class, but its not what I want.

The goal is to be able to send and receive data from inside GameScene to update players location and etc. But the matchmaking happens inside a SwiftUI View, which is also where the class is created.

The gameCenterManger class is created like so;

struct ContentView: View {
   
    @StateObject var gameCenterManager = GameCenterManager()
    
    var body: some View {

    ...
    etc

the class is set up like so :

class GameCenterManager: NSObject, ObservableObject {

   //lots of stuff going on
   ...

}

And is shared to the GameSceneView view that will create the SpriteView, like so :

    Button("Show Sheet") {
            self.showingSheet.toggle()
    }
    .buttonStyle(RoundedRectangleButtonStyle())
    .buttonStyle(ShadowButtonStyle())
    .fullScreenCover(isPresented: $showingSheet, content: { GameSceneView(gameCenterManager:self.gameCenterManager)})

Finally, inside my GameSceneView, the GameScene for SpriteView is configured.

struct GameSceneView: View {
    
    var gameCenterManager: GameCenterManager
    @Environment(\.presentationMode) var presentationMode
    
    var scene: SKScene {
        let scene = GameScene()
        scene.size = CGSize(width: UIScreen.main.bounds.size.width , height: UIScreen.main.bounds.size.height)
        scene.scaleMode = .fill

        return scene
    }

    var body: some View {
        
        Button("Dismiss") {
            self.presentationMode.wrappedValue.dismiss()

        }
        
        Button("send data") {
            gameCenterManager.increment()
        }
        

        SpriteView(scene: scene )
            .frame(width: UIScreen.main.bounds.size.width, height: UIScreen.main.bounds.size.height - 200 )
            .ignoresSafeArea()
            .overlay(ImageOverlay(), alignment: .bottomTrailing)
            
    }
    
}

Solution

  • Perhaps others are looking to do the same? Here below is the answer in code snippets

    GameCenterManager is the class that I want to access across all views and SKScenes

    In mainview:

       @main    
       struct gameTestApp: App {
            
            @StateObject var gameCenterManager = GameCenterManager()
            
            var body: some Scene {
                WindowGroup {
                    ContentView().environmentObject(gameCenterManager)
                }
            }
        }
    

    In Contentview view add :

    @EnvironmentObject var gameCenterManager:GameCenterManager
    

    And where I transition to GameSceneView inside Contentview, which will load my SKScene

        Button("Show Sheet") {
                self.showingSheet.toggle()
        }
        .buttonStyle(RoundedRectangleButtonStyle())
        .buttonStyle(ShadowButtonStyle())
        
        .fullScreenCover(isPresented: $showingSheet, content: { GameSceneView()})
    

    Then in GameSceneView add:

    @EnvironmentObject var gameCenterManager:GameCenterManager
    

    and where we load SKScene:

    var scene: SKScene {
            let scene = GameScene()
            scene.size = CGSize(width: UIScreen.main.bounds.size.width , height: UIScreen.main.bounds.size.height)
            scene.scaleMode = .fill
            scene.gameCenterManager = gameCenterManager
    
            return scene
        }
    

    Then finally in GameScene itself add:

    var gameCenterManager: GameCenterManager?