版本:unity 5.4.1 语言:C#
海水先在这里坑一会,看了里面的算法深深感到自己数学能力的不足,经过同学的推荐,我准备先看会《数值分析》闭关修炼一下。
至于我在看的实战核心技术的第十章MVC设计框架,提供了一堆无用的代码,然后让你去看他的课程,我就自己研究一下如何从Asset中加载到场景中,又如何在场景中释放资源。
总结一下网上一共有三种方法(这次最终解决了AssetBundle的加载问题,AssetBundle原来是要打包后才能加载……):静态加载、Resources.Load、AssetBundle.LoadAsset。
各有不同的用处吧,本地的话前两个更加容易管理使用,AssetBundle可以用在网络环境下。
接下来看代码:
(参考:http://www.taidous.com/portal.php?mod=view&aid=445&page=1)
public class ResManager : MonoBehaviour {
public GameObject tps;
void Start ()
{
//StartCoroutine(LoadResByResources("TPS"));
//StartCoroutine(LoadResByStatic());
StartCoroutine(LoadResByBundle("file://" + Application.dataPath + @"/Resources/rs.assetbundle", "assets/standard assets/characters/thirdpersoncharacter/prefabs/thirdpersoncontroller.prefab"));
}
// Resources的方法加载资源,只能在Resources文件夹下读取,不想创建Resources文件夹的可以考虑静态加载
IEnumerator LoadResByResources(string path)
{
Resources.UnloadUnusedAssets();
// 读取,此时仅读取了资源的少量信息,并不占多少内存
GameObject go = Resources.Load<GameObject>(path);
yield return new WaitForSeconds(5f);
// 创建,如果Instantiate过多会产生卡顿,所以在加载大量资源的时候,考虑对象池
// 先在读取进度的时候把对象创建出来,并SetActive(false),使用的时候SetActive(true)
GameObject goInit = Instantiate(go);
goInit.transform.parent = transform;
goInit.transform.localPosition = Vector3.zero;
goInit.transform.localRotation = Quaternion.identity;
yield return new WaitForSeconds(5f);
// 销毁对象,但各种资源还占据内存
Destroy(goInit);
yield return new WaitForSeconds(5f);
// 卸载所有没有引用的资源,相当于清空了内存
// 但最好不要主动使用,转换场景的时候会清空资源
Resources.UnloadUnusedAssets();
}
// 静态的方法加载资源,效果与Resources加载类似
IEnumerator LoadResByStatic()
{
Resources.UnloadUnusedAssets();
yield return new WaitForSeconds(5f);
GameObject goInit = Instantiate(tps);
goInit.transform.parent = transform;
goInit.transform.localPosition = Vector3.zero;
goInit.transform.localRotation = Quaternion.identity;
yield return new WaitForSeconds(5f);
Destroy(goInit);
yield return new WaitForSeconds(5f);
Resources.UnloadUnusedAssets();
}
// 使用AssetBundle加载资源,在LoadAsset的时候就会加载大量的资源
// 所以实例化时加载的资源量反而小,可以考虑利用这种方法做加载而不卡顿
IEnumerator LoadResByBundle(string path, string name)
{
Resources.UnloadUnusedAssets();
// 建立WWW读取,这边是本地
WWW bundle = new WWW(path);
yield return bundle;
yield return new WaitForSeconds(5f);
// 从读取到的资源中获取对应prefab
//Object obj = bundle.assetBundle.Load(name); //方法已经被废弃
Object obj = bundle.assetBundle.LoadAsset(name);
yield return new WaitForSeconds(5f);
// 实例化
GameObject goInit = Instantiate(obj) as GameObject;
goInit.transform.parent = transform;
goInit.transform.localPosition = Vector3.zero;
goInit.transform.localRotation = Quaternion.identity;
yield return new WaitForSeconds(5f);
// 删除
Destroy(goInit);
yield return new WaitForSeconds(5f);
// Unload释放内存镜像,参数是是否强制删除内存资源
// true强制删除,即使内存有引用也删除
//bundle.assetBundle.Unload(true);
// 删除没有引用的资源,比如说这边,如果调用的是这个方法的的话
// 虽然资源已经被删除了,但内存中还保留的该prefab,直到调用Resources.UnloadUnusedAssets()
bundle.assetBundle.Unload(false);
Resources.UnloadUnusedAssets();
}
// 打包方法是jiange啊啊啊撰写的()
// 这个方法是打包当前项目的资源,从而形成assetbundle文件,供LoadResByBundle加载
[MenuItem("Assets/Build AssetBundle From Selection")]
static void ExportResourceRGB2()
{
// 打开保存面板,获得用户选择的路径
string path = EditorUtility.SaveFilePanel("Save Resource", "", "New Resource", "assetbundle");
if (path.Length != 0)
{
// 选择的要保存的对象
Object[] selection = Selection.GetFiltered(typeof(Object), SelectionMode.DeepAssets);
//打包
BuildPipeline.BuildAssetBundle(Selection.activeObject, selection, path, BuildAssetBundleOptions.CollectDependencies | BuildAssetBundleOptions.CompleteAssets, BuildTarget.StandaloneWindows);
}
}
}
静态读取和Resources.Load最好先把要用到的实例出来,嗯,在进度读取的时候做,然后SetActive(false)将其隐藏,这样卡顿现象应该不会出现吧。
好了,这本书我看了,再写个热更新吧,其他章节也没什么好看的了。