添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
  • Live2D Cubism SDK教程
  • SDK for Native
  • SDK for Web
  • SDK for Java
  • SDK for Unity
  • SDK for Cocos Creator
  • SDK for Unreal Engine
  • 群组SDK
  • Live2D GARAGE
  • 使用AssetBundle中的模型时的内存记忆泄漏及其解决方法

    最終更新: 2020年10月21日

    在从AssetBundle读取和卸载使用剪贴的模型的Prefab时,可能会发生内存记忆泄漏,具体取决于CubismMaskTexture的处理方式。

    这里将说明其原因、未应对的原因以及应对措施。

    如果您想在Unity中处理设置了剪贴的模型,请使用CubismMaskController。
    您在CubismMaskController.MaskTexture中设置的蒙版纹理(CubismMaskTexture副本),如果未设置,则将在原始化时参考应用程序内的GlobalMaskTexture。
    但是,根据项目的规格,CubismMaskTexture的副本可能包含在AssetBundle中,而不是应用程序端。
    在这种情况下,从AssetBundle读取和卸载模型可能会导致内存记忆泄漏。

    造成内存记忆泄漏的原因是CubismMaskTexture内部的RenderTexture生成并保留。
    根据CubismMaskTexture的使用方式,有两种对策。

    case 1: 如果所有模型都使用一种CubismMaskTexture
    1-1. 删除CubismMaskControllerInspector.cs的EditorGUILayout.ObjectField
    1-2. 将CubismMaskController.cs中序列化的_maskTexture变更为非序列化处理
    1-3. 重新创建AssetBundle

    case 2: 如果各模型都有一个CubismMaskTexture副本
    2-1. 在CubismMasktexture.cs中创建删除_renderTexture的方法
    2-2. 在放弃模型的时机调用2-1中创建的方法
    2-3. 重新创建AssetBundle

    采取上述任一措施都可以解决内存记忆泄漏的问题。

    背景/原因

    在Live2D模型中对设置剪贴的模型进行AssetBundle化后,从那里读取和卸载模型会导致内存记忆泄漏。

    原因是每次读取模型时,都会生成一个蒙版用RenderTexture,即使模型被删除,RenderTexture仍然存在。
    在组件上设置的物体是通过物体复制进行AssetBundled化,而不是对该物体的参考。
    因此,如果您通过AssetBundle化生成模型,在将CubismMaskTexture的副本GlobalMaskTexture设置到CubismMaskController.MaskTexture时,会在读取模型的同时生成GlobalMaskTexture的复制并创建RenderTexture。
    但是,即使删除了模型,RenderTexture仍然没有被删除。结果导致内存记忆泄漏。

    由于以下三个原因,此错误的更正没有应用在Cubism SDK中。

    1. 因为根据如何处理蒙版用RenderTexture,对应方法也有所差异
    2. 因为专注于结构清晰和简单的CubismComponents变得复杂
    3. 因为不使用AssetBundle时没有问题

    对策的注意事项

    本节介绍了两种对策。

    请注意,这两个对策是独立的对策,所以不要在一个项目中同时采取两个对策。

    对策因您使用CubismMaskTexture的方式而异。只使用一个CubismMaskTexture时,或者为各模型使用一个 CubismMaskTexture副本。
    这里将针对两种使用方法,各说明一种对策。

    Case 1: 使用一个CubismMaskTexture显示模型时

    如果您重复使用一个CubismMaskTexture显示模型,请采取此对策。

    首先,删除CubismMaskControllerInspector.cs中包含的EditorGUILayout.ObjectField。

    // Draw mask texture. EditorGUI.BeginChangeCheck(); // 相关部分。删除这一行。 controller.MaskTexture = EditorGUILayout.ObjectField("Mask Texture", controller.MaskTexture, typeof(CubismMaskTexture), true) as CubismMaskTexture; // Apply changes. if (EditorGUI.EndChangeCheck()) EditorUtility.SetDirty(controller);

    接下来,将CubismMaskController.cs中序列化的_maskTexture变更为非序列化处理。

    public sealed class CubismMaskController : MonoBehaviour, ICubismMaskTextureCommandSource /// <summary> /// <see cref="MaskTexture"/> backing field. /// </summary> [SerializeField, HideInInspector] // 相关部分。删除这一行。 private CubismMaskTexture _maskTexture; /// <summary> /// Mask texture. /// </summary> public CubismMaskTexture MaskTexture

    至此即完成了对策。
    然后,请重新创建AssetBundle。

    case 2: 如果各模型都有一个CubismMaskTexture副本

    如果各模型都有一个CubismMaskTexture副本,请执行以下对策。

    首先,在CubismMaskTexture.cs中创建一个对_randerTexture进行Destroy的public方法。
    以下为代码示例。

            public void DeleteRenderTexture()
                DestroyImmediate(_renderTexture);
    

    在放弃模型的时候调用上述方法。
    这样您就可以向模型一样删除RenderTexture。

    完成上述对策后,请重新创建AssetBundle。

    请问这篇文章对您有帮助吗?
    关于本报道,敬请提出您的意见及要求。