设置 scnnode 呈现位置
setting scnnode presentation position
我想将给定 scn:SCNNode
和 其当前表示节点的转换设置为新值。但是,我在设置演示节点时遇到问题。我试过四种方法:
设置表示节点的变换:
scn.position = newVal
scn.presentation.position = newVal
scn.presentation.transform
是 只读 -- 无法设置。 (顺便说一句,设置演示节点的转换编译没有错误,也许需要清理)
使用resetTransform():
scn.position = newVal
scn.physicsBody.resetTransform()
什么都不做。文档说 "Updates the position and orientation of a body in the physics simulation to match that of the node to which the body is attached"。但它没有改变。不清楚为什么!
设置时移除physicsBody:
let pb = scn.physicsBody
scn.physicsBody = nil
scn.position = newVal
scn.physicsBody = pb
这将表示变换设置为 newVal ("yea!"),但 Physics 不起作用 ("boo!").也许一个人不能重复使用物理学 body.
设置后添加新物理body:
scn.position = newVal
scn.physicsBody = SCNPhysicsBody(type:.dynamic, shape:nil)
可惜,scn.presentation.position 没有 newVal。
想法?
我在使用 SceneKit 的项目中也注意到了这一点。您问题的直接答案是:“演示节点自动更新其变换以匹配场景节点的变换。如果它似乎没有更新,请确保场景节点的 isPaused
设置为 false
。” 但是,您的场景节点可能未暂停 and/or 您根本没有使用动画,但出现了这个问题。
我开始注意到这个问题在 iOS 11 间歇性地发生,当时我的项目中的所有内容在 iOS 10 上运行良好。我没有触及 SCNAnimation
或类似的东西 -我有自己的动画系统,所以我只是每隔 renderer(_:, updateAtTime:)
.
更新节点的 .position
所以 AFAICT,这里的问题不是你正在做的任何事情——问题是 SceneKit 一直是错误的并且写得不好 (API 的某些部分仍然没有已经针对 Swift) 进行了全面更新,并且可能仍然存在错误和编写不当,因为 SceneKit 团队似乎已经完全转向 ARKit 的工作。所以你的问题的解决方案似乎是 “只是尝试一堆东西,设置 .position
比必要的更频繁,或者在更新循环中的不同时间,或者真正的 hack-y 解决方案似乎解决了 SceneKit 中的问题”.
就我个人而言,我正在慢慢努力在我的项目中放弃 SceneKit — 我主要切换到自定义 Metal 着色器,然后我会做我自己的场景渲染循环,最终我会替换场景图和 SCNNode
用法让我对 SceneKit 的错误混乱零依赖。
我希望我有更好的消息告诉你,但我已经处理 SceneKit 的怪异问题 2 年了。是未完成的垃圾。
更新: 我最终“修复”了我的演示节点的错误行为,方法是使用一个肮脏的 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 进行一些 batching/rendering 优化,并且(以我的经验)会导致性能下降。这是一个可怕的 hacky 解决方法,仅用于最坏的情况 (“客户说我们必须在本周上线游戏,否则我们就得不到报酬,现在这个愚蠢的 SceneKit 错误? !”)
所以是的......这里真正的解决方案是“不要使用 SceneKit”。
我在使用 ARKit 时遇到了同样的问题。因为 physicsBody 根据呈现节点而不是节点本身调整自身,并且因为当您更改节点的变换时呈现节点不会立即更新,所以您获得的 physicsBody 可能很奇怪。
我最近找到了一种解决方案:
要更改表示节点的变换,请使用 SCNAction。例如,如果要设置位置,请使用 node.runAction(SCNAction.move(by: SCNVector3, duration: 0))
而不是简单地 node.position = SCNVector3
。这样,演示节点会立即更新,您将获得正确的物理效果。
此外,此方法仅适用于节点本身(不适用于子节点)。所以如果你运行对节点的子节点进行操作,你仍然无法获得正确的表示节点和物理。要更改 子节点的 转换和表示转换,请使用 node.position = SCNVector3
方法。
综上所述,当改变节点的变换时,运行一个动作,当改变节点的子变换时,直接设置变换。
我想将给定 scn:SCNNode
和 其当前表示节点的转换设置为新值。但是,我在设置演示节点时遇到问题。我试过四种方法:
设置表示节点的变换:
scn.position = newVal scn.presentation.position = newVal
scn.presentation.transform
是 只读 -- 无法设置。 (顺便说一句,设置演示节点的转换编译没有错误,也许需要清理)使用resetTransform():
scn.position = newVal scn.physicsBody.resetTransform()
什么都不做。文档说 "Updates the position and orientation of a body in the physics simulation to match that of the node to which the body is attached"。但它没有改变。不清楚为什么!
设置时移除physicsBody:
let pb = scn.physicsBody scn.physicsBody = nil scn.position = newVal scn.physicsBody = pb
这将表示变换设置为 newVal ("yea!"),但 Physics 不起作用 ("boo!").也许一个人不能重复使用物理学 body.
设置后添加新物理body:
scn.position = newVal scn.physicsBody = SCNPhysicsBody(type:.dynamic, shape:nil)
可惜,scn.presentation.position 没有 newVal。
想法?
我在使用 SceneKit 的项目中也注意到了这一点。您问题的直接答案是:“演示节点自动更新其变换以匹配场景节点的变换。如果它似乎没有更新,请确保场景节点的 isPaused
设置为 false
。” 但是,您的场景节点可能未暂停 and/or 您根本没有使用动画,但出现了这个问题。
我开始注意到这个问题在 iOS 11 间歇性地发生,当时我的项目中的所有内容在 iOS 10 上运行良好。我没有触及 SCNAnimation
或类似的东西 -我有自己的动画系统,所以我只是每隔 renderer(_:, updateAtTime:)
.
.position
所以 AFAICT,这里的问题不是你正在做的任何事情——问题是 SceneKit 一直是错误的并且写得不好 (API 的某些部分仍然没有已经针对 Swift) 进行了全面更新,并且可能仍然存在错误和编写不当,因为 SceneKit 团队似乎已经完全转向 ARKit 的工作。所以你的问题的解决方案似乎是 “只是尝试一堆东西,设置 .position
比必要的更频繁,或者在更新循环中的不同时间,或者真正的 hack-y 解决方案似乎解决了 SceneKit 中的问题”.
就我个人而言,我正在慢慢努力在我的项目中放弃 SceneKit — 我主要切换到自定义 Metal 着色器,然后我会做我自己的场景渲染循环,最终我会替换场景图和 SCNNode
用法让我对 SceneKit 的错误混乱零依赖。
我希望我有更好的消息告诉你,但我已经处理 SceneKit 的怪异问题 2 年了。是未完成的垃圾。
更新: 我最终“修复”了我的演示节点的错误行为,方法是使用一个肮脏的 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 进行一些 batching/rendering 优化,并且(以我的经验)会导致性能下降。这是一个可怕的 hacky 解决方法,仅用于最坏的情况 (“客户说我们必须在本周上线游戏,否则我们就得不到报酬,现在这个愚蠢的 SceneKit 错误? !”)
所以是的......这里真正的解决方案是“不要使用 SceneKit”。
我在使用 ARKit 时遇到了同样的问题。因为 physicsBody 根据呈现节点而不是节点本身调整自身,并且因为当您更改节点的变换时呈现节点不会立即更新,所以您获得的 physicsBody 可能很奇怪。
我最近找到了一种解决方案:
要更改表示节点的变换,请使用 SCNAction。例如,如果要设置位置,请使用 node.runAction(SCNAction.move(by: SCNVector3, duration: 0))
而不是简单地 node.position = SCNVector3
。这样,演示节点会立即更新,您将获得正确的物理效果。
此外,此方法仅适用于节点本身(不适用于子节点)。所以如果你运行对节点的子节点进行操作,你仍然无法获得正确的表示节点和物理。要更改 子节点的 转换和表示转换,请使用 node.position = SCNVector3
方法。
综上所述,当改变节点的变换时,运行一个动作,当改变节点的子变换时,直接设置变换。