SceneKit:在两个节点之间接触后缓慢加载UIView

时间:2016-07-19 04:15:59

标签: ios swift physics contact scenekit

我刚刚在Scene Kit中发现了一个非常奇怪的行为。我创建了一个干净的项目,看看是否会发生这种情况,而且确实如此。请考虑以下GameViewController类:

import UIKit
import QuartzCore
import SceneKit

class GameViewController: UIViewController, SCNPhysicsContactDelegate {

    func physicsWorld(world: SCNPhysicsWorld, didBeginContact contact: SCNPhysicsContact) {
        let label = UILabel(frame: CGRectMake(0, 0, 100, 100))
        label.textColor = .whiteColor()
        label.text = "Test"
        self.view.addSubview(label)
    }

    override func viewDidLoad() {

        // Controller
        super.viewDidLoad()

        // Scene
        let scene = SCNScene()
        scene.physicsWorld.contactDelegate = self

        // Scene View
        let scnView = self.view as! SCNView
        scnView.scene = scene

        // Camera
        let camera = SCNCamera()
        camera.usesOrthographicProjection = true
        camera.orthographicScale = 8

        // Camera Node
        let cameraNode = SCNNode()
        cameraNode.camera = camera
        cameraNode.position = SCNVector3(x: -3, y: 7.5, z: 10)
        cameraNode.eulerAngles = SCNVector3(x: -0.5, y: -0.5, z: 0)
        scene.rootNode.addChildNode(cameraNode)

        // Light
        let light = SCNLight()
        light.type = SCNLightTypeDirectional

        // Light Node
        let lightNode = SCNNode()
        lightNode.light = light
        lightNode.eulerAngles = SCNVector3Make(-1, -0.5, 0)
        scene.rootNode.addChildNode(lightNode)

        // Box Shape
        let geometry = SCNBox(width: 1, height: 1, length: 1, chamferRadius: 0)
        geometry.materials.first?.diffuse.contents = UIColor(red: 255, green: 255, blue: 0, alpha: 1)

        // Upper Box
        let box = SCNNode(geometry: geometry)
        box.physicsBody = SCNPhysicsBody(type: .Dynamic, shape: nil)
        box.physicsBody?.categoryBitMask = 1
        box.physicsBody?.contactTestBitMask = 2
        scene.rootNode.addChildNode(box)

        // Bottom Box
        let box2 = SCNNode(geometry: geometry)
        box2.position.y -= 5
        box2.physicsBody = SCNPhysicsBody(type: .Static, shape: nil)
        box2.physicsBody?.categoryBitMask = 2
        box2.physicsBody?.contactTestBitMask = 1
        box2.physicsBody?.affectedByGravity = false
        scene.rootNode.addChildNode(box2)

    }
}

这里发生的是,我们创建一个SCNScene,然后我们添加相机/闪电并创建两个将发生碰撞的盒子。我们还将控制器设置为物理联系代表的委托。

但是当两个对象之间发生接触时,重要的代码位于顶部。我们创建一个UILabel并将其放置在屏幕的左上角。但问题出在这里:标签显示需要大约7秒钟。而且似乎总是这一次。这看起来很奇怪,但您可以自己尝试:只需创建一个SceneKit项目(使用Swift),并将控制器代码替换为我提供的代码。

附加说明:如果您在print("a")函数中添加physicsWorld(),它会立即运行,因此代码会在正确的时间运行,但出于某种原因,UILabel不是&{} #39;立即显示。

1 个答案:

答案 0 :(得分:1)

起初我以为你的场景在接触后没有渲染;因此不显示标签,因此请放入scnView.playing = true行。但是,这导致标签永远不会显示。

接下来的想法是,你正试图在一个你不应该做的事情上做点什么。修改UIKit视图应该只在主线程上完成,并且不清楚什么线程调用SCNPhysicsContactDelegate函数。鉴于它确保它在主线程上运行相对容易......

func physicsWorld(world: SCNPhysicsWorld, didBeginContact contact: SCNPhysicsContact) {
    dispatch_async(dispatch_get_main_queue()) {
        let label = UILabel(frame: CGRectMake(0, 0, 100, 100))
        label.textColor = .whiteColor()
        label.text = "Test"
        self.view.addSubview(label)
    }
}

这可以解决我的延迟,也适用于scnView.playing = true