设置scnnode呈现位置

All*_*ing 4 core-animation scenekit swift

我想设置两个给定的变换 scn:SCNNode 其当前演示文稿节点,为一个新值。但是,我在设置演示节点时遇到了问题。我试过四种方法:

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

    scn.position              = newVal
    scn.presentation.position = newVal
    
    Run Code Online (Sandbox Code Playgroud)

    scn.presentation.transform只读的——它不能被设置。(顺便说一句,设置表示节点的转换编译没有错误,也许需要清理一些东西)

  2. 使用 resetTransform():

    scn.position              = newVal
    scn.physicsBody.resetTransform()
    
    Run Code Online (Sandbox Code Playgroud)

    什么都不做。文档说它“更新物理模拟中身体的位置和方向以匹配身体所连接的节点的位置和方向”。但它没有改变。不清楚为什么!

  3. 设置时移除physicsBody:

    let pb                  = scn.physicsBody
    scn.physicsBody         = nil
    scn.position            = newVal
    scn.physicsBody         = pb
    
    Run Code Online (Sandbox Code Playgroud)

    这将演示转换设置为 newVal ( "yea!" ),但物理不起作用 ( "boo!" )。也许不能重复使用物理体。

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

    scn.position            = newVal
    scn.physicsBody         = SCNPhysicsBody(type:.dynamic, shape:nil)
    
    Run Code Online (Sandbox Code Playgroud)

    但唉,scn.presentation.position 没有 newVal。

想法?

Sli*_*son 5

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

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

所以 AFAICT,这里的问题不是你在做什么——问题是 SceneKit 一直有问题而且写得不好(API 的某些部分仍然没有为 Swift 完全更新),并且可能仍然有问题写得不好是因为 SceneKit 团队似乎已经完全转向了 ARKit 的工作。所以你的问题的解决方案似乎是“只是尝试一堆东西,.position比必要的更频繁地设置,或者在更新循环中的不同时间,或者似乎解决 SceneKit 中的问题的真正hack-y解决方案” .

就我个人而言,我正在慢慢地在我的项目中放弃 SceneKit——我主要切换到自定义 Metal 着色器,然后我会做我自己的场景渲染循环,最终我会替换场景图和SCNNode用法让我对 SceneKit 的混乱局面零依赖。

我希望我有更好的消息告诉你,但我已经处理 SceneKit 的奇怪问题 2 年了。这是未完成的垃圾。

更新:我最终通过使用一个肮脏的黑客来“修复”我的演示节点的行为不端,该技巧在每一帧的节点位置上增加了少量的“摆动”:

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
}
Run Code Online (Sandbox Code Playgroud)

旁注:正如预期的那样,像这样“摇晃”节点位置也不允许 SceneKit 进行一些批处理/渲染优化,并且(根据我的经验)会导致性能下降。这是一个可怕的hacky变通方法,仅适用于最坏的情况(“客户说我们这周必须上线游戏,否则我们不会得到报酬,现在这个愚蠢的SceneKit错误?!”)

所以是的......这里真正的解决方案是“不要使用SceneKit”。