赞
踩
使用unity开发游戏的过程中,资源的加载一直都是需要重点关注的。unity一共提供了5种资源加载的方式,分别是Resources(只能加载Resources目录中的资源),AssetBundle(只能加载AB资源,当前设备允许访问的路径都可以),WWW(可以加载任意处资源,包括项目外资源(如远程服务器)),AssetDatabase(只能加载Assets目录下的资源,但只能用于Editor),UnityWebRequest(可以加载任意处资源,是WWW的升级版本)。关于加载的的具体方法建议直接看Unity的API,讲解的比较明白,这里提一下同步与异步加载的意思与优缺点:
同步:并不是按字面意思的同时或一起,而是指协同步调,协助、相互配合。是按先后顺序执行在发出一个功能调用时,在没有得到返回结果之前一直在等待,不会继续往下执行。异步:刚好和同步相反,也就是在发出一个功能调用时,不管没有没得到结果,都继续往下执行,异步加载至少有一帧的延迟。
同步的优点:管理方便,资源准备好可以及时返回。缺点:没有异步快。
异步的优点:速度快与主线程无关。缺点:调用比较麻烦,最好的做法是使用回调。
在UnityWebRequest和WWW的使用过程中使用了回调,为了方便以后自己使用,贴一下代码:
首先是定义一个资源加载的接口:
-
public
interface
IResourcesLoadingMode {
-
void ResourcesLoading<T>(T t,
string path,
bool IsAsync)
where T:UnityEngine.Object;
-
void ResourcesUnLoading<T>(T t)
where T:UnityEngine.Object;
-
-
}
然后是资源加载的基类:
-
public
class
ResourcesLoadingMode :
IResourcesLoadingMode
-
{
-
public Image Img;
-
public MonoBehaviour MB;
-
-
public
virtual
void ResourcesLoading<T>(T t,
string path,
bool IsAsync)
where T:UnityEngine.Object
-
{
-
throw
new NotImplementedException();
-
}
-
-
public
virtual
void ResourcesUnLoading<T>(T t)
where T : UnityEngine.Object
-
{
-
throw
new NotImplementedException();
-
}
-
}
这里的monoBehaviour是因为整个资源加载器没有继承MonoBehaviour,在异步加载的时候可以把上层控制层的MonoBehavior拿过来,以便可以调用协程实现异步加载。这是一种解决方案,在老大的教导下采用了第二种使用回调函数的方案。
Resouces方式:
-
public
override
void ResourcesLoading<T>(T t,
string path,
bool IsAsync)
-
{
-
-
if (IsAsync ==
false)
-
{
-
T load = Resources.Load<T>(path);
-
t = load;
-
Debug.Log(
"===="+path+
"====");
-
if (t.GetType() == Img.sprite.GetType())
-
{
-
Img.sprite = t
as Sprite;
-
Resources.UnloadAsset(t);
-
}
-
}
-
else
-
{
-
T load = Resources.LoadAsync<T>(path).asset
as T;
-
t = load;
-
if (t.GetType() == Img.sprite.GetType())
-
{
-
Img.sprite = t
as Sprite;
-
Resources.UnloadAsset(t);
-
}
-
}
-
}
AssetDatabase方式:
-
public
override
void ResourcesLoading<T>(T t,
string path,
bool IsAsync)
-
{
-
if (IsAsync==
false)
-
{
-
//s=string.Format( "Assets/Image/{0}.jpg",Index.ToString())
-
T load = AssetDatabase.LoadAssetAtPath<T>(path);
-
Debug.Log(path);
-
t = load;
-
Debug.Log(t.name);
-
if (t.GetType() == Img.sprite.GetType())
-
{
-
Img.sprite = t
as Sprite;
-
Resources.UnloadAsset(t);
-
}
-
else
-
{
-
Debug.Log(t.name);
-
}
-
}
-
-
else
-
{
-
Debug.Log(
"assetdatabase没有异步加载");
-
}
-
}
WWW方式:
-
public
override
void ResourcesLoading<T>(T t,
string path,
bool isAsync)
-
{
-
if (isAsync ==
true)
-
{
-
// MB.StartCoroutine(WWWLoad());
-
}
-
else
-
{
-
Debug.Log(
"----WWW没有同步加载----");
-
}
-
}
-
-
public
override
void ResourcesUnLoading<T>(T t)
-
{
-
base.ResourcesUnLoading<T>(t);
-
-
}
-
-
public static IEnumerator WWWLoad(string url, Action<WWW>callback)
-
{
-
Debug.Log(
"----WWW协程调用----");
-
//string url = string.Format(@"file://{0}/{1}.jpg", Application.streamingAssetsPath, Index.ToString());
-
WWW www =
new WWW(url);
-
yield
return www;
-
callback.Invoke(www);
-
yield
return
null;
-
}
WWW方式的回调(上层的逻辑来决定需要加载什么资源,写在回调函数里):
-
/// <summary>
-
/// WWW回调函数
-
/// </summary>
-
/// <param name="obj"></param>
-
private void WWWcallback(object obj)
-
{
-
WWW www = obj
as WWW;
-
Texture2D tex = www.texture;
-
BG.sprite = Sprite.Create(tex,
new Rect(
0,
0, tex.width, tex.height), Vector2.zero);
-
Debug.Log(
"----callback调用----");
-
www.Dispose();
-
}
UnityWebRequest方式:
-
public
override
void ResourcesLoading<T>(T t,
string path,
bool isAsync)
-
{
-
-
if (isAsync==
false)
-
{
-
Debug.Log(
"unityWebRequest没有同步加载");
-
}
-
}
-
-
public
override
void ResourcesUnLoading<T>(T t)
-
{
-
base.ResourcesUnLoading<T>(t);
-
}
-
-
public static IEnumerator UnityWebRequestLoad(string url,Action<UnityWebRequest>callback)
-
{
-
//string url =string.Format( @"file://{0}/{1}.jpg", Application.streamingAssetsPath,Index.ToString());
-
UnityWebRequest webRequest = UnityWebRequestTexture.GetTexture(url);
-
yield
return webRequest.SendWebRequest();
-
if (webRequest.isNetworkError || webRequest.isHttpError)
-
{
-
Debug.Log(webRequest.error);
-
}
-
else
-
{
-
callback.Invoke(webRequest);
-
yield
return
null;
-
//Texture2D tex = DownloadHandlerTexture.GetContent(webRequest);
-
//Img.sprite = Sprite.Create(tex, new Rect(0, 0, tex.width, tex.height), Vector2.zero);
-
}
-
}
-
}
UnityWebRequest的回调:
-
/// <summary>
-
/// UnityWebRequest回调函数
-
/// </summary>
-
/// <param name="obj"></param>
-
private void unityWebRequestcallback(object obj)
-
{
-
UnityWebRequest request = obj
as UnityWebRequest;
-
Texture2D tex = DownloadHandlerTexture.GetContent(request);
-
BG.sprite = Sprite.Create(tex,
new Rect(
0,
0, tex.width, tex.height), Vector2.zero);
-
request.Dispose();
-
}
最后的业务层代码也贴一点核心的方法:
-
using System.Collections;
-
using System.Collections.Generic;
-
using UnityEngine;
-
using UnityEngine.Networking;
-
using UnityEngine.UI;
-
-
public
class
ModeControl :
MonoBehaviour {
-
-
-
public
bool IsAsync;
//是否异步加载
-
public Image BG;
-
public ResourcesModeEnum ModeEnum;
//资源加载类型
-
private
bool Next;
-
-
ResourcesLoadingMode mode =
null;
-
Mode_Resources resourcesMode =
null;
-
Mode_AssetDatabase assetDatabaseMode =
null;
-
Mode_WWW wwwMode =
null;
-
Mode_UnityWebRequest unityWebRequestMode =
null;
-
-
-
private
int textureIndex=
1;
// 图片路径索引
-
-
-
void Awake()
-
{
-
resourcesMode =
new Mode_Resources();
-
assetDatabaseMode =
new Mode_AssetDatabase();
-
wwwMode =
new Mode_WWW();
-
unityWebRequestMode =
new Mode_UnityWebRequest();
-
}
-
-
-
private IEnumerator PreviousPageBtnClick(ResourcesModeEnum modeEnum)
-
{
-
changeColor =
true;
-
yield return new WaitForSeconds(1);
-
Next =
false;
-
ResourceModeChoice(modeEnum);
-
colorChange =
true;
-
Debug.Log(
"----上一页按钮点击----");
-
}
-
private IEnumerator NextPageBtnClick(ResourcesModeEnum modeEnum)
-
{
-
changeColor =
true;
-
yield return new WaitForSeconds(1);
-
Next =
true;
-
ResourceModeChoice(modeEnum);
-
colorChange =
true;
-
Debug.Log(
"----下一页按钮点击----");
-
-
}
-
-
/// <summary>
-
/// 资源加载方式公共方法
-
/// </summary>
-
/// <param name="modeEnum">资源类型</param>
-
private void ResourceModeChoice(ResourcesModeEnum modeEnum)
-
{
-
switch (modeEnum)
-
{
-
case ResourcesModeEnum.ResourcesMode:
-
mode = resourcesMode;
-
ChangePage();
-
mode.ResourcesLoading(BG.sprite,textureIndex.ToString(), IsAsync);
-
break;
-
case ResourcesModeEnum.WWWMode:
-
mode = wwwMode;
-
ChangePage();
-
StartCoroutine(Mode_WWW.WWWLoad(
string.Format(
@"file://{0}/{1}.jpg", Application.streamingAssetsPath, textureIndex.ToString()), WWWcallback));
-
break;
-
case ResourcesModeEnum.AssetDatabaseMode:
-
mode = assetDatabaseMode;
-
ChangePage();
-
mode.ResourcesLoading(BG.sprite,
string.Format(
"Assets/Image/{0}.jpg", textureIndex.ToString()), IsAsync);
-
break;
-
case ResourcesModeEnum.UnityWebMode:
-
mode = unityWebRequestMode;
-
ChangePage();
-
StartCoroutine(Mode_UnityWebRequest.UnityWebRequestLoad(
string.Format(
@"file://{0}/{1}.jpg", Application.streamingAssetsPath, textureIndex), unityWebRequestcallback));
-
break;
-
case ResourcesModeEnum.NULL:
-
mode.ResourcesUnLoading(BG.sprite);
-
BG.sprite =
null;
-
break;
-
default:
-
break;
-
}
-
}
-
-
/// <summary>
-
/// 换页公共方法
-
/// </summary>
-
private void ChangePage()
-
{
-
-
if (Next ==
false) textureIndex--;
-
if (Next ==
true) textureIndex++;
-
mode.Img = BG;
-
mode.MB =
this.GetComponent<MonoBehaviour>();
-
// mode.ResourcesLoading<Sprite>(BG.sprite, IsAsync);
-
-
// mode.ResourcesUnLoading(BG.sprite);
-
}
-
private void ResourcesClick()
-
{
-
ModeEnum = ResourcesModeEnum.ResourcesMode;
-
ResourceModeChoice(ModeEnum);
-
SetTipText(TipText,
"ResourcesMode");
-
}
-
private void AssetBundleBtnClick()
-
{
-
//TODO
-
}
-
private void WWWBtnClick()
-
{
-
if (IsAsync ==
false)
-
{
-
ModeEnum = ResourcesModeEnum.NULL;
-
SetTipText(TipText,
"WWW没有同步加载");
-
}
-
else
-
{
-
ModeEnum = ResourcesModeEnum.WWWMode;
-
ResourceModeChoice(ModeEnum);
-
SetTipText(TipText,
"WWWMode");
-
}
-
-
}
-
private void AssetDatabaseBtnClick()
-
{
-
if (IsAsync ==
false)
-
{
-
ModeEnum = ResourcesModeEnum.AssetDatabaseMode;
-
ResourceModeChoice(ModeEnum);
-
SetTipText(TipText,
"AssetDatabaseMode");
-
}
-
else
-
{
-
ModeEnum = ResourcesModeEnum.NULL;
-
SetTipText(TipText,
"AssetDatabase没有异步加载");
-
}
-
-
}
-
private void UnityWebRequestBtnClick()
-
{
-
if (IsAsync ==
false)
-
{
-
ModeEnum = ResourcesModeEnum.NULL;
-
SetTipText(TipText,
"UnityWebRequest没有同步加载");
-
}
-
else
-
{
-
ModeEnum = ResourcesModeEnum.UnityWebMode;
-
ResourceModeChoice(ModeEnum);
-
SetTipText(TipText,
"UnityWebRequestMode");
-
}
-
-
}
-
private void SynBtnClick()
-
{
-
IsAsync =
false;
-
SetTipText(IsAnsynText,
"当前为同步加载方式");
-
}
-
private void AsynBtnClick()
-
{
-
IsAsync =
true;
-
SetTipText(IsAnsynText,
"当前为异步加载方式");
-
}
-
-
/// <summary>
-
/// WWW回调函数
-
/// </summary>
-
/// <param name="obj"></param>
-
private void WWWcallback(object obj)
-
{
-
WWW www = obj
as WWW;
-
Texture2D tex = www.texture;
-
BG.sprite = Sprite.Create(tex,
new Rect(
0,
0, tex.width, tex.height), Vector2.zero);
-
Debug.Log(
"----callback调用----");
-
www.Dispose();
-
}
-
-
/// <summary>
-
/// UnityWebRequest回调函数
-
/// </summary>
-
/// <param name="obj"></param>
-
private void unityWebRequestcallback(object obj)
-
{
-
UnityWebRequest request = obj
as UnityWebRequest;
-
Texture2D tex = DownloadHandlerTexture.GetContent(request);
-
BG.sprite = Sprite.Create(tex,
new Rect(
0,
0, tex.width, tex.height), Vector2.zero);
-
request.Dispose();
-
}
-
-
private void SetTipText(Text text,string str)
-
{
-
text.text = str;
-
}
-
}
这次的demo让我认识自己很多的不足,接口,类的继承,同步与异步,资源的卸载,还有很关键的一点,写的很多代码不能复用,在资源加载器写了具体的实现,这些东西应该放在上层业务层去决定你要什么资源就加载什么资源,把加载的类型和路径传进去就行了。下次千万注意,单一职责原则,可以很大的降低代码的耦合。感谢龙哥,继续加油!
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。