我正在编写OS X SpriteKit应用程序。我正在从主菜单场景转换到主场景,但转换大约需要3秒钟才能启动。在我的主场景中,我有一个以编程方式生成的屏幕钢琴。有大约55个精灵需要加载。有什么方法可以加快速度吗?
在我的主要SKScene 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
}
方法调用的内容:
npm config set prefix
答案 0 :(得分:2)
加载所有纹理一次并保留对它们的引用。您可以将所有纹理存储在共享数组或字典中。实际上,您可以创建一个类来管理它。这样,所有纹理都已经加载到内存中,因此创建节点应该更快,这将导致快速的场景转换。
Yosemite也有一个错误,当纹理是地图集的一部分时,从地图集中按名称加载精灵需要很长时间(实际上会使游戏失速)。我猜这是一个与低效搜索地图集路径有关的错误。从地图集手动加载是一种解决方法。不确定这个bug是否会影响你,但我想我还是提到了它。无论如何,做我上面所说的应该解决你的问题。
更新以回答包含代码:
我快速写了一些代码,通过加载和卸载资产向您展示我的意思。在这个例子中,我们有一个单例类,SharedAssetsManager,负责从内存中加载和卸载资产。出于性能原因,尽可能将所有纹理保留在图集中是最佳做法。如果你有一些纹理不是(我在示例代码中包含),你可以看到它必须手动添加到字典中(尽管你可能想出一个更快的解决方案,如分组文件或使用用于描述图像名称的plist。在下面的代码中,您可以看到加载资产然后卸载它们的示例。如果您的游戏足够小,您可以在AppDelegate或某个等效区域中加载一次,但如果您的游戏太大,您将需要在加载屏幕之间动态加载场景,您可以看到{{3}的示例最后,你可以看到我使用常量引用文件名而不是硬编码。您不应该为精灵帧动画执行此操作,例如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()