Scene Kit Performance mit Würfeltest
eim Erlernen der 3D-Grafikprogrammierung für Spiele entschied ich mich für den einfachen Einstieg mit der Scene Kit 3D-API. Mein erstes Spielziel war es, eine sehr vereinfachte Nachahmung von MineCraft zu erstellen. Ein Spiel mit nur Würfeln - wie schwer kann es sein.
Below ist eine Schleife, die ich geschrieben habe, um eine Fahrt mit 100 x 100 Würfeln (10.000) zu platzieren, und die FPS-Leistung war miserabel (~ 20 FPS). Ist mein ursprüngliches Spielziel für das Scene Kit zu hoch oder gibt es einen besseren Weg, dies zu erreichen?
Ich habe andere Themen zu StackExchange gelesen, habe jedoch nicht das Gefühl, dass sie meine Frage beantworten. Das Konvertieren der freiliegenden Flächenblöcke in ein einzelnes Netz funktioniert nicht, da die SCNGeometry unveränderlich ist.
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)
}
UPDATE 12-30-2014: Ich habe den Code so geändert, dass der SCNBoxNode einmal erstellt wird, und dann wird jedes zusätzliche Feld im Array von 100 x 100 über Folgendes erstellt:
var newBoxNode = firstBoxNode.clone()
newBoxNode.position = SCNVector3Make(x, y, z)
Diese Änderung scheint die FPS auf ~ 30 fps erhöht zu haben. Die anderen Statistiken lauten wie folgt (aus den in SCNView angezeigten Statistiken):
10K (Ich nehme an, dies sind Draw Calls?) 120K (Ich nehme an, dies sind Faces) 360K (Angenommen, dies ist die Vertexanzahl)
Der Großteil der Run-Schleife befindet sich im Rendern (ich schätze 98%). Die Gesamtschleifenzeit beträgt 26,7 ms (autsch). Ich arbeite auf einem Mac Pro Late 2013 (6-Core mit Dual D500-GPU).
Angesichts der Tatsache, dass ein Spiel im MineCraft-Stil eine Landschaft hat, die sich basierend auf den Aktionen des Spielers ständig ändert, sehe ich nicht, wie ich dies innerhalb der Grenzen von Scene Kit optimieren kann. Eine große Enttäuschung, da ich den Rahmen wirklich mag. Ich würde gerne die Ideen von jemandem hören, wie ich dieses Problem angehen kann - ohne das bin ich gezwungen, mich für OpenGL zu entscheiden.
UPDATE 12-30-2014 @ 2:00 Uhr ET: Ich sehe eine signifikante Leistungsverbesserung bei der Verwendung von flattenedClone (). Die FPS beträgt jetzt solide 60 fps, auch bei mehr Boxen und ZWEI Zeichenaufrufen. Die Anpassung an eine dynamische Umgebung (wie von MineCraft unterstützt) erweist sich jedoch weiterhin als problematisch - siehe unten.
Da das Array die Zusammensetzung im Laufe der Zeit ändern würde, habe ich einen keyDown-Handler hinzugefügt, um dem vorhandenen ein noch größeres Box-Array hinzuzufügen, und den zeitlichen Unterschied zwischen dem Hinzufügen des Arrays von Boxen, der zu weitaus mehr Aufrufen führt, und dem Hinzufügen eines abgeflachten Klons. Folgendes habe ich gefunden:
Auf keyDown füge ich ein weiteres Array von 120 x 120 Boxen (14.400 Boxen) hinzu.
// This took .0070333 milliseconds
scene?.rootNode.addChildNode(boxArrayNode)
// This took .02896785 milliseconds
scene?.rootNode.addChildNode(boxArrayNode.flattenedClone())
Das erneute Aufrufen von flattenedClone () ist 4x langsamer als das Hinzufügen des Arrays.
Dies führt zu zwei Zeichenaufrufen mit 293.000 Teilflächen und 878.000 Eckpunkten. Ich spiele immer noch damit und werde es aktualisieren, wenn ich etwas Neues finde. Fazit: Mit meinen zusätzlichen Tests habe ich immer noch das Gefühl, dass die unveränderlichen geometrischen Einschränkungen von Scene Kit bedeuten, dass ich das Framework nicht nutzen kann.