Reputation: 48495
I'm building a 3D game scene with SceneKit and I want to build like a "hud" over top, in order to get it kind of working, I built my ViewController by using a subview and overlaySKScene
like so:
class ViewController:UIViewController {
var sceneView: SCNView!
var mainScene = MainScene() // <- SCNScene
var spriteScene: OverlayScene! // <- SKScene
override func viewDidLoad() {
super.viewDidLoad()
self.sceneView = SCNView(frame: CGRect(x: 0, y: 0, width: self.view.frame.width, height: self.view.frame.height))
self.sceneView.scene = mainScene
self.sceneView.backgroundColor = UIColor.clear
self.view.addSubview(self.sceneView)
self.spriteScene = OverlayScene(size: self.view.bounds.size)
self.sceneView.overlaySKScene = self.spriteScene
}
}
I've got a few questions about how this should be done the right way, as I'm running into some things that seem unusual.
First, lets say I need to do a segue, it doesn't seem clear to me how I would actually observe a tap on one of the SpriteKit nodes in the OverlayScene
and then change controllers for the main parent ViewController. I haven't found any resources online that describe a similar situation.
Here is a trimmed down version of my OverlayScene
:
import UIKit
import SpriteKit
class OverlayScene: SKScene {
var actionBarNode: SKSpriteNode!
override init(size: CGSize) {
super.init(size: size)
self.backgroundColor = UIColor.clear
self.actionBarNode = SKSpriteNode()
self.actionBarNode.size = CGSize(width: size.width, height: 100)
self.actionBarNode.position = CGPoint(x: size.width / 2, y: 50)
self.actionBarNode.color = .white
self.addChild(self.actionBarNode)
}
}
Upvotes: 2
Views: 1731
Reputation: 48495
I found a solution for my problem for anyone who may stumble into this same issue (which I think is likely as many examples demonstrate an overlay scene added as a subview in the manner I did.
First the tapHandler
I had in my viewController
needed to have the property cancelsTouchesInView
set to false. This will allow the gesture to be received by the underlying views.
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(handleTap(_:)))
tapGesture.cancelsTouchesInView = false
sceneView.addGestureRecognizer(tapGesture)
The reason this doesn't happen to all subviews is because I was relying on a view that was sized to 100% of the frame, covering the underlying ones, rather than just having the view occupy a smaller screen area, like a button or scoreboard as seen in the example docs.
Upvotes: 1
Reputation: 553
I am not answering your two questions directly, instead I will deal with your larger issue which is that you want a HUD on your game. A user interface. I never made a Scenekit
game, but I did make a Spritekit
game and the HUD is a clever trick. Let me explain.
Imagine you are standing behind a camera and looking through to see what the camera is seeing through its lens. You see the scene in front of it. Now take a piece of paper, cut out a rectangular box in the middle and draw on the remaining periphery. Tape this piece of paper to the front of the camera and look through. You still see the scene (a little smaller now), but now you also see the paper with the drawings. This is how HUDs work for the game.
I did some searching and both SpriteKit
and SceneKit
have a camera
. In sceneKit you create a camera node
and set the point of view of the scene to that camera. This represents the player looking out into the scene.
I am not sure if it works the same way in SceneKit
, but in SpriteKit
you can add nodes to the camera that will be locked in place. These become your HUD elements (buttons, score, etc). Since these are all child nodes of the camera
they move when you move the camera so it feels like they are a static HUD. This is how you achieve a HUD. Read up on the documentation for SceneKit
cameras as this will help you understand how to achieve the same effect.
I once also thought about doing it the way you are going now and it proved to be a very painful experience to mix SceneKit
and SpriteKit
so I would caution against it.
Also, while you can mix Interface Builder and SpriteKit
I would caution against it. It basically ruined my first game into a buggy mess. If you do decide to use Interface Builder, try to limit it to menu screens and options screens. But, I found that programmatically creating everything gives you a much smoother, cleaner, and bug free experience.
Hope this helps!
Upvotes: 3