您的位置:首页 > 移动开发 > Unity3D

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

2015-10-29 15:43 507 查看
看了两篇关于Unity加载和内存管理的文章,写得很详细。
文章链接:
http://game.ceeger.com/forum/read.php?tid=4394
http://game.ceeger.com/forum/read.php?tid=4466

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。

可以这个功能封装起来。

using System;
using UnityEngine;
using System.Collections;
using System.Runtime.CompilerServices;
using Object = UnityEngine.Object;

public class ClearSceneData : MonoBehaviour
{
//异步对象
private AsyncOperation async;

//下一个场景的名称
private static string nextSceneName;

void Awake()
{
Object[] objAry = Resources.FindObjectsOfTypeAll<Material>();

for (int i = 0; i < objAry.Length; ++i)
{
objAry[i] = null;//解除资源的引用
}

Object[] objAry2 = Resources.FindObjectsOfTypeAll<Texture>();

for (int i = 0; i < objAry2.Length; ++i)
{
objAry2[i] = null;
}

//卸载没有被引用的资源
Resources.UnloadUnusedAssets();

//立即进行垃圾回收
GC.Collect();
GC.WaitForPendingFinalizers();//挂起当前线程,直到处理终结器队列的线程清空该队列为止
GC.Collect();

}

void Start()
{
StartCoroutine("AsyncLoadScene", nextSceneName);
}

/// <summary>
/// 静态方法,直接切换到ClearScene,此脚本是挂在ClearScene场景下的,就会实例化,执行资源回收
/// </summary>
/// <param name="_nextSceneName"></param>
public static void LoadLevel(string _nextSceneName)
{
nextSceneName = _nextSceneName;
Application.LoadLevel("ClearScene");
}

/// <summary>
/// 异步加载下一个场景
/// </summary>
/// <param name="sceneName"></param>
/// <returns></returns>
IEnumerator AsyncLoadScene(string sceneName)
{
async = Application.LoadLevelAsync(sceneName);
yield return async;
}

void OnDestroy()
{
async = null;
}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: