2016-10-28 3 views
6

Es scheint, dass ich beim Ziehen von Texturen aus einem Texturatlas jetzt neue Texturen erzeuge anstatt dieselbe Textur über verschiedene Sprites mit iOS 10 zu verwenden. Auf iOS 9 funktioniert das wie erwartet. Hat noch jemand dieses Problem? Vielleicht gibt es einen Schritt, den ich verpasste, der jetzt ein Teil von iOS ist.SKTextureAtlas teilt Texturen in iOS 10 nicht mehr

Anmerkungen: Ich erstellte ein Beispielprojekt und erstellte einen neuen Atlas, dann schleppte ich einfach Raumschiff in @ 1x, ich habe auch versucht, vorzuladen, und das tat nichts so gut.

Code:

let atlas = SKTexturAtlas(named:"Sprites") 
    var texture = atlas.textureNamed("Spaceship") 
    print("\(Unmanaged.passUnretained(texture)),\(Unmanaged.passUnretained(texture).toOpaque())") 

    texture = atlas.textureNamed("Spaceship") 
    print("\(Unmanaged.passUnretained(texture)),\(Unmanaged.passUnretained(texture).toOpaque())") 

Edit: Um Fragen des Vergleichs zu erhalten, verwende ich die Beschreibung Eigenschaft zu vergleichen, wenn zwei Texturen gleich sind. Damit das funktioniert, können Sie nicht zwei Atlanten verwenden, die jeweils eine Textur mit exaktem Namen und Größe enthalten. Ich werde diese Situation nie treffen, aber für jeden, der da draußen nach Hilfe sucht, sollte man das im Hinterkopf behalten.

+1

Oh, interessante Frage, iOS10 hört nie in Erstaunen versetzen zu .. –

+0

Zwischen dies und das Erstellen von SkPhysicsBodies (Texturen) dauert 10x so lange sie mich wirklich über – Knight0fDragon

+0

schraubt Also, endlich ... BOOM! Das ist ein echter Fehler :-(... das lässt mich viel über die letzte Langsamkeit während meines Spiels (nach dem Spielen von 20 Levels) nur in iOS 10 nachdenken. –

Antwort

1

um dieses Problem zu bekommen, musste ich einen Weg kommen, die Texturen cachen, so dass es nicht zu einem doppelten hat:

private var textureCache = [String: SKTexture]() 
extension SKTextureAtlas 
{ 
    func texturesWithNames(_ names:[String]) -> [SKTexture] 
    { 
     var textures = [SKTexture]() 
     names.forEach({textures.append(textureNamed($0))}) 
     return textures 
    } 
    func cachedTextureWithName(_ name:String) -> SKTexture 
    { 
     if textureCache[name] == nil 
     { 

      textureCache[name] = textureNamed(name) 
     } 

     return textureCache[name]! 
    } 
    func cachedTexturesWithNames(_ names:[String]) -> [SKTexture] 
    { 
     var textures = [SKTexture]() 
     names.forEach({textures.append(cachedTextureWithName($0))}) 
     return textures 
    } 
    func clearCache() 
    { 
     textureCache = [String: SKTexture]() 
    } 
} 


extension SKTexture 
{ 

    var name : String 
    { 
     return self.description.slice(start: "'",to: "'")! 
    } 


} 
+0

Große Problemumgehung. Ich nehme an, dass man nach dem Erstellen/Erstellen einer Instanz von 'SKTextureAtlas'' cachedTexturesWithNames: 'mit dem Array von' textureNames' aus dem Atlas aufrufen müsste, um sie im Cache zu speichern, oder? – damirstuhec

+0

Ja, von hier an würden Sie nur cachedTexturesWithNames verwenden. Wenn Sie sks building verwenden möchten, müssen Sie SKSpriteNodes init überschreiben, um den Caching-Aufruf zu verarbeiten. – Knight0fDragon

+0

Ich habe die Erweiterung zur Verfügung gestellt, um den Namen von einer Textur zu bekommen, auch wenn Sie sie brauchen – Knight0fDragon

3

Ich habe den gleichen Test gemacht und bekomme die gleichen Ergebnisse.

Ich bin 100% sicher, aber nicht scheint, dass ein Vorschlag bei der Entwicklung von Swift 3 dort here war Unmanaged zu ändern UnsafePointer zu verwenden.

Aber wenn Sie versuchen, zu machen:

func address<T: AnyObject>(o: T) -> String{ 
    let addr = unsafeBitCast(o, to: Int.self) 
    return NSString(format: "%p", addr) as String 
} 

Nutzungs:

print(address(o: texture)) 

in iOS9 Sie korrekte Werte haben, in iOS10 falsche Ergebnisse.

enter image description here

Ich glaube, du hast recht, wir einen Fehler konfrontiert sind (eine andere ..)

+0

hmm das mag den Zeiger der Texturvariable greifen, nicht die Instanz es hält, wenn das Sinn macht.Make eine neue Textur namens texture2, und Sie werden sehen, die Adresse ändern um 4 Bytes – Knight0fDragon

+0

Ja, mein Fehler, ich habe Update-Code –

1

Ist eine unterschiedliche physikalische Adresse für eine Textur Verweis auf die „gleiche Textur“ wirklich ein Problem?

Ich habe das Standard-Beispielspiel-Projekt ausgeführt, aber Setup für Obj-C. Ich habe einen Texturatlas, der so etwas wie das Bild unten wäre. Beachten Sie jedoch, dass ich das durch TexturePacker ausgeführt habe. Der tatsächlich generierte Atlas von Xcode ist also anders.

enter image description here

ich tun, wie Sie gesagt haben und erstellt zwei Texturen mit dem gleichen Namen.

self.myTextureAtlas = [SKTextureAtlas atlasNamed:@"MyTexture"]; 
self.tex0 = [self.myTextureAtlas textureNamed:@"tex0"]; 
self.tex1 = [self.myTextureAtlas textureNamed:@"tex0"]; 

Wie Sie sagten, die Zeiger für tex0 und tex1 sind unterschiedlich. Zumindest gibt es Konsistenz zwischen Swift und Obj-C.

Allerdings glaube ich nicht, dass dies ein Problem/Bug ist. Was ich vermute, ist, dass sie die Implementierung so geändert haben, dass die zurückgegebene SKTexture eine neue "Instanz" ist, die zugrunde liegende Textur jedoch immer noch dieselbe ist.

Ich werde OpenGL sprechen, da das ist, was ich meine Motoren schreiben. Metall wird immer noch Ähnlichkeiten haben.Eine grundlegende Unterstruktur hat nur zwei wichtige Eigenschaften: einen Texturnamen (dies ist der OpenGL-Texturname) und UVs. Wenn Sie darüber nachdenken, was als die "Gleichheit" für die Übereinstimmung mit Equatable gilt, würde es höchstwahrscheinlich auf Gleichheit gegen diese 2 Punkte prüfen. Der Texturname ist der Name der Atlas-Textur, und die UVs sind die UVs innerhalb des Atlas, die den Bereich der bestimmten Sub-Textur darstellen.

Um diese Hypothese zu testen, habe ich eine GPU-Frame-Capture auf diesem durchgeführt. Mit Xcode 8 scheint das ziemlich fehlerhaft zu sein. Mit Metal ist es zu 100% abgestürzt. Ich habe es gezwungen, OpenGL zu verwenden, und habe es geschafft, eine Bildaufnahme zu bekommen. Wie erwartet, wenn ich mir alle Texturressourcen anschaue, sehe ich nur eine Textur für meinen Atlas.

enter image description here

Texture # 3 ist MyTexture.

Wenn ich die textureRect Dump, die die UVs zu sein scheinen, kann ich sehen, sie sind die gleichen:

Tex0 Rect 0,001618 0,793765 0,139159 0,203837

Tex1 Rect 0,001618 0,793765 0,139159 0,203837

Basierend darauf scheint es, dass beide self.tex0 und self.tex1, obwohl unterschiedliche physikalische Adressen, immer noch beide auf die gleiche Sub-Textur zeigen.

Beachten Sie, dass ich SpriteKit nicht mehr verwende. Mein aktueller Renderer verwendet Handles für Texturen, beim Abrufen können Sie jedoch Handle-Objekte mit unterschiedlichen physischen Adressen abrufen. Sie alle dereferenzieren immer noch auf die wahre Textur, da sie immer noch auf dieselbe zugrunde liegende Texturinstanz verweisen.

Ich denke, ich sehe nicht wirklich diff Zeiger ein Problem, vorausgesetzt, sie verweisen immer noch die gleiche zugrunde liegende Textur (dh. Nicht mehr Textur Speicher zugeordnet ist).

+0

Nicht mehr Textur Speicher zugeordnet werden kann, aber mehr physischen Speicher wird zugewiesen, und es wird zum Zeitpunkt des Aufrufs zugewiesen, was bedeutet, dass es jetzt länger dauert, es ist auch nicht mehr gleichsetzbar und hat jetzt einen neuen Hash-Wert für jede Instanz, so dass ich das SKTexture nicht mehr als Schlüssel verwenden kann Das ist ein Problem für mich, da ich irgendwie SKPhysicsBodies finden muss, die basierend auf der Textur erstellt wurden, weil SKPhysicsBody (Textur) jetzt 10x so lange dauert, da die Ladezeit für mein Spiel aufgebläht wurde 4 Sekunden dauert jetzt 90 Sekunden onds oder mehr (Andere Verlangsamungen gibt es auch) – Knight0fDragon

+1

Dies ist eine große Veränderung von iOS 9 – Knight0fDragon

+0

Das ist wirklich scheiße. Da ich nicht weiß, wie du Dinge machst, warum brauchst du eine Textur über den 'textureNamed' Aufruf? Wäre es möglich, dass Sie eine Texturmanager verwenden, um die Textur zu verkaufen, anstatt "texturNamed" zu verwenden? Wenn Sie das gleiche physikalisch adressierte 'SKTexture' haben, hat' SKPhysicsBody' noch immer negative Auswirkungen? –

Verwandte Themen