呈现 SpriteKit 场景时出现内存泄漏 [英] Memory leak when presenting SpriteKit scenes

查看:28
本文介绍了呈现 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 中分析了应用程序以检查内存泄漏(在这一点上,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(), willMove(from:)didMove(to:).这让我想知道,当我在不同场景之间转换时,是否应该以某种方式使用这些方法来尝试从内存中清除不需要的对象.

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.

第三个查看位置是代码中您调用 self 的任何位置.这在 SKAction 的运行块中很常见.您可能有一个在场景中调用方法的动作,并且您可能在该 SKAction 的那个场景上有一个属性.由于运行块,动作具有对场景的引用,并且场景具有对动作的引用.因此,查找 self 并查看该对象是否是该场景中的属性.

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天全站免登陆