【发布时间】:2019-03-02 16:11:18
【问题描述】:
我有一个 SCNSphere 正在爬 45 度的山坡。
节点保持一致的速度,直到每个级别的同一点,在该点它意外地下降速度,这是一个 10 秒的问题片段。
速度下降发生在this clip 中的 8 秒。
当节点到达 -240 的 z 位置时,似乎整个游戏速度减半。
我通过以下方式对此进行了测试,但始终没有成功。
- 尝试在没有重力的情况下进行测试。
- 在不与山丘相撞的情况下进行了测试。
- 尝试在没有阻尼或摩擦的情况下进行测试。
- 尝试打印节点速度以注意到任何变化,尽管速度在 z 轴上保持在 -5.0 的持续时间 尽管速度显着下降,但仍保持水平。
- 尝试打印物理世界速度以注意任何变化,尽管速度在持续时间保持在 1.0 尽管速度显着下降,但仍保持水平。
- 检查了帧速率下降,尽管它保持 60 fps 的帧速率,总共只进行了 14 次绘制调用,多边形计数低于 15k。
使用以下函数在渲染器中的每一帧更新球体的速度。
func updatePositions() {
if let playerPhysicsBod = playerNode.physicsBody {
playerPhysicsBod.velocity.x = (lastXPosition - playerNode.position.x) * 8
playerPhysicsBod.velocity.z = -5
print("player velocity is \(playerNode.physicsBody!.velocity)")
}
}
func renderer(_ renderer: SCNSceneRenderer, updateAtTime time: TimeInterval) {
updatePositions()
updateSegments()
}
这个项目是一个新项目,所以行数不多,我将整个代码库包含在下面。
class GameViewController: UIViewController {
let scene = SCNScene(named: "art.scnassets/gameScene.scn")!
let jump = SCNScene(named: "art.scnassets/jump.scn")!.rootNode.childNode(withName: "jump", recursively: true)!
let box = SCNScene(named: "art.scnassets/box.scn")!.rootNode.childNode(withName: "box", recursively: true)!
var playerNode = SCNNode()
var cameraNode = SCNNode()
var lastXPosition = Float()
var floorSegments = [SCNNode]()
override func viewDidLoad() {
super.viewDidLoad()
// retrieve the SCNView
let scnView = self.view as! SCNView
// scnView.isJitteringEnabled = true
scnView.scene = scene
scnView.delegate = self
scnView.showsStatistics = true
setupCamera()
setupPlayer()
setupSegments()
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
guard let tLocationX = touches.first?.location(in: self.view).x else { return }
let ratio = tLocationX / self.view.frame.maxX
lastXPosition = Float((5 * ratio) - 2.5)
}
func setupCamera() {
if let camera = scene.rootNode.childNode(withName: "camera", recursively: true) {
cameraNode = camera
cameraNode.name = "camera"
}
}
func setupPlayer() {
if let player = scene.rootNode.childNode(withName: "player", recursively: true) {
playerNode = player
playerNode.name = "player"
}
}
func setupSegments() {
if let segment = scene.rootNode.childNode(withName: "segment", recursively: true) {
floorSegments.append(segment)
}
}
}
extension GameViewController: SCNSceneRendererDelegate {
func updateSegments() {
playerNode.position = playerNode.presentation.position
if let lastSegmentClone = floorSegments.last?.clone() {
lastSegmentClone.childNodes.forEach { (node) in
node.removeFromParentNode()
}
if abs(playerNode.position.z - lastSegmentClone.position.z) < 30 {
// set up next segment
lastSegmentClone.position = SCNVector3(lastSegmentClone.position.x, lastSegmentClone.position.y + 4, lastSegmentClone.position.z - 4)
floorSegments.append(lastSegmentClone)
// Add falling blocks to the segment
for _ in 0...2 {
let boxClone = box.clone()
let randomX = Int.random(in: -2...2)
let randomY = Int.random(in: 1...3)
boxClone.eulerAngles.z = Float(GLKMathDegreesToRadians(-45))
boxClone.position = SCNVector3(randomX, randomY, -randomY)
lastSegmentClone.addChildNode(boxClone)
}
// Add falling blocks to the segment
for (index,segment) in floorSegments.enumerated().reversed() {
if segment.position.z > playerNode.position.z + 5 {
floorSegments.remove(at: index)
segment.childNodes.forEach { (node) in
node.removeFromParentNode()
}
segment.removeFromParentNode()
}
}
scene.rootNode.addChildNode(lastSegmentClone)
}
}
}
func updatePositions() {
if let playerPhysicsBod = playerNode.physicsBody {
playerPhysicsBod.velocity.x = (lastXPosition - playerNode.position.x) * 8
playerPhysicsBod.velocity.z = -5
print("player velocity is \(playerNode.physicsBody!.velocity)")
}
}
func renderer(_ renderer: SCNSceneRenderer, updateAtTime time: TimeInterval) {
updatePositions()
updateSegments()
}
}
【问题讨论】:
-
不要删除并添加更多的clone(),这很慢。只需隐藏它们,然后在正确的位置取消隐藏。
-
还有 playerPhysicsBod.allowsResting = false 可能会有所帮助。
-
@E.Coms 感谢您的帮助,不幸的是,我已经在关闭 allowResting 的情况下进行了测试,并且根本没有添加任何克隆。很奇怪的东西
-
一种可能性是该位置远离原点。在您的场景中,您可以模拟另一种方式并使活动场景围绕原点发生。