在学习3D游戏图形编程时,我决定通过使用Scene Kit 3D API来开始简单的尝试。我的第一个游戏目标是构建一个非常简化版的Minecraft。只有方块的游戏-这有多难呢。
下面是我编写的循环,用于放置100 x 100个方块(10,000),但FPS性能非常糟糕(约20 FPS)。我的初始游戏目标对于Scene Kit 来说太过于艰难了,还是有更好的方法来解决这个问题吗?
我已经阅读了 StackExchange 上的其他主题,但觉得它们没有回答我的问题。将暴露表面块转换为单个网格不起作用,因为SCNGeometry是不可变的。
func createBoxArray(scene : SCNScene, lengthCount: Int, depthCount: Int) {
let startX : CGFloat = -(CGFloat(lengthCount) * CUBE_SIZE) + (CGFloat(lengthCount) * CUBE_MARGIN) / 2.0
let startY : CGFloat = 0.0
let startZ : CGFloat = -(CGFloat(lengthCount) * CUBE_SIZE) + (CGFloat(lengthCount) * CUBE_MARGIN) / 2.0
var currentZ : CGFloat = startZ
for z in 0 ..< depthCount {
currentZ += CUBE_SIZE + CUBE_MARGIN
var currentX = startX
for x in 0 ..< lengthCount {
currentX += CUBE_SIZE + CUBE_MARGIN
createBox(scene, x: currentX, y: startY, z: currentZ)
}
}
}
func createBox(scene : SCNScene, x: CGFloat, y: CGFloat, z: CGFloat) {
var box = SCNBox(width: CUBE_SIZE, height: CUBE_SIZE, length: CUBE_SIZE, chamferRadius: 0.0)
box.firstMaterial?.diffuse.contents = NSColor.purpleColor()
var boxNode = SCNNode(geometry: box)
boxNode.position = SCNVector3Make(x, y, z)
scene.rootNode.addChildNode(boxNode)
}
更新时间:2014年12月30日 我修改了代码,现在SCNBoxNode只创建一次,然后通过数组中的每个附加盒子来创建100 x 100。
var newBoxNode = firstBoxNode.clone()
newBoxNode.position = SCNVector3Make(x, y, z)
这个更改似乎将FPS增加到了约30fps。其他统计数据如下(从SCNView显示的统计数据):
10K(我认为这是绘制调用?) 120K(我认为这是面数) 360K(假设这是顶点数)
大部分运行循环在渲染中(我估计有98%)。总循环时间为26.7毫秒(糟糕)。我正在Mac Pro Late 2013上运行(带有双D500 GPU的6核)。
考虑到像MineCraft风格的游戏会根据玩家的操作不断变化,我不知道如何在Scene Kit的限制内进行优化。这让我非常失望,因为我真的很喜欢这个框架。我很想听听别人对如何解决这个问题的想法-如果没有,我就不得不使用OpenGL。
更新12-30-2014 @ 2:00pm ET: 当使用flattenedClone()时,我看到了显着的性能提升。即使有更多的方块和两个绘图调用,FPS现在仍稳定在60fps。但是,适应动态环境(如MineCraft所支持的)仍然存在问题-请见下文。
由于数组会随时间而改变组成,因此我添加了一个keyDown处理程序来向现有的数组中添加一个更大的框数组,并计算添加框数组与添加flattenedClone之间的时间差异。这是我发现的:
在keyDown上,我添加另一个120 x 120方块(14,400个方块)的数组
// This took .0070333 milliseconds
scene?.rootNode.addChildNode(boxArrayNode)
// This took .02896785 milliseconds
scene?.rootNode.addChildNode(boxArrayNode.flattenedClone())
再次调用flattenedClone()的速度比添加数组慢4倍。
这导致两个绘图调用具有293K个面和878K个顶点。我仍在进行测试,如果发现任何新情况将进行更新。总之,通过我的额外测试,我仍然觉得Scene Kit的不可变几何约束意味着我无法利用该框架。
flattenedClone()
),您可以大大减少绘制调用的数量。如果一个盒子稍后应该由用户的操作分离,我会在那个动作时处理该盒子,而不是让整个场景处于分离状态,仅因为用户可能与它交互。 - David Rönnqvistobjc [88539]:__weak变量位于0x6000037d0f30,而不是0x6000032db180。 这可能是对objc_storeWeak()和objc_loadWeak()的不正确使用。 在objc_weak_error上断点进行调试。
当使用flattenedClone()
? 我正在面临这个问题。 没有展平,控制台中没有错误:( - piotr_ch