首页 > 解决方案 > 如何确保 SceneKit 相机始终指向特定位置

问题描述

我正在用 Swift 5 编写游戏(但我最近通过游戏更新了 Swift 4 也有同样的问题),我所有的 SCNNode 都以 SCNVector3Zero 为中心。换句话说,(0,0,0) 位于我的游戏区域的中心。

SCNCamera 连接到 SNCNode 并位于游戏区域的边界之外,查看 (0,0,0)。

cameraNode.look(at: SCNVector3Zero)

如果我在场景中放置 5 个节点,都在 y=0 平面上,(0,0,0),(-1,0,-1),(1,0,1),(-1,0,1 ) 和 (1,0,-1) 就像骰子的表面显示 5,这一切都很好。我可以在 (0,0,0) 处的节点保持居中而没有移动的情况下围绕场景旋转。

如果我添加第二行,那么第一行移动到 y=1 并且第二行获得 y=-1 的节点,场景在旋转时会稍微摆动。

节点离中心越远,这种摆动就越夸张。

这是设置场景的代码(这个例子有三行,看起来像一个骰子的三维“五”面,点在 (0,0,0) 的中心,其他点在立方体的每个角上) ...

        添加球体(
            x: 0.0,
            y: 0.0,
            z: 0.0,
            半径:半径,
            纹理名称:“地球”)

        添加球体(
            x:-2.0 * 间距,
            y:-2.0 * 间距,
            z: 0.0,
            半径:半径,
            纹理名称:“地球”)
        添加球体(
            x:2.0 * 间距,
            y:2.0 * 间距,
            z: 0.0,
            半径:半径,
            纹理名称:“地球”)


        添加球体(
            x:-2.0 * 间距,
            y:2.0 * 间距,
            z: 0.0,
            半径:半径,
            纹理名称:“花岗岩”)
        添加球体(
            x:2.0 * 间距,
            y:-2.0 * 间距,
            z: 0.0,
            半径:半径,
            纹理名称:“花岗岩”)


        添加球体(
            x: 0.0,
            y:-2.0 * 间距,
            z:-2.0 * 间距,
            半径:半径,
            纹理名称:“粘液”)
        添加球体(
            x: 0.0,
            y:2.0 * 间距,
            z:2.0 * 间距,
            半径:半径,
            纹理名称:“粘液”)


        添加球体(
            x: 0.0,
            y:2.0 * 间距,
            z:-2.0 * 间距,
            半径:半径,
            纹理名称:“木头”)
        添加球体(
            x: 0.0,
            y:-2.0 * 间距,
            z:2.0 * 间距,
            半径:半径,
            纹理名称:“木头”)

这段代码的行为是,一切都围绕 (0,0,0) 对称,并且 (0,0,0) 处的节点准确地停留在它应该在的位置。

如果我将这个节点引入场景,一切都会大错特错......

        添加球体(
            x: 6.0,
            y: 6.0,
            z: 6.0,
            半径:半径,
            纹理名称:“地球”)

我尝试向每个质量为零的节点添加一个固定的物理体,但无济于事。这就像相机不再直接看(0,0,0),而是受到影响,而是场景中的节点。

我已经尝试过添加节点的各种排列方式,在某些测试中,似乎添加任何对 z 轴有价值的东西都会导致问题

这是 addSphere 方法...

    internal func addSphere(x: Float, y: Float, z: Float, radius: Float, color: UIColor, textureName: String) -> SCNNode {

        让sphereGeometry = SCNSphere(半径:CGFloat(半径))
        sphereGeometry.firstMaterial?.diffuse.contents = UIImage(imageLiteralResourceName: textureName)

        让sphereNode = SCNNode(几何:sphereGeometry)
        sphereNode.name = "点"

        sphereNode.position = SCNVector3(x: x, y: y, z: z)
        sphereNode.lines = [];
        sphereNode.ignoreTaps = false
        sphereNode.categoryBitMask = NodeBitMasks.dot

        //sphereNode.physicsBody = SCNPhysicsBody(type: .static, shape: nil)

        self.rootNode.addChildNode(sphereNode)

        返回 sphereNode
    }

没有错误,正如您所料,任何位于 (0,0,0) 的点在“查看”该点时旋转时都应保持静止。

任何指针都会非常感激,因为我无法弄清楚它为什么会这样。

标签: iosswiftcamerascenekit

解决方案


我假设您使用SCNView.allowsCameraControl = true来移动相机。SceneKit 的这个内置设置实际上仅用于您的场景的调试目的。当您想对相机移动进行专门控制时,它不适合任何事情。

您应该尝试实现相机轨道,请参阅https://stackoverflow.com/a/25674762/3358138

我可以用场景的“摇摆”中心重现您的问题,请参阅 Playground Gist https://gist.github.com/dirkolbrich/e2c247619b28a287c464abbc0595e23c

相机轨道解决了这种“摆动”,让相机保持在中心,请参阅 Playground Gist https://gist.github.com/dirkolbrich/9e4dffb3026d0540d6edf6877f27d1e4


推荐阅读