• Unity在场景切换之间清理下内存


    看了两篇关于Unity加载和内存管理的文章,写得很详细。
    文章链接:
     

     Unity系统在加载新场景时,所有的内存对象都会被自动销毁,包括你用AssetBundle.Load加载的对象和Instaniate克隆的。

    但是不包括AssetBundle文件自身的内存镜像,那个必须要用Unload来释放,用.net的术语,这种数据缓存是非托管的。

     
    既然加载场景不会释放AssetBundle文件自身的内存镜像,那我们就手动释放。
     
    Destroy:主要用于销毁克隆对象,也可以用于场景内的静态物体,不会自动释放该对象的所有引用。虽然也可以用于Asset,但是概念不一样要小心,如果用于销毁从文件加载的Asset对象会销毁相应的资源文件!但是如果销毁的Asset是Copy的或者用脚本动态生成的,只会销毁内存对象。
    AssetBundle.Unload(false):释放AssetBundle文件内存镜像
    AssetBundle.Unload(true):释放AssetBundle文件内存镜像同时销毁所有已经Load的Assets内存对象
    Reources.UnloadAsset(Object):显式的释放已加载的Asset对象,只能卸载磁盘文件加载的Asset对象
    Resources.UnloadUnusedAssets:用于释放所有没有引用的Asset对象
    GC.Collect()强制垃圾收集器立即释放内存 Unity的GC功能不算好,没把握的时候就强制调用一下
     
    场景A切换到场景B,使用同步加载Application.LoadLevel(sceneName)或者异步加载Application.LoadLevelAsync(sceneName)都可以。
     
    我们可以在场景A和场景B之间插入一个清理内存的场景X,场景X就是一个空场景,它的主要作用是承上启下,把场景A留下的资源清理,然在切换到场景B。
     
    可以这个功能封装起来。
     
     1 using System;
     2 using UnityEngine;
     3 using System.Collections;
     4 using System.Runtime.CompilerServices;
     5 using Object = UnityEngine.Object;
     6 
     7 public class ClearSceneData : MonoBehaviour
     8 {
     9     //异步对象
    10     private AsyncOperation async;
    11 
    12     //下一个场景的名称
    13     private static string nextSceneName;
    14 
    15     void Awake()
    16     {
    17         Object[] objAry = Resources.FindObjectsOfTypeAll<Material>();
    18 
    19         for (int i = 0; i < objAry.Length; ++i)
    20         {
    21             objAry[i] = null;//解除资源的引用
    22         }
    23 
    24         Object[] objAry2 = Resources.FindObjectsOfTypeAll<Texture>();
    25 
    26         for (int i = 0; i < objAry2.Length; ++i)
    27         {
    28             objAry2[i] = null;
    29         }
    30 
    31         //卸载没有被引用的资源
    32         Resources.UnloadUnusedAssets();
    33 
    34         //立即进行垃圾回收
    35         GC.Collect();
    36         GC.WaitForPendingFinalizers();//挂起当前线程,直到处理终结器队列的线程清空该队列为止
    37         GC.Collect();
    38 
    39     }
    40 
    41     void Start()
    42     {
    43         StartCoroutine("AsyncLoadScene", nextSceneName);
    44     }
    45 
    46     /// <summary>
    47     /// 静态方法,直接切换到ClearScene,此脚本是挂在ClearScene场景下的,就会实例化,执行资源回收
    48     /// </summary>
    49     /// <param name="_nextSceneName"></param>
    50     public static void LoadLevel(string _nextSceneName)
    51     {
    52         nextSceneName = _nextSceneName;
    53         Application.LoadLevel("ClearScene");
    54     }
    55 
    56     /// <summary>
    57     /// 异步加载下一个场景
    58     /// </summary>
    59     /// <param name="sceneName"></param>
    60     /// <returns></returns>
    61     IEnumerator AsyncLoadScene(string sceneName)
    62     {
    63         async = Application.LoadLevelAsync(sceneName);
    64         yield return async;
    65     }
    66 
    67     void OnDestroy()
    68     {
    69         async = null;
    70     }
    71     
    72 }
  • 相关阅读:
    WPF Path使用Geometry数据
    WPF Uri反射加载XAML
    T4模板生成数据库实体DB First
    Unsatisfied dependency expressed through method 'shirFilter' parameter 0 异常排查
    SpringBoot集成多数据源
    SpringBoot整合Flyway数据库版本管理
    阿里云服务器Docket安装RabbitMQ 3.8.12
    Docker 部署阿里云RocketMQ 4.5.1
    SpringBoot 整合EasyExcel 获取动态Excel列名
    SpringBoot 开发提速神器 Lombok+MybatisPlus+SwaggerUI
  • 原文地址:https://www.cnblogs.com/dongz888/p/4920714.html
Copyright © 2020-2023  润新知