【问题标题】:How to Properly Manage Memory in UnityUnity中如何正确管理内存
【发布时间】:2019-12-05 22:28:25
【问题描述】:

我有一个相当麻烦的记忆问题。我正在使用名为 Memory Profiler 的软件包来帮助我尝试找出问题所在,但我不确定我是否理解正确。基本上,我在运行时从文件加载地图,当我在实际构建中加载它时,我从 Memory Profiler 获得了大约 1.2 GB 的内存快照文件。但是当我使用相同的代码在一个新的空项目中加载相同的地图时,快照文件大约为 230 MB。我检查了额外的内存是否来自项目中的其他内容,但如果我在加载地图之前进行内存快照,快照文件只有 90 MB 大。从我在内存映射视图中可以看到,看起来额外的数量是我认为对象之间的未使用空间(我不确定,我不太了解这些术语)。所以我的问题是,如果是这样的话,我怎样才能避免这种情况发生。这不是问题,但加载较大的地图会导致崩溃。

作为参考,以下是内存分析器快照的一些图像:

主项目树图

新建项目树图

主项目内存映射

新项目内存映射

【问题讨论】:

    标签: c# unity3d memory


    【解决方案1】:

    每个引擎都会为其内部使用预先分配内存。然而,这并没有说明您的特定崩溃的原因。

    大多数与内存相关的崩溃不是由您可以通过此内存分配和碎片视图了解的常规操作引起的。

    您需要做的是确定崩溃发生的那一刻,并阅读它的堆栈跟踪以获取详细信息。因为例如,您的问题可能是由您自己的代码(我敢打赌)引起的,该代码在某种循环中加载资产而从未释放该内存。

    【讨论】:

    • 您的内存不足事件将在 CPU RAM 数量较少的设备上提前触发。这只是意味着您的 PC 比该 android 设备拥有更多的 RAM(和虚拟 RAM)。这是意料之中的。
    • CASE A). 如果您的场景脚本正在引用预制件 - 请注意,其依赖链中的所有资产都将在场景加载时加载到内存中(预加载以供即时使用)。这样做的好处是,简单地实例化这些预制件不会在内存中创建重复的资产(纹理等)分配,并且一旦您更改/重新加载场景,其分配将自动释放。所以这些都是 Unity 管理的,如果这些会造成内存问题,那么解决这个问题的唯一方法是让你的资产在内存方面更小或引用更少的预制件。
    • CASE B). 如果您手动加载网格、材质和纹理 - 那么您有责任释放它们,即:如果没有您直接调用 Destroy(asset),它们将永远不会释放它的内存。这通常发生在您的项目需要通过网络从光盘或流加载原始纹理文件时。要解决此问题,您需要创建自己的系统来跟踪这些资产并在不再需要(或无法保留)时销毁它们(释放内存)。
    • Here is a link 到我的 github 存储库中负责加载地图的函数。它变得相当复杂,但我很确定我在使用资产后会正确删除它们,因为我可以加载许多小地图(不是同时)而不会遇到内存问题。加载大地图时会出现问题,这会导致应用程序挂起(在 Windows 上)。当发生这种情况时,日志给出了我之前发布的错误。
    • 支线任务:我看到您正在使用 Color[] - 您可以通过使用 Texture2D.LoadRawTextureData 并直接加载 byte[] 来摆脱此分配。这可以防止不必要的双重分配,并且应该加快加载速度
    猜你喜欢
    • 1970-01-01
    • 2018-08-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-16
    • 1970-01-01
    相关资源
    最近更新 更多