using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using UnityEditor;
using UnityEngine;
using UnityEngine.Networking;
namespace Assets.UnityTest
{
/// <summary>
/// 插件里的方法如何在lua里调用
/// 小地图问题
/// probuf协议
/// lua、C#交互性能问题优化
/// unity动态加载和内存管理
/// unity俩种动态加载方式:(1)Resouces.Load();(2)Assetsboundle.Load()
///
/// AssetsBoundle运行时加载:
/// 来自文件加载用CreateFromFile(这里只能用于standalone程序)这是最快的加载方法
/// 来自缓存的加载用CrateFromMemory(byte[])byte可以来自文件读取的缓存,www的下载或其他可能的方式
/// www的assetsboundle是内部数据读取完成后自己创建了一个assetsboundle而已
/// Create等于把硬盘或者网络的文件读取到一个内存区域,这时候只是个AssetsBoundle内存镜像数据块,还没有Assets的感念
/// Assets加载:
/// AssetsBoundle.Load()(同Rescource.Load())这时会从AssetsBoundle内存镜像里读取并创建一个Assets,创建Assets对象,同时分配相应的内存进行存放(反序列化)
///
/// AssetsBoundle的释放:
/// AssetsBoundle.UnLoad(false);只释放镜像内存,不包含Load创建出来的Assets内存对象
/// AssetsBoundle.UnLoad(true);释放镜像内存,并销毁所有Load创建出来的Assets内存对象
/// Destory()一个实例的时候,只会释放掉克隆,不会释放引用对象和克隆对象的数据源对象,Destory()并不知道是否还有别的Object在引用那些对象
///
/// 当游戏中没有任何场景引用这些Assets以后,这些Assets就成了没有引用的数据块了。就用Rescpource.UnLoadUnUseAssets来释放Destory不能释放的任务。
/// AssetBundle.Unload(false)也不行,AssetBundle.Unload(true)可以但不安全,除非你很清楚没有任何对象在用这些Assets了。
///
/// 关于内存管理:
/// (1)先创建一个AssetsBoundle,无论是文件还是www还是memory
/// (2)用AssetsBoundle.Load()加载对象
/// (3)加载完成后立即AsssetsBoundle.Unload(false)释放掉Assets的镜像内存,但不销毁加载的assets对象
/// 释放时:
/// (1)如果有Instence对象,用Destory进行销毁
/// (2)在合适的地方进行Rescouse.UnLoadUnUseAssets()释放镜像内存
/// (3)如果需要立即释放内存需要加上CG.Collect(),否则内存不会立即释放,有时候可能导致内存没有立即释放而引发异常
/// 这样可以保证内存始终被及时释放,占用量最少。也不需要对每个加载的对象进行引用。
/// 系统在切换新的场景时,所有的内存对象都会被自动销毁,包括AssetsBound.Load()和Instence对象。但不包括AssetsBoundle文件自身的镜像内存,必须用UnLoad进行释放
///
///
///
/// Unity的内存种类:程序代码、托管堆以及本机堆
///
///
///
/// </summary>
///
//AssetsBundle只能加载ab资源,当前设备允许访问的路径都可以
class AssetsBundleTest:MonoBehaviour
{
GameObject obj;
AssetBundleManifest manifestBundle;
IEnumerator<AssetBundle> LoadAB()
{
//来自文件的加载,先加载ab资源到镜像内存
AssetBundle ab = AssetBundle.LoadFromFile(Application.dataPath + "/../../../DarklyRes/Android/thr/models/npcs/npc110.ly");
yield return ab;
manifestBundle = ab.LoadAsset<AssetBundleManifest>("AssetBundleManifest");
string[] manifest = manifestBundle.GetAllDependencies("npc110");
for (int i = 0; i < manifest.Length; i++)
{
AssetBundle.LoadFromFile(manifest[i].ToString());
}
//从镜像内存中加载到内存,并创建assets对象
obj = ab.LoadAsset<GameObject>("npc110");
//释放镜像内存
ab.Unload(false);
//创建实例
Instantiate(obj);
}
private void OnDestroy()
{
if (obj == null) return;
//释放克隆
DestroyImmediate(obj,true);
//释放掉所有的引用
Resources.UnloadUnusedAssets();
//立即释放内存
GC.Collect();
}
private void Start()
{
//StartCoroutine(LoadAB());
}
}
/// <summary>
/// 同步异步:
/// 同步:指定协程步调,协助,相互配合;按照先后顺序执行,在没有得到返回结果之前会一直等待,不会继续往下执行
/// 异步:在同一个功能调用时,不管用没有结果都会继续执行,异步加载至少有一帧的延迟
/// 同步的优点:管理方便,资源准备好可以及时返回,缺点:没有异步快
/// 异步的优点:速度快,和主线程无关;调用比较麻烦,最好的方法是使用回调
///
///
/// </summary>
interface LoadInterface<T> where T:UnityEngine.Object
{
void LoadResourcesObject(T t,string path,bool IsAsync);
void UnLoadResourcesObject(T t);
}
class LoadResourcesBase<T>:LoadInterface<T> where T:UnityEngine.Object
{
virtual public void LoadResourcesObject(T t, string path, bool IsAsync)
{
throw new NotImplementedException();
}
virtual public void UnLoadResourcesObject(T t)
{
throw new NotImplementedException();
}
}
class LoadResources<T> : LoadResourcesBase<T> where T : UnityEngine.Object
{
MonoBehaviour MB;
public override void LoadResourcesObject(T t, string path, bool IsAsync)
{
base.LoadResourcesObject(t, path, IsAsync);
//Resource方式加载
ResourceLoad(t, path, IsAsync);
}
public override void UnLoadResourcesObject(T t)
{
base.UnLoadResourcesObject(t);
}
/// <summary>
/// resource加载;只能加载resources目录下的资源
/// </summary>
/// <param name="t"></param>
/// <param name="path"></param>
/// <param name="IsAsync"></param>
void ResourceLoad(T t,string path,bool IsAsync)
{
if (IsAsync == false)
{
T obj = Resources.Load(path) as T;
t = obj;
/*
*
*
*/
Resources.UnloadAsset(t);
}
else
{
T obj = Resources.LoadAsync(path) as T;
t = obj;
/*
*
*
*/
Resources.UnloadAsset(t);
}
}
/// <summary>
/// AssetsDataBase.Load加载 只能加载Assets下的资源,但是用于Editor
/// </summary>
/// <param name="t"></param>
/// <param name="path"></param>
/// <param name="IsAsync"></param>
void AssetsDataBaseLoad(T t,string path,bool IsAsync)
{
if (IsAsync == false)
{
T obj = AssetDatabase.LoadAssetAtPath<T>(path);
t = obj;
/*
*
*/
Resources.UnloadAsset(t);
}else
Console.WriteLine("AssetsDatabase没有异步加载");
}
/// <summary>
/// www加载 可以加载任意处的资源,包括服务器
/// </summary>
/// <param name="t"></param>
/// <param name="path"></param>
/// <param name="IsAsync"></param>
void WWWResLoad(T t,string url,bool IsAsync)
{
if (IsAsync == false) { Console.WriteLine("www没有同步加载"); }
else
{
MB.StartCoroutine(AsyncLoad(t,url));
}
}
IEnumerator<T> AsyncLoad(T t,string url)
{
T www = new WWW(url) as T;
yield return www;
/*
...
*/
Resources.UnloadAsset(t);
yield return null;
}
/// <summary>
/// unitywebrequstLoad加载 www的升级版
/// </summary>
/// <param name="t"></param>
/// <param name="url"></param>
/// <param name="IsAsync"></param>
void UnityWebRequstLoad(T t,string url,bool IsAsync)
{
if (IsAsync == true)
{
MB.StartCoroutine(UnityRequstAsync(t, url));
}else
Console.WriteLine("UnityWebRequstLoad没有同步");
}
IEnumerator<T> UnityRequstAsync(T t,string url)
{
T obj = new UnityWebRequest(url) as T;
t = obj;
/*
...
*/
Resources.UnloadAsset(t);
yield return null;
}
}
}