设置cnnode展示位置

时间:2018-07-21 14:14:52

标签: swift core-animation scenekit

我想将给定的scn:SCNNode 及其当前显示节点的转换设置为新值。但是,我在设置演示节点时遇到了麻烦。我尝试了四种方法:

  1. 设置演示节点的变换:

    scn.position              = newVal
    scn.presentation.position = newVal
    

    scn.presentation.transform只读的-无法设置。 (顺便说一句,设置演示文稿节点的转换不会出错,也许可以清除)

  2. 使用resetTransform():

    scn.position              = newVal
    scn.physicsBody.resetTransform()
    

    不执行任何操作。文档说它“在物理仿真中更新了身体的位置和方向,以匹配与身体相连的节点的位置和方向”。但是它没有改变。不清楚原因!

  3. 在设置时删除PhysicalBody:

    let pb                  = scn.physicsBody
    scn.physicsBody         = nil
    scn.position            = newVal
    scn.physicsBody         = pb
    

    这会将演示文稿转换设置为newVal(“是!” ),但是物理不起作用(“ boo!” )。也许一个人不能重用物理物体。

  4. 设置后添加新的物理实体:

    scn.position            = newVal
    scn.physicsBody         = SCNPhysicsBody(type:.dynamic, shape:nil)
    

    但是可惜scn.presentation.position没有newVal。

有想法吗?

2 个答案:

答案 0 :(得分:3)

我在使用SceneKit的项目中也注意到了这一点。您问题的直接答案是:“表示节点会自动更新其变换以匹配场景节点的变换。如果它似乎没有更新,请确保场景节点的isPaused设置为false。” 但是,场景节点很可能没有被暂停,并且/或者您'根本不使用动画,但是会发生此问题。

当项目中的所有内容在iOS 10上都运行良好时,我开始注意到该问题在iOS 11上间歇性地发生。我没有碰过SCNAnimation或类似的东西–我有自己的动画系统,所以我只是每.position更新我节点的renderer(_:, updateAtTime:)

所以AFAICT,这里的问题不是您要执行的操作-问题是SceneKit一直是错误的且编写得不好(API的某些部分尚未针对Swift进行全面更新) ,并且可能仍会出现bug和编写不佳的情况,因为SceneKit团队似乎已经完全着手开发ARKit。因此,解决您的问题的方法似乎是“只需尝试一堆东西,设置.position的次数比必要的时间多,或者在更新循环中的其他时间进行,或者实际上是hack-y解决方案,解决SceneKit中的问题”。

就我而言,个人而言,我正在缓慢地努力放弃项目中的SceneKit-我主要切换到了自定义的Metal着色器,然后我将创建自己的场景渲染循环,最终将替换场景图和SCNNode的使用情况使我对SceneKit越野车的混乱情况零依赖。

我希望我对你有个好消息,但是两年来我一直在处理SceneKit的怪异之处。这是未完成的垃圾。

更新:我最终通过使用肮脏的hack“修复”了我的演示节点的异常行为,这种肮脏的黑客在每帧节点的位置上都添加了少量的“摆动”:

public func updateNode()
{
    let wigglePositionValue = SCNVector3(
        x: Float.random(in: -0.00001...0.0001),
        y: Float.random(in: -0.00001...0.0001),
        z: Float.random(in: -0.00001...0.0001)
    )
    self.scnNode.position = _locationModel.value + wigglePositionValue
}

旁注:正如预期的那样,像这样的“抖动”节点位置也不允许SceneKit进行某些批处理/渲染优化,并且(以我的经验)会导致性能下降。这是一个骇人的变通办法,仅适用于最坏的情况(“客户说我们必须在本周开始使用该游戏,否则我们将无法获得报酬,现在这是愚蠢的SceneKit错误?!” )

是的,...真正的解决方案是“不要使用SceneKit”。

答案 1 :(得分:0)

我在使用ARKit时遇到了同样的问题。因为physicsBody根据表示节点而不是节点本身进行调整,并且由于更改节点的变换时表示节点不会立即更新,所以您获得的PhysicsBody可能很奇怪。

我最近找到了一种解决方案

要更改表示节点的变换,请使用SCNAction。例如,如果要设置位置,请使用node.runAction(SCNAction.move(by: SCNVector3, duration: 0))而不是简单的node.position = SCNVector3。这样,表示节点将立即更新,您将获得正确的物理。

此外,此方法仅适用于节点本身(不适用于子节点)。因此,如果您对节点的子节点执行操作,您仍然无法获得正确的表示节点和物理。要更改子节点的变换和表示形式变换,请使用node.position = SCNVector3方法。

总而言之,在更改节点的变换时,请执行一个操作,在更改节点的子变换时,请直接设置该变换。