How to prevent SpriteKit from being stretched in SceneKit?

In WWDC 2017 SceneKit session they recommend using overlaySKScene to overlay SpriteKit layer on top of SceneKit for HUD etc. It seems to work fine until I rotate the iPhone / iPad. SpriteKit text is now stretched (when going from portrait to landscape) or shrunk (when going from landscape to portrait). Is there a way to keep text or graphics the same size regardless of orientation?

    sceneView.overlaySKScene = SKScene(size: sceneView.frame.size)

      

I solved the problem very simply. Just resize overlaySKScene and move everything to

override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
    let width = sceneView.frame.height
    let height = sceneView.frame.width

    sceneView.overlaySKScene?.size = CGSize(width:width, height:height)
    ...
}

      

Hopefully this helps other people to face the same problem.

+3


source to share


1 answer


You need to see how SKScene works:

This means overlaying the iphone screen size for a given orientation:  sceneView.overlaySKScene = SKScene(size: sceneView.frame.size)

Now I am not accepting any changes, so this means yours is scaleMode

set to .fill

, which means stretching the graphics until all sides are filled.

When you sit in portrait mode, you won't notice anything because it's a 1: 1 scale.

Now you translate it into a landscape.

The system will try to convert the size of your portrait screen to landscape size.

This means you're going to end up with a bold short graphic because it will stretch your sides and squeeze the top and bottom to fill in all the edges.

This is why the type code is sceneView.overlaySKScene = SKScene(size: sceneView.frame.size)

bad. You end up confusing yourself.

I always recommend using an SKS file or setting a constant scene size, so sceneView.overlaySKScene = SKScene(size: CGSize(750,1334))



Then, depending on how I want to display my overlay, I use the correct scaling mode.

For games where I want the overlay to take up an exact percentage of the screen space, I use .aspectFill

In games where I want the overlay to occupy the exact number of pixels, I use .resizeFill

After looking at scaleMode

, I now know what my scene should look like.

With .aspectFill

I will need to detect when the orientation has been flipped, at which time either present the SKS corresponding to the orientation, or move the nodes that match the orientation.

Since .resizeFill

I need to create a resize method that sticks to when the orientation is flipped and move the nodes in proportion to the new size.

You can detect when orientation is flipped in ViewController

with

override func viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator) 

      

then use the view to go to the scene to call the resize function / load the new scene.

+4


source







All Articles