Unity3d使用内存:加载和卸载预制件

mad*_*mik 6 memory assets unity-game-engine ios

我真的需要帮助!我无法理解如何使用预制件和卸载.

我有下一个情况.

我在Xcode上运行我的应用程序.Unity版本4.3.1 Pro.使用以下内容观察内存:Xcode Debug Navigator Xcode Instruments Unity Profiler

我接下来的步骤:

0)Unity从Empty场景开始.

使用的内存XCODE Debug Navigator:11 mb仪器:26.4 mb Unity Profiler:使用总计13.2保留总计13.7

1)从Resources文件夹加载预制件

prefab = Resources.Load("Room1"); 
Run Code Online (Sandbox Code Playgroud)

使用的内存XCODE Debug Navigator:30.8 mb仪器:49.54 mb Unity Profiler:总共使用19.8保留总计20.4

2)实例化预制件

go = (GameObject)Instantiate(prefab); 
go.name = "Room1"; 
Run Code Online (Sandbox Code Playgroud)

XCODE Debug Navigator:31.2 mb仪器:50 mb Unity Profiler:总共20个预留总数20.7

3)销毁场景中的所有对象 - 内存未更改

Transform[] tr = FindObjectsOfType<Transform>(); 
for (int i = 0; i < tr.Length; i++) 
{ 
    GameObject goo = tr.gameObject; 
    if (goo.name != "Main Camera") 
    {
        Destroy(goo); 
        goo = null;
    } 
} 
Run Code Online (Sandbox Code Playgroud)

XCODE Debug Navigator:31.1 mb仪器:49.93 mb Unity Profiler:总共19.8保留总计20.4

4)呼叫Resources.UnloadUnusedAssets();- 内存未更改

5)呼叫System.GC.Collect();- 内存未更改

6)调用UnloadAsset of prefab Resources.UnloadAsset(prefab);- 内存未更改

7)呼叫Resources.UnloadUnusedAssets();- 内存部分清理

XCODE Debug Navigator:21.9 mb仪器:40.79 mb Unity Profiler:总共13.2保留总计13.9

在我看到的剖析器中,删除了预制件中使用的所有纹理

8)System.GC.Collect();- 记忆没有改变

9)加载空场景 - 内存未更改

这是另一个有趣的时刻:

当应用程序进入后台并启动另一个应用程序时,使用的RAM的大小会大大减少,当我调用统一应用程序时 - 内存会变为第一个大小的空白场景.

我有下一个问题:

1)为什么在删除预制件后没有完全清理内存并调用UnloadUnusedAssets - 我们可以在Instruments和Xcode中看到它 - 但在Profiler中我们看到,该内存几乎完全免费?

2)清理内存到初始大小是真的吗?

3)我是一切正确还是我做错了什么?

你可以在这里下载测试项目:http: //gfile.ru/aa5on

非常感谢您的回复.

Ser*_*sch 8

前言

你知道RAM的使用情况很好.但是,问题是:到目前为止,您是否遇到过内存使用方面的任何问题?如果没有,那么你所做的是为时过早.

一些想法

以下是您需要考虑的一些想法:

  1. 重要文章:http://docs.unity3d.com/Manual/MobileProfiling.html
  2. 有Unity内存和单声道内存.Mono永远不会回放操作系统内存:

    一旦分配了一定量的内存,它就会保留为单声道,而不适用于操作系统.即使你发布它,它也只能在内部用于Mono,而不能用于操作系统.Profiler中的堆内存值只会增加,永不减少.

  3. 预制件和游戏对象只是一大堆链接,因此它们没有资源那么大的内存占用.
  4. Object.Destroy 不会立即破坏对象:

    实际对象破坏始终延迟到当前Update循环之后,但始终在渲染之前完成.

  5. Resources.UnloadUnusedAssets是异步的.它不会立即卸载所有内容.
  6. 在Unity的文档中没有提到Resources.UnloadAsset(Object assetToUnload)将卸载引用的资源assetToUnload.

说明

我不能称自己是内存管理(Unity和Mono)的专家.但这是我如何理解正在发生的事情:

  1. 1)从Resources文件夹加载预制件

    Prefab加载了它引用的所有资源.内存使用量增加.一切都很清楚了.

  2. 2)实例化预制件

    内存使用量增加了一点,以保持预制克隆.

  3. 3)销毁场景中的所有对象 - 内存未更改

    这里有趣的事情:)实际上,根据Unity的分析器,内存使用情况发生了变化:它与预制实例化之前的情况相同.因此,看起来Unity发布了与预制实例直接相关的内容.但是,正如所说的那样,单声道不会将内存返回给操作系统(即使它确实也没有时间这样做).

  4. 4)调用Resources.UnloadUnusedAssets(); - 记忆未改变

    Resources.UnloadUnusedAssets 无法在这里卸载任何东西,因为仍然没有未使用的资产:虽然对象被标记为销毁,但实际的垃圾收集还没有发生.

  5. 5)调用System.GC.Collect(); - 记忆未改变.

    这是因为它的内存由mono管理.

  6. 6)调用UnloadAsset预制的Resources.UnloadAsset(prefab);

    我相信这里的内存使用率有所下降(100K-200K左右),但你没有注意到它.但是,正如我上面提到的,UnloadAsset不会卸载作为参数传递的对象引用的资源UnloadAsset.

  7. 7)调用Resources.UnloadUnusedAssets(); - 记忆部分清洁

    在步骤5中,您已调用GC.Collect(),已发生集合,现在某些Unity资产没有对它们的引用.因此,它们最终可以被释放.这就是记忆被释放的原因.

  8. 8)System.GC.Collect(); - 记忆未改变

    以上解释

  9. 9)加载空场景 - 内存未更改

    一切可以被释放的东西已经被释放了.因此内存使用没有变化.

  • 我懂了。这里首先要关注的是尝试减少纹理的内存使用量。你使用纹理压缩吗?是否可以在不损失质量的情况下缩小一些纹理?然后,您需要在暂停 Unity 播放器之前卸载尽可能多的资源。您可以尝试在加载的每个资源(主要是纹理)上调用 Resource.UnloadAsset(我从未尝试过,但应该可以),或者您可以加载一些空白的“暂停”场景并调用 Resources.UnloadUnusedAssets。 (2认同)