我现在正在开发一个游戏,在该游戏中,当触发时,我的自定义 spritenode 子类 FireAlarm 会执行一个功能,它会两次更改其纹理并生成一个“爆炸”节点。这非常有效,除了第一次在游戏中发生时,游戏会明显滞后。延迟的根源似乎是 FireAlarm 纹理的变化,我尝试了很多不同的方法来使用单例类和其他策略来预加载纹理,但似乎没有任何方法可以解决它。我觉得很奇怪,这只发生在第一次,然后似乎工作正常,是我遗漏了什么吗?
class FireAlarm: SKSpriteNode {
var isOccupied: Bool = false
var firstTexture = SKTexture(imageNamed: "fireAlarm")
var pulledTexture = SKTexture(imageNamed: "fireAlarmPulled")
var charredTexture = SKTexture(imageNamed: "fireAlarmCharred")
...
func occupy() {
print("occupying alarm")
isOccupied = true
let quickDelay = SKAction.wait(forDuration: 1.85)
let explosionAction = SKAction.run {
self.addExplosion()}
let sequence = SKAction.sequence([quickDelay, explosionAction])
self.run(sequence)
let delayAction = SKAction.wait(forDuration: 1.0)
let changeTexture1 = SKAction.run {
self.texture = self.pulledTexture}
let changeTexture2 = SKAction.run {
self.texture = self.charredTexture
}
let finalSequence = SKAction.sequence([delayAction, changeTexture1, delayAction, changeTexture2])
self.run(finalSequence){
self.isAlive = false
self.shadow.removeFromParent()
}
我尝试了很多不同的方法来使用单例类和其他策略来预加载纹理,但似乎没有什么可以解决它。
我看到你声明了纹理的一些实例属性
var firstTexture = SKTexture(imageNamed: "fireAlarm")
var pulledTexture = SKTexture(imageNamed: "fireAlarmPulled")
var charredTexture = SKTexture(imageNamed: "fireAlarmCharred")
但这不是纹理预加载。事实上,SKTexture(imageNamed:)
初始化程序仅创建一个引用,真正的图像加载和准备工作稍后完成。
新的纹理对象使用图像文件的名称进行初始化,然后控制立即返回到您的游戏。 Sprite Kit 在您的游戏需要时加载并准备纹理数据。
https://developer.apple.com/documentation/spritekit/sktexture/1520086-init
解决方案这是一个例子。
class GameScene: SKScene {
let textureAtlas = SKTextureAtlas(dictionary: [
"fireAlarm": UIImage(named: "fireAlarm")!, // Force unwrapping only for demonstration purposes.
"fireAlarmPulled": UIImage(named: "fireAlarmPulled")!,
"fireAlarmCharred": UIImage(named: "fireAlarmCharred")!
])
override func didMove(to view: SKView) {
textureAtlas.preload {
print("Now the textures are preloaded and you can start your game.")
}
}
}
请注意,textureAtlas.preload 方法是异步的。预加载完成后,就可以在游戏中使用了。
class FireAlarm: SKSpriteNode {
func occupy() {
guard let gameScene = self.scene as? GameScene else { fatalError() }
// ...
let changeTexture1 = SKAction.run {
self.texture = gameScene.textureAtlas.textureNamed("fireAlarmPulled")
}
let changeTexture2 = SKAction.run {
self.texture = gameScene.textureAtlas.textureNamed("fireAlarmCharred")
}
}
}
请告诉我这是否可以解决您的问题。