Unity3d卸载未使用的资源

来源:互联网 发布:淘宝网注册账号 编辑:程序博客网 时间:2024/06/05 15:59

通常在变换场景后,上个场景中除了使用 DontDestroyOnLoad() 保留的物件,将会被释放掉,但如果在没有变换场景的情形下,想把未使用的资源卸载掉,该如何做呢?

一般情况下,我们会利用 Unity 的编辑器来部属每个关卡或场景中的物件,这些物件在载入场景后都是必要的,也不太会持续增加物件数,在关卡结束后即转换到下个场景,所以原本场景中的物件 将不再需要,所以 Unity 将会自动将前一场景的物件都销毁掉,所以我们通常不太需要去管理记忆体的使用或是否释放,但如果你的游戏全部是在单一个场景中运行的,那麼物件的產生、销 毁、释放资源等等的动作就变得格外重要。

我做了一个宝石类型的游戏,画面上除了 GUI 及背景外就只有宝石,所以我事先将宝石做成 Prefabs ,在需要时利用 Instantiate() 產生,我在不同的关卡利用 renderer.material.mainTexture 变更背景图,利用 GetComponent(MeshFilter).sharedMesh 变更宝石的形状以及利用 renderer.material.color 变更宝石顏色,如此一个Prefabs 可以重复无限使用,所以在游戏场景中只设置了简单几个场景物件,在这种场景不需要变化太多的情况下,每个关卡都换场景重新配置一样的物件似乎有点多餘,所 以这个游戏便只有一个场景,在需要时產生宝石,然后再视情况使用 Destroy() 销毁掉,这样看起来只要在產生宝石时控制画面上的物件数量,那麼也就不用担心记忆体使用过量或没释放掉的问题。

但是,这个游戏在连续玩好几个关卡后,也就是连续玩一段时间后,会发生停顿或画面变慢的问题,游戏刚开始玩时是相当顺畅的,但长时间执行将使效能降低,直 觉上的判断应该是记忆体累积到一定程度造成的,每个物件在不使用时都使用 Destroy() 销毁掉,那麼,堆积的记忆体是从哪裡来的呢?
打开 Profiler 视窗看看,会发现其中的 Memory 的 Total Object Count 数值,不断的增减变化,但随着时间的增加会慢慢的往上累积,查看官网 (http://unity3d.com/support/documentation/Manual/Profiler.html) 是这样说的 “If this number rises over time then it means your game is creating some objects that are never destroyed.”,有些物件未销燬,很奇怪吧!都有使用 Destroy(),那為何还有未销毁的物件?其实,主要是因為我这裡有对 renderer.material 设置改变其内容,在这个执行时期并不会真的去改变 Project 中的 material,而是產生这个物件实例(instance) 的材质实例以供该物件使用,所以如果只是 Destroy(gameObject) 的话,将会残留部份物件数,每个產生的物件都残留一点点的话,慢慢的长时间下来将会累积相当多,记忆体将会不敷使用,所以在 Destroy(gameObject) 的同时,应该也要 Destroy(renderer.material) 才行。

如果程式结构简单,给物件使用的 Script 档案也不多的话,也许多加一句并不困难,但我们有时候无法确定是否有在适当时机為每个物件做到完整的销毁,也许还有残留别的东西也会有这种情形持续累积记 忆体,这时又该寻找更简单统一的方法了,於是我们可以在每个关卡开始前或结束时执行一句 Resources.UnloadUnusedAssets() ,让 Unity 自行去卸载掉不使用的资源,如此在平时物件销毁时,我们已经先行释放掉大部份不使用的资源,然后再由 Resources.UnloadUnusedAssets() 卸载我们未清理掉的部份,如此的话查看 Profiler 视窗的 Memory 的 Total Object Count 数值就可以维持在一定范围内起伏,而不再随着时间增加,当然我们在关卡设置上都会有难度上的差异,在某些关卡裡,玩家可能必须花较多时间才能完成关卡,所 以如果我们只在关卡开始或结束时使用 Resources.UnloadUnusedAssets() 也许会不够,此时也可另外定义每过一段时间就执行 Resources.UnloadUnusedAssets() ,如此将可避免掉系统资源不足的问题。



来处:http://www.comedreams.com/index.php/archives/41105

原创粉丝点击