Unity 工具类 之 简单网络下载任务队列服务实现(WWW/UnityWebRequest/下载AssetBundle/Audioclip/Texture2D/Text等)
目录
Unity 工具类 之 简单网络下载任务队列服务实现(WWW/UnityWebRequest/下载AssetBundle/Audioclip/Texture2D/Text等)
一、简单介绍
Unity 工具类,自己整理的一些游戏开发可能用到的模块,单独独立使用,方便游戏开发。
简单网络下载任务队列服务,单独做了一个单例类,实现向服务中添加任务,就会自动下载对应的下载任务,可以根据自己的需要添加自己下载后的资源管理,以及扩展其他下载类型的任务和功能,供外界调用。
二、实现原理
1、IWWWBase 和 WWWBase ,作为具体的下载类型基类,定义共有方法和属性;
2、WWWAudio 、WWWImage 实现具体类型下载方法和开始下载、下载错误、下载完成的事件(根据需要可以自行拓展);
3、WWWService 负责添加下载任务,并自动下载对应下载任务;
4、简单网络下载任务队列服务 大概的框架如下:
三、效果预览
四、实现步骤
1、打开Unity,新建一个空工程
2、在场景中添加 RawImage和Text 用显示下载的图片的和Text文本
3、新建脚本,实现各个类型下载,以及 下载服务类,添加任务下载,和一个测试功能的脚本
4、把测试脚本对应添加到场景中,并对应的赋值
5、运行脚本,会有图片显示、文本显示,以及一个音频播放
6、断网的时候,结果如下
五、关键代码
1、TestWWWService
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class TestWWWService : MonoBehaviour
{
public RawImage rawImage;
public Text text;
AudioSource audioSource;
// Start is called before the first frame update
void Start()
{
audioSource =this.gameObject.AddComponent<AudioSource>();
Test();
}
void Test() {
string imageUrl = @"https://ss1.bdstatic.com/70cFvXSh_Q1YnxGkpoWK1HF6hhy/it/u=1752460159,226752426&fm=26&gp=0.jpg";
WWWImage wImage = new WWWImage(imageUrl,
(texture)=> {
rawImage.texture = (Texture2D)texture;
if (WWWService.Instance.wImageDic.ContainsKey(imageUrl) == false)
{
WWWService.Instance.wImageDic.Add(imageUrl, (Texture2D)texture);
}
});
string audioUrl = @"http://downsc.chinaz.net/Files/DownLoad/sound1/201702/8369.wav";
WWWAudio wAudio = new WWWAudio(audioUrl,
(clip) =>{
audioSource.clip = (AudioClip)clip;
audioSource.Play();
if (WWWService.Instance.wAudipDic.ContainsKey(audioUrl) == false)
{
WWWService.Instance.wAudipDic.Add(audioUrl, (AudioClip)clip);
}
});
string txtUrl = @"http://baidu.com";
WWWText wText = new WWWText(txtUrl,
(txt)=>{
text.text = (string)txt;
if (WWWService.Instance.wTextDic.ContainsKey(txtUrl) == false)
{
WWWService.Instance.wTextDic.Add(txtUrl, (string)txt);
}
});
WWWService.Instance.AddWWWTask(wImage);
WWWService.Instance.AddWWWTask(wAudio);
WWWService.Instance.AddWWWTask(wText);
}
}
2、WWWService
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class WWWService : MonoSingleton<WWWService>
{
// 下载队列
private Queue<WWWBase> allWWWTaskQue = new Queue<WWWBase>();
#region 数据管理
internal Dictionary<string, string> wTextDic = new Dictionary<string, string>();
internal Dictionary<string, Texture2D> wImageDic = new Dictionary<string, Texture2D>();
internal Dictionary<string, AudioClip> wAudipDic = new Dictionary<string, AudioClip>();
#endregion
#region 下载任务
public void AddWWWTask(WWWBase task) {
Debug.Log(GetType()+ "/AddWWWTask() Add One WWW Task/");
allWWWTaskQue.Enqueue(task);
// 有开始下载
if (allWWWTaskQue.Count == 1)
{
// 协程开始任务下载
StartCoroutine(DownloadWWWTask());
}
}
IEnumerator DownloadWWWTask() {
// 循环到下载完为止
while (allWWWTaskQue.Count > 0)
{
WWWBase task = allWWWTaskQue.Dequeue();
// 等待这个任务下载完
yield return task.Download();
}
}
#endregion
}
3、IWWWBase
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Networking;
public interface IWWWBase
{
//开始下载
void BeginDownload();
// 下载出错
void DownloadError(UnityWebRequest uwr);
// 下载结束
void DownloadFinish(UnityWebRequest uwr);
// 协程下载
IEnumerator Download();
}
4、WWWBase
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Networking;
public class WWWBase : IWWWBase
{
private string url;
public string Url { get => url; set => url = value; }
protected Action<object> action;
public WWWBase(string url, Action<object> action = null)
{
Url = url;
this.action = action;
}
public virtual void BeginDownload()
{
}
public virtual void DownloadError(UnityWebRequest uwr)
{
}
public virtual void DownloadFinish(UnityWebRequest uwr)
{
}
public virtual IEnumerator Download()
{
BeginDownload();
using (UnityWebRequest uwr = UnityWebRequest.Get(Url))
{
yield return uwr.SendWebRequest();
if (!(uwr.isNetworkError || uwr.isHttpError))
{
DownloadFinish(uwr);
}
else
{
DownloadError(uwr);
}
}
}
}
5、WWWAudio
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Networking;
public class WWWAudio : WWWBase
{
// 最好构建资源管理统一放置
public AudioClip clip;
public WWWAudio(string url, Action<object> action = null) : base(url, action)
{
}
public override void BeginDownload()
{
Debug.Log(GetType()+ "/BeginDownload()/ Audio");
}
public override void DownloadError(UnityWebRequest uwr)
{
Debug.Log(GetType() + "/BeginDownload()/ Audio uwr.error : " + uwr.error);
}
public override void DownloadFinish(UnityWebRequest uwr)
{
clip = DownloadHandlerAudioClip.GetContent(uwr);
action?.Invoke(clip);
}
public override IEnumerator Download()
{
BeginDownload();
using (var uwr = UnityWebRequestMultimedia.GetAudioClip(Url, AudioType.WAV))
{
yield return uwr.SendWebRequest();
if (!(uwr.isNetworkError || uwr.isHttpError))
{
DownloadFinish(uwr);
}
else
{
DownloadError(uwr);
}
}
}
}
6、WWWImage
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Networking;
public class WWWImage : WWWBase
{
// 最好构建资源管理统一放置
public Texture2D texture2D;
public WWWImage(string url , Action<object> action = null):base(url,action)
{
}
public override void BeginDownload()
{
Debug.Log(GetType() + "/BeginDownload()/ Image");
}
public override void DownloadError(UnityWebRequest uwr)
{
Debug.Log(GetType() + "/BeginDownload()/ Image uwr.error : " + uwr.error);
}
public override void DownloadFinish(UnityWebRequest uwr)
{
texture2D = ((DownloadHandlerTexture)uwr.downloadHandler).texture;
action?.Invoke(texture2D);
}
public override IEnumerator Download()
{
BeginDownload();
using (UnityWebRequest uwr = new UnityWebRequest(Url))
{
DownloadHandlerTexture downloadTexture = new DownloadHandlerTexture(true);
uwr.downloadHandler = downloadTexture;
yield return uwr.SendWebRequest();
if (!(uwr.isNetworkError || uwr.isHttpError))
{
DownloadFinish(uwr);
}
else
{
DownloadError(uwr);
}
}
}
}
7、WWWText
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEngine;
using UnityEngine.Networking;
public class WWWText : WWWBase
{
// 最好构建资源管理统一放置
public string txtStr;
public WWWText(string url, Action<object> action = null) : base(url, action)
{
}
public override void BeginDownload()
{
Debug.Log(GetType() + "/BeginDownload()/ Text");
}
public override void DownloadError(UnityWebRequest uwr)
{
Debug.Log(GetType() + "/BeginDownload()/ Text uwr.error : " + uwr.error);
}
public override void DownloadFinish(UnityWebRequest uwr)
{
txtStr = uwr.downloadHandler.text;
action?.Invoke(txtStr);
}
public override IEnumerator Download()
{
BeginDownload();
using (UnityWebRequest uwr = UnityWebRequest.Get(Url)) {
yield return uwr.SendWebRequest();
if (!(uwr.isNetworkError || uwr.isHttpError))
{
DownloadFinish(uwr);
}
else
{
DownloadError(uwr);
}
// 保存本地(酌情处理)
//File.WriteAllText(@"D:\xxxx.txt", str);
}
}
}
8、WWWAssetBundle
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Networking;
public class WWWAssetBundle : WWWBase
{
// 最好构建资源管理统一放置
public AssetBundle assetBundle;
public WWWAssetBundle(string url, Action<object> action = null) : base(url, action)
{
}
public override void BeginDownload()
{
Debug.Log(GetType() + "/BeginDownload()/ AssetBundle");
}
public override void DownloadError(UnityWebRequest uwr)
{
Debug.Log(GetType() + "/BeginDownload()/ AssetBundle uwr.error : " + uwr.error);
}
public override void DownloadFinish(UnityWebRequest uwr)
{
assetBundle = ((DownloadHandlerAssetBundle)uwr.downloadHandler).assetBundle;
}
public override IEnumerator Download()
{
BeginDownload();
using (UnityWebRequest uwr = new UnityWebRequest(Url))
{
DownloadHandlerAssetBundle handler = new DownloadHandlerAssetBundle(uwr.url, uint.MaxValue);
uwr.downloadHandler = handler;
yield return uwr.SendWebRequest();
if (!(uwr.isNetworkError || uwr.isHttpError))
{
DownloadFinish(uwr);
}
else
{
DownloadError(uwr);
}
}
}
}
9、MonoSingleton
using UnityEngine;
public abstract class MonoSingleton<T> : MonoBehaviour where T : MonoBehaviour
{
private static T instance = null;
private static readonly object locker = new object();
private static bool bAppQuitting;
public static T Instance
{
get
{
if (bAppQuitting)
{
instance = null;
return instance;
}
lock (locker)
{
if (instance == null)
{
instance = FindObjectOfType<T>();
if (FindObjectsOfType<T>().Length > 1)
{
Debug.LogError("不应该存在多个单例!");
return instance;
}
if (instance == null)
{
var singleton = new GameObject();
instance = singleton.AddComponent<T>();
singleton.name = "(singleton)" + typeof(T);
singleton.hideFlags = HideFlags.None;
DontDestroyOnLoad(singleton);
}
else
DontDestroyOnLoad(instance.gameObject);
}
instance.hideFlags = HideFlags.None;
return instance;
}
}
}
private void Awake()
{
bAppQuitting = false;
}
private void OnDestroy()
{
bAppQuitting = true;
}
}