问题描述
好一会儿,我在测试中发生了一次随机崩溃,没有错误,而且我也不知道为什么.因此,我开始分析事物,并得出了以下数据.
Ok so awhile back in testing I had a random crash with no error, and I have no clue why. So i went into analyze things and I came up with the following data.
似乎我的内存使用率越来越高,直到达到了末日.请注意,在开始时,总曲率的斜率如何变大,然后再变大. (您可能会注意到,这是我第一次进行此类事情的分析.)
As it would appear my memory usage is getting higher and higher and higher until it sorta plateus. Notice how at the beginning the slope of the general curvature is greater then later on. (as you might notice this is my first time going in and analyzing this sort of thing).
现在游戏中发生的基本上是两个屏幕.1.菜单:此屏幕上有很多纹理,但除了具有可玩游戏的按钮外,什么也不做2.游戏:因为它是实际的游戏,所以它具有TOOONS的纹理,并且具有大量的CPU使用率.3.死亡:此屏幕上有一项资产,它是一个按钮,您可以通过它重玩游戏.这不应该使用太多内存或cpu.但是它仍然有内存.对我来说,无论内存泄漏"是什么,这种尖叫一直在发生.
Now what happens in the game is that basically their are two screens.1. Menu: this screen has quite a few textures but does nothing except has button to play game2. Game: this has TOOONS of textures and has the bulk of the cpu usage because its the actual game.3. Death: This screen has one asset, and it is a button that allows you to replay the game. This should not be using much memory OR cpu. However it still has memory. To me this screams whatever a "memory leak" is, is going on.
如果您基本上会看一下图表,则开始菜单时游戏正在发生什么,而第一个峰值是加载实际游戏,那么我就死了.然后从那时开始,我在游戏"和死亡"屏幕之间切换,每个尖峰信号都表示正在加载游戏场景.
If you will look at the chart basically what was going on in the game was the menu started, and the first spike was loading up the actual game, then I died. Then from then on I was switching between the Game and Death screens, each spike signals the Game scene being loaded.
如果这些数据是我预测的方式,那么您会在死机屏幕上非常小的内存使用与游戏内存使用之间的回荡之间发生振荡.
If this data were the way I would predict it you would se an oscillation between a very small memory use for the death screen, and then a return to a game memory usage.
故事的寓意是,我很确定切换场景后sprite工具包不能正确清理,我需要知道为什么.
Moral of the story is I am pretty sure that sprite kit isn't properly cleaning up after switching scenes and I need to know why if possible.
为了切换场景我正在使用maxkargin制作的方法详细此处
Btw in order to switch scenes I am using the method made by maxkargin detailedhere
顺便说一句,我正在迅速使用Sprite Kit,SKScenes和SKSpriteNodes
BTW I am working in swift with sprite kit and SKScenes, and SKSpriteNodes
非常感谢!
推荐答案
原因有很多,我的游戏也遇到类似的问题.如果操作正确,则无需删除诸如纹理之类的东西.在每个场景更改时都删除纹理也不是理想的选择,您想将它们保留在内存中以提高性能,这样就不必每次都重新加载它们.
There is a few reasons why this is, I had a similar problem with my games. If you do it correctly there is no need to remove stuff such as textures. Removing textures on every scene changes is also not ideal, you want to keep them in memory for performance so they do not have to be reloaded each time.
这是一个基本清单,您可以用来查看是否造成内存泄漏.
Here is a basic checklist you can use to see if you create a memory leak.
1)将带有打印语句的deinit方法添加到每个场景/类.如果调用deinit,则您的场景已正确释放.
1) Add the deinit method with a print statement to each scene/class. If deinit gets called your scene deallocated correctly.
deinit {
print("Deinit GameScene")
}
2)您是否通过在2个类之间创建引用来在某个地方创建强大的引用周期?
2) Are you creating strong reference cycles somewhere by creating references between 2 classes?
强大参考周期的经典苹果示例
The classic Apple example of a strong reference cycle
class Person {
var dog: Dog?
}
class Dog {
var person: Person?
}
要解决此问题,您必须将这2个属性中的1个设为弱
To fix it you would have to make 1 of those 2 properties weak
class Person {
var dog: Dog?
}
class Dog {
weak var person: Person?
}
对于可选选项的一种很好的做法是在不再需要它们时将它们设置为nil.
Also good practice with optionals is to set them to nil when they are no longer needed.
person = nil
也许可以查看google和Apple Swift文档以了解如何处理此问题.不久前我也问过类似的问题
Maybe check google and the Apple Swift documentation on how to deal with this. I also asked a similar question a while back
3)您正在使用闭包吗?它们可能导致内存泄漏.
3) Are you using closures? They can cause memory leaks.
SpriteKit中最常见的情况是这两个示例,它们可能/将导致内存泄漏,并使您的场景无法释放. (动作2是一个捕获自我的闭包)
A more common scenario in SpriteKit is these 2 examples which could/will cause a memory leak and makes your scene to not deallocate. (action 2 is a closure which captures self)
// Example 1
let action1 = SKAction.wait(forDuration: 1)
let action2 = SKAction.run(someMethod)
let sequence = SKAction.sequence([action1, action2])
run(SKAction.repeatForever(sequence))
// Example 2
let action1 = SKAction.wait(forDuration: 1)
let action2 = SKAction.run {
self.someMethod()
}
let sequence = SKAction.sequence([action1, action2])
run(SKAction.repeatForever(sequence))
一个好的经验法则是,当编译器强迫您使用self时,最有可能在不使用weak/unowned的情况下造成内存泄漏.
A good rule of thumb is that when the compiler forces you to use self than you most likely will create a memory leak without using weak/unowned.
因此,要修复上述2个SKAction示例,您可以确保在更改场景时始终删除所有操作,或者甚至最好将IMO更改为此代码,以免首先造成内存泄漏.
So to fix the above 2 SKAction examples you could either make sure you always remove all actions when you change scenes or IMO even better would be to change your code to this to avoid creating a memory leak in the first place.
let action1 = SKAction.wait(forDuration: 1)
let action2 = SKAction.run { [weak self] in
self?.someClassMethod()
}
let sequence = SKAction.sequence([action1, action2])
run(SKAction.repeatForever(sequence))
请注意,在上述所有示例中,您还可以编写
Note in all those above example you could also write
.... { [unowned self] in
,那么您将不需要使用?在关闭中
and than you would not need to use the ? in the closure
self.someMethod()
当您使用无所有权时,您基本上会说self永远不会为nil,如果在调用闭包时实际上为nil,则可能导致崩溃.如果使用弱self,则告诉编译器self在调用闭包之前可能变为nil,因此self是避免崩溃的可选方法.
When you use unowned you basically say self will never be nil which could cause a crash if it is actually nil when the closure is called. If you use weak self you tell the compiler self might become nil before the closure is called therefore self is an optional to avoid the crash.
为了避免这种情况,我认为使用弱"而不是无主"几乎总是更好的选择.在我的其中一款游戏中,我在一个封闭的容器中使用了无主的自我,当它从iTunes中获取StoreKit产品时,这个容器就被称为.这导致了我的崩溃,因为我可以在调用闭包之前退出SKScene.如果您使用弱自我,则不会因为使用可选项而崩溃.
I think it is almost always better to use "weak" instead of "unowned" to avoid this. In one of my games I was using unowned self in a closure that was called when it fetched StoreKit products from iTunes. This caused me subtile crashes because I could exit the SKScene before the closure was called. If you use weak self you will not crash because you use optionals.
希望这会有所帮助
这篇关于在场景之间切换时出现内存问题SpriteKit的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!