3

In WWDC 2017 SceneKit session they recommend using overlaySKScene to overlay a SpriteKit layer over SceneKit for HUD, etc. It seems to work fine until I rotate the iPhone/iPad. Now the text in SpriteKit all got stretched (if turn from portrait to landscape) or shrunk (if turn from landscape to portrait). Is there anyway to keep the text or graphics in same size regardless of orientation?

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

I solved the issue in a very simple way. Just resize the overlaySKScene and reposition everything in

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)
    ...
}

Hope this helps others facing similar problem.

Lim Thye Chean
  • 8,704
  • 9
  • 49
  • 88

1 Answers1

5

You need to look at how SKScene works:

This means set the overlay to size of the iphone screen for the given orientation: sceneView.overlaySKScene = SKScene(size: sceneView.frame.size)

Now I am assuming nothing else changes, so that means your scaleMode is set to .fill, which means stretch graphics till all sides are filled in.

When sitting in portrait mode, you will not notice anything because it is 1:1 scale.

Now you flip it to landscape.

The system is going to attempt to convert your portrait screen size to a landscape size.

This means you are going to get fat stubby graphics because it is going to stretch out your sides, and shrink your top and bottom to fill all edges.

This is why doing code like sceneView.overlaySKScene = SKScene(size: sceneView.frame.size) is bad. You end up getting yourself confused.

I always recommend either 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 proper scale mode.

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

In games where I want the overlay to take up the exact amount of pixel space, I use .resizeFill

By looking at the scaleMode, I now know how my scene is suppose to behave.

With .aspectFill, I am going to need to detect when orientation was flipped, and at that time either present the SKS corresponding to orientation, or move nodes corresponding to orientation.

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

You can detect when orientation flips in the ViewController with

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

then use the view to get to the scene to call your resize function/load a new scene.

Knight0fDragon
  • 16,609
  • 2
  • 23
  • 44