介绍SpriteKit场景时发生内存泄漏 [英] Memory leak when presenting SpriteKit scenes

查看:102
本文介绍了介绍SpriteKit场景时发生内存泄漏的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个SKScene,它是我的2D游戏的游戏世界.就像玩家可以探索的邻居.邻里到处都是房子.玩家可以自由进出房屋.当玩家进入房屋时,我呼叫skView.presentScene(newHouse)将房屋内部呈现为新场景.当玩家离开房屋时,我呼叫skView.presentScene(overworld)再次显示该邻居.玩家可能会进入&他们探索附近地区时,房屋多次退出.因此,邻居场景和房屋场景的新实例被多次展示.

I have an SKScene which is the overworld for my 2D game. It's like a neighborhood that the player can explore. The neighborhood is full of houses. Players can freely enter and exit houses. When the player enters a house, I call skView.presentScene(newHouse) to present the interior of the house as a new scene. When the player exits the house, I call skView.presentScene(overworld) to present the neighborhood again. The player is likely to enter & exit houses many times as they explore the neighborhood. Thus, the neighborhood scene and new instances of the house scene are presented many times.

问题在于,每次我呈现房屋场景时,内存中都会出现峰值.这是预期的,因为我们正在加载新房子场景.但是,当我退出房屋场景并返回到邻域场景时,内存使用量并没有减少.我已经通过反复进入和退出房屋进行了测试.每次我进入房屋时,内存使用量都会持续增加(〜2 MB).最终,内存使用量变得非常大,游戏开始丢帧(但仅在房屋场景中,而不在邻居场景中),并最终变得无法播放.

The problem is that each time I present a house scene, there is a spike in the memory. This is expected since we are loading a new house scene. But when I exit a house scene and return to the neighborhood scene, the amount of memory use does not go down. I've tested this by entering and then exiting houses over and over. The memory use climbs by a consistent amount (~2 MB) every time I enter a house. Eventually, the amount of memory use becomes very large and the game starts dropping frames (but only in the house scenes, not in the neighborhood scene) and eventually becomes unplayable.

使用SpriteKit时,我认为最佳实践是使用 presentScene 将玩家转移到游戏世界的完全不同的境界"(例如,不同的级别),这就是我在这里所做的.我还认为,在加载然后过渡到新场景时,您不应该采取任何措施来卸载"旧场景.实际上, SKView 文档没有任何方法可以清除旧版本中不需要的对象呈现新场景时的场景.我以为您应该信任操作系统来处理从内存中删除旧场景的对象的工作.这就是为什么我只介绍新场景而不用担心旧场景占用内存的原因.

When working with SpriteKit I thought that best practice is to use presentScene to transition the player to a substantially different "realm" of the game world (e.g. a different level), which is what I believe I am doing here. I also thought that you are not supposed to take any action to "unload" your old scene when you load and then transition to a new scene. Indeed, the SKView documentation does not have any methods for cleaning up unneeded objects from your old scene when you present a new scene. I thought that you are supposed to trust the OS to handle the job of removing the old scene's objects from memory. That is why I simply present new scenes and don't worry about old scenes taking up memory.

我在Instruments中分析了该应用程序,以检查是否存在内存泄漏(此时仪器仍然有点过头).我确实发现了一些看起来很小的内存泄漏,但是没有泄漏似乎直接导致每次我展示新房场景时都发生的大而一致的内存峰值.

I profiled the app in Instruments to check for memory leaks (Instruments is still a bit over my head at this point). I did find some memory leaks that looked very small, but no leaks that seemed to be directly causing the large and consistent memory spikes that are happening each time I present a new house scene.

我相信我会通过呈现新场景并让操作系统处理清理旧场景的方法来采取正确的方法.但是,也许我在我的应用程序设计中犯了一个错误,导致了此内存问题.当我呈现新房子场景时,我将一些信息从邻域场景传递到新房子场景.此信息与房屋外观(颜色,纹理,内容等)相关,这是必需的,因为房屋是按程序生成的:每座房屋都是唯一的.当我返回到邻域场景时,我将一些信息从房屋场景传递到了邻域场景.但是也许我在场景之间传递信息的方式无意间导致对象被保留在内存中.如果是这样,我该怎么做以确保不会发生这种情况?呈现新场景时,是否应该运行一些代码以清除内存中不需要的对象?

I believe I am taking the correct approach by presenting new scenes and letting the OS handle the job of cleaning up the old scenes. But maybe I am making a mistake in my app design that is causing this memory issue. When I present a new house scene, I pass some information from the neighborhood scene to the new house scene. This information is related to things like the appearance of the house (color, texture, contents, etc.) which is necessary because the houses are procedurally generated: each one is unique. And when I return to the neighborhood scene, I pass some information from the house scene to the neighborhood scene. But maybe the way that I am passing information between scenes is somehow unintentionally causing objects to be retained in memory. If so, what should I do to make sure that this does not happen? Is there some code I should run to clear the unwanted objects from memory when I present a new scene?

我确实注意到 SKScene 文档有几种与呈现场景有关的方法: sceneDidLoad()

I did notice that the SKScene documentation has several methods related to presenting a scene: sceneDidLoad(), willMove(from:), and didMove(to:). Which makes me wonder if I should be using these methods somehow to try and clear unneeded objects from memory when I transition between different scenes.

可能是我的应用程序体系结构很糟糕(它已经对我造成了其他问题).如果是这样,那么解决方案将是从全面改进我的应用程序架构开始.因此,基本上,我试图确定我的不良应用程序体系结构是否导致此内存膨胀问题,或者原因是否与SpriteKit和场景呈现方式有关.

It may be that my app architecture is simply bad (it's already causing other problems for me). If so, then the solution would be to start by overhauling my app architecture to improve it. So basically, I am trying to determine if my bad app architecture is causing this memory bloat problem, or if the cause is related to SpriteKit and the way that scenes are presented.

推荐答案

首先,您正确地介绍了SKScene,并且您是对的,您应该能够相信会清理掉旧的场景.我的意思是说,您无需执行任何其他操作即可将其释放.

First off you are presenting SKScene's correctly and you are correct you should be able to trust that the old scene will get cleaned up. By that I mean there is nothing else you need to do to make it release.

现在,您可以做一些事情来创建循环引用.希望其中一些检查可以帮助您找到答案.

Now with that being said there are things that you may have done to create a circular reference. Hopefully a couple of these checks will help you track it down.

我经常看到的第一个地方是您的播放器.如果您的场景具有播放器属性,而您的播放器具有场景属性,则这可能会阻止场景取消分配.播放器保持在场景上,场景保持在播放器上.我怀疑这是您的情况,但值得检查.

The first place I always look is at your player. If your scene has a player property and your player has a scene property this could prevent the scene from deallocating. Player holds on to the scene and scene holds on to player. I doubt this is your case but worth checking.

要看的第二个地方还有其他与该场景有关的参考或属性吗?一个常见的问题是当您创建自己的委托方法时.如果您的播放器执行了某个动作,然后将方法调用回该场景.玩家只应对该场景有较弱的引用.我自己做过,还看到其他人在创建自定义委托或协议并对其保持强引用而不是弱引用的情况下这样做.

Second place to look is there anything else that has a reference or property to that scene? A common issue is when you create your own delegate method. If your player does an action and then calls a method back to that scene. The player should only have weak references to that scene. I have done this myself and seen other do it where they create a custom delegate or protocol and keep a strong reference to it instead of weak.

在代码中称为自我"的任何地方都可以找到第三处.这在SKActions的运行块中很常见.您可能有一个在场景上调用方法的动作,并且在该SKAction的该场景上可能有一个属性.由于运行块,动作引用了场景,场景引用了动作.因此,寻找自我,看看那个物体是否是那个场景的一个属性.

Third place to look is anywhere in your code where you call self. This is common in run blocks of SKActions. You may have an action that calls a method on the scene and you may have a property on that scene of that SKAction. The action has reference to the scene due to the run block and the scene has a reference to the action. So look for self and see if that object is a property on that scene.

希望可以帮助您找到答案.我知道跟踪这样的泄漏可能是令人沮丧的,而这些是我过去见过的常见问题.

Hopefully that helps you track it down. I know it can be frustrating tracking a leak like this down and those are common issues I have seen in the past.

这篇关于介绍SpriteKit场景时发生内存泄漏的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆