I got a question about a Scene Kit project I'm doing. So I have this scene where I randomly spawn cubes and add them to my scene root node, the thing is that they are rendered at the beginning, but quickly they stop being rendered, so I don't see these new objects being spawned, I do see them again when I tap on the screen (so when I make an action on the scene or whatever) OR sometimes some of them are randomly rendered and I don't know why
I have tried setting rendersContinuously to true but this does not change anything.
Here is the cube spawning thread :
DispatchQueue.global(qos: .userInitiated).async {
while true {
self.spawnShape()
sleep(1)
}
}
Here is how I add them to the child nodes :
let geometryNode = SCNNode(geometry: geometry)
geometryNode.simdWorldPosition = simd_float3(Float.random(in: -10..<10), 2, shipLocation+Float.random(in: 20..<30))
self.mainView.scene!.rootNode.addChildNode(geometryNode)
And here's the endless action applied to the camera and my main node :
ship.runAction(SCNAction.repeatForever(SCNAction.moveBy(x: 0, y: 0, z: 30, duration: 1)))
camera.runAction(SCNAction.repeatForever(SCNAction.moveBy(x: 0, y: 0, z: 30, duration: 1)))
The added geometryNode cubes stop being rendered unless I tap on screen
How can I force the rendering of these new child node objects on the scene even when I don't touch the screen?
Thank you
EDIT asked by ZAY:
Here is the beginning of my code basically:
override func viewDidLoad() {
super.viewDidLoad()
guard let scene = SCNScene(named: "art.scnassets/ship.scn")
else { fatalError("Unable to load scene file.") }
let scnView = self.view as! SCNView
self.mainView = scnView
self.mainView.rendersContinuously = true
self.ship = scene.rootNode.childNode(withName: "ship", recursively: true)!
self.camera = scene.rootNode.childNode(withName: "camera", recursively: true)!
self.ship.renderingOrder = 1
self.ship.simdWorldPosition = simd_float3(0, 0, 0)
self.camera.simdWorldPosition = simd_float3(0, 15, -35)
self.mainView.scene = scene
DispatchQueue.global(qos: .userInitiated).async {
while true {
self.spawnShape()
sleep(1)
}
}
ship.runAction(SCNAction.repeatForever(SCNAction.moveBy(x: 0, y: 0, z: 30, duration: 1)))
camera.runAction(SCNAction.repeatForever(SCNAction.moveBy(x: 0, y: 0, z: 30, duration: 1)))
let tap = UILongPressGestureRecognizer(target: self, action: #selector(tapHandler))
tap.minimumPressDuration = 0
self.mainView.addGestureRecognizer(tap)
}
When I tap on screen, this code is called:
func tapHandler(gesture: UITapGestureRecognizer) {
let p = gesture.location(in: self.mainView)
let turnDuration: Double = 0.3
print("x: \(p.x) y: \(p.y)")
if gesture.state == .began {
if p.x >= self.screenSize.width / 2 {
self.delta = 0.5
}
else {
self.delta = -0.5
}
self.ship.runAction(SCNAction.rotateBy(x: 0, y: 0, z: self.delta, duration: turnDuration))
return
}
if gesture.state == .changed {
return
}
self.ship.runAction(SCNAction.rotateBy(x: 0, y: 0, z: -self.delta, duration: turnDuration))
}
Basically it rotates my ship to right or left depending on which side of screen I tap, and it displays the coordinates where I tapped in the console. When I release, the ship goes back to the initial position/rotation.
DispatchQueue.global(qos: .userInitiated).async {
while true {
self.spawnShape()
sleep(1)
}
}
Aren't you blocking that shared queue by doing that? Use a Timer if you want to run something periodically.