0

The old way of adding a gesture recognizer no longer works because the view is always nil. This is because there is no view actively presenting the SpriteView scene in SwiftUI.

class GameScene: SKScene {
    override func sceneDidLoad() {
        let gestureSwipe = UISwipeGestureRecognizer()
        gestureSwipe.addTarget(self, action: #selector(gestureActionHandleSwipe(_:)))
        view?.addGestureRecognizer(gestureSwipe)
        /// `view` is always nil
struct ContentView: View {
    var body: some View {
        SpriteView(scene: GameScene())
    }

To present a scene, you call the presentScene(:) method or presentScene(:transition:) method on the SKView class. If the scene is not currently presented, this property holds nil. https://developer.apple.com/documentation/spritekit/skscene/1519726-view

Simulating a drag gesture with the touchesMoved function seems easy. However, simulating a gesture like pinch is not as straightforward. So how can we gesture recognizer for a SpriteKit scene in SwiftUI?

XY L
  • 25,431
  • 14
  • 84
  • 143

2 Answers2

1

you will have better luck capturing the gesture at the SwiftUI level, then passing it to your GameScene state variable

class GameScene: SKScene {
    func swipeLeft() {
        print("left")
    }
    
    func swipeRight() {
        print("right")
    }

}
        
struct Gesture: View {
    @State var gameScene = GameScene()
    
    var body: some View {
        SpriteView(scene: gameScene)
            .gesture(DragGesture(minimumDistance: 20, coordinateSpace: .global)
                        .onEnded { value in
                            let horizontalAmount = value.translation.width
                            let verticalAmount = value.translation.height
                            
                            if abs(horizontalAmount) > abs(verticalAmount) {
                                (value.translation.width < 0) ? gameScene.swipeLeft() : gameScene.swipeRight()
                            }
                        })
    }
}
Fault
  • 1,115
  • 1
  • 7
  • 11
0

To add a gesture recognizer to the scene's view in didMove(to:), use SKScene's convertPoint(fromView:) and SKNode's convert(_:to:) methods to obtain the touch in the required coordinate space.

    /// SpriteKit calls the method didMove(to:) before it presents your scene
    /// in a view; it’s a good place to do some initial setup of your scene’s contents.
    ///
    /// You can use this method to implement any custom behavior for your scene
    /// when it is about to be presented by a view. For example, you might use this method to create the scene’s contents.
    /// https://developer.apple.com/documentation/spritekit/skscene/1519607-didmove
    override func didMove(to view: SKView) {        
        /// https://stackoverflow.com/a/50623843/2226315
        /// https://munirwanis.github.io/blog/2020/wwdc20-spritekit-swiftui/
        
        let pinchGesture = UIPinchGestureRecognizer()
        pinchGesture.addTarget(self, action: #selector(gestureHandlerPinch(_:)))
        view.addGestureRecognizer(pinchGesture)

        let gestureSwipe = UISwipeGestureRecognizer()
        gestureSwipe.addTarget(self, action: #selector(gestureHandlerSwipe(_:)))
        view.addGestureRecognizer(gestureSwipe)
    }
XY L
  • 25,431
  • 14
  • 84
  • 143