SK Переходы от сцены к сцене медленные

Я пишу приложение OS X SpriteKit. Я перехожу из сцены главного меню в основную сцену, но для перехода требуется около 3 секунд. В моей основной сцене у меня есть экранное пианино, которое генерируется программно. Есть около 55 спрайтов, которые нужно загрузить. Есть ли способ ускорить это?

В моем основном SKScene LevelSceneэто то, что didMoveToView метод вызывает:

-(void)didMoveToView:(SKView *)view {
    _piano = [[Keyboard alloc] init]; //creates on screen piano keyboard
    [self addChild:_piano]; 
    [_piano setPosition:[[self childNodeWithName:@"piano"] position]];
    [_piano setAnchorPoint:CGPointMake(1, 0)];

    _midiController = [[MIDIController alloc] initWithAudio:YES];

    [self initGameStateMachine];
    [self initLevel]; //this involves loading a couple more sprites onto the screen
}

1 ответ

Решение

Загрузите все свои текстуры один раз и сохраните ссылку на них. Вы можете хранить все свои текстуры в общем массиве или словаре. На самом деле вы можете создать класс для управления этим. Таким образом, все ваши текстуры будут уже загружены в память, поэтому создание узлов должно быть намного быстрее, что приведет к быстрому переходу сцены.

Также есть ошибка в Yosemite, загрузка спрайта по имени из атласа занимает очень много времени (и фактически останавливает игру), когда текстура является частью атласа. Я предполагаю, что это ошибка, связанная с неэффективным поиском пути к атласу. Ручная загрузка из атласа - это обходной путь. Не уверен, что эта ошибка влияет на вас, но я думаю, что я все равно упоминаю об этом. Несмотря на это, выполнение того, что я сказал выше, должно решить вашу проблему.


Обновите, чтобы ответить, чтобы включить код:
Я написал очень быстрый код, чтобы показать вам, что я имею в виду под загрузкой и выгрузкой ресурсов. В этом примере у нас есть одноэлементный класс SharedAssetsManager, который отвечает за загрузку и выгрузку ваших ресурсов из памяти. По соображениям производительности рекомендуется хранить все свои текстуры в атласе. Если у вас есть текстуры, которых нет (которые я включил в пример кода), вы можете увидеть, что их нужно добавить в словарь вручную (хотя, возможно, вы могли бы найти более быстрое решение, такое как группировка файлов или использование plist). описать названия изображений). В приведенном ниже коде вы можете увидеть пример загрузки ресурсов, а затем выгрузки их. Если ваша игра достаточно мала, вы можете загрузить их один раз в AppDelegate или в другой эквивалентной области, но если ваша игра слишком большая, вам нужно будет динамически загружать сцены между собой, возможно, с загрузочным экраном, пример которого вы можете увидеть здесь: Наконец, Вы можете видеть, что я использую константы для ссылки на имена файлов вместо их жесткого кодирования. Вы не должны делать это для анимации кадров спрайтов, таких как Walk_0,Walk1_1,Walk_2 и т. Д. Вместо этого вы можете придумать другой класс для управления анимацией. Надеюсь, этот код станет хорошей отправной точкой.

import SpriteKit

struct FileNameConstants {
    static let LEVEL1_ATLAS = "Level1_Atlas"
    static let SOME_TEXTURE1 = "Some_Texture_In_Atlas"
    static let SOME_TEXTURE2 = "Some_Texture_Not_In_Atlas"
}

class SharedAssetsManager {
    static let sharedInstance = SharedAssetsManager()

    //Keep these private for safety.
    private init() {}
    private(set) var level1Assets: [String : SKTexture]!

    func getAssetsDictionaryFromAtlasNamed(atlasNamed: String) -> [String : SKTexture] {
        let atlas = SKTextureAtlas(named: atlasNamed)
        var textures: [String : SKTexture] = Dictionary(minimumCapacity: atlas.textureNames.count)
        for textureName in atlas.textureNames as [String] {
            textures[textureName.stringByDeletingPathExtension] = atlas.textureNamed(textureName)
        }
        return textures
    }

    func loadLevel1Assets() {
        level1Assets = getAssetsDictionaryFromAtlasNamed(FileNameConstants.LEVEL1_ATLAS)
        //Textures that are not part of the atlas but should be part of level1 assets can be added here:
        level1Assets[FileNameConstants.SOME_TEXTURE2] = SKTexture(imageNamed: FileNameConstants.SOME_TEXTURE2)

    }
    func unloadLevel1Assets() {
        level1Assets = nil
    }
}

//When loading level 1:
let sam = SharedAssetsManager.sharedInstance
sam.loadLevel1Assets()

//When assigning textures:
let someNode1 = SKSpriteNode(texture: sam.level1Assets[FileNameConstants.SOME_TEXTURE1]!)
let someNode2 = SKSpriteNode(texture: sam.level1Assets[FileNameConstants.SOME_TEXTURE2]!)

//When cleaning up (if needed).
sam.unloadLevel1Assets()
Другие вопросы по тегам