WWW

作者:追风剑情 发布于:2019-7-16 17:59 分类:Unity3d

示例一:实现一个简单的加载队列

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

/// <summary>
/// WWW加载队列
/// </summary>
public class WWWQueue : MonoBehaviour
{
    private List<WWWLoader> list = new List<WWWLoader>();

    private void Awake()
    {
        DontDestroyOnLoad(gameObject);
    }

    private void Update()
    {
        for (int i=0; i < list.Count; i++)
        {
            WWW www = list[i].www;
            if (!www.isDone)
                continue;

            if (!string.IsNullOrEmpty(www.error))
            {
                Debug.LogErrorFormat("{0}\n{1}", www.error, www.url);
                RemoveAt(i);
                continue;
            }

            AssetBundle ab = www.assetBundle;
            Action<AssetBundle> callback = list[i].callback;
            bool cancel = list[i].cancel;
            if (!cancel && callback != null)
                callback(ab);
            ab.Unload(false);//释放镜像资源
            www.Dispose();

            RemoveAt(i);
        }
    }

    private void RemoveAt(int index)
    {
        if (index >= list.Count)
            return;
        if (index == list.Count - 1)
        {
            list.RemoveAt(index);
            return;
        }

        //优化
        var obj = list[index];
        list[index] = list[list.Count-1];
        list[list.Count-1] = obj;
        list.RemoveAt(list.Count - 1);
    }

    // 加载
    public void Load(string url, Action<AssetBundle> callback)
    {
        WWW www = new WWW(url);
        WWWLoader loader = new WWWLoader(www, callback);
        list.Add(loader);
    }

    // 取消
    public void Cancel(string url)
    {
        for (int i=0; i<list.Count; i++)
        {
            if (list[i].www.url == url)
            {
                list[i].cancel = true;
            }
        }
    }

    private class WWWLoader
    {
        public Action<AssetBundle> callback;
        public WWW www;
        public bool cancel = false;

        public WWWLoader(WWW www, Action<AssetBundle> callback)
        {
            this.www = www;
            this.callback = callback;
        }

        public void Dispose()
        {
            callback = null;
            if (www != null)
                www.Dispose();
            www = null;
        }
    }
}


示例二:资源加载器

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

/// <summary>
/// 资源加载器
/// </summary>
public class AssetDownLoader : MonoBehaviour
{
    public bool dontDestroyOnLoad = true;
    public bool isSingleInstance = true;
    public readonly int MAX_LOADING_COUNT = 100;
    public int LoadingCount { get { return m_LoadingList.Count; } }
    public int WaitingCount { get { return m_WaitingQueue.Count; } }

    private Queue<AssetObject> m_WaitingQueue = new Queue<AssetObject>();
    private List<AssetObject> m_LoadingList = new List<AssetObject>();
    private List<AssetObject> tmp_LoadingList = new List<AssetObject>();

    public static AssetDownLoader Instance { get; private set; }

    private void Awake()
    {
        if (dontDestroyOnLoad)
            DontDestroyOnLoad(gameObject);

        if (isSingleInstance)
            Instance = this;
    }

    public void Load(string url, 
        Action<AssetObject> OnCompletedCallback, 
        Action<AssetObject> OnProgressCallback=null, 
        Action<AssetObject> OnErrorCallback=null, 
        string flag="")
    {
        AssetObject asset = new AssetObject();
        asset.url = url;
        asset.OnCompletedCallback = OnCompletedCallback;
        asset.OnProgressCallback = OnProgressCallback;
        asset.OnErrorCallback = OnErrorCallback;
        asset.flag = flag;
        m_WaitingQueue.Enqueue(asset);
    }

    public void Load(AssetObject asset)
    {
        if (asset == null || string.IsNullOrEmpty(asset.url))
            return;
        m_WaitingQueue.Enqueue(asset);
    }

    // 清空加载列表
    public void ClearLoadingList()
    {
        for (int i = 0; i < m_LoadingList.Count; i++)
            m_LoadingList[i].Dispose();
        m_LoadingList.Clear();
    }

    // 清空待加载列表
    public void ClearWaitingList()
    {
        while (WaitingCount > 0)
        {
            AssetObject asset = m_WaitingQueue.Dequeue();
            asset.Dispose();
        }
    }

    private void Update()
    {
        UpdateWaiting();
        UpdateLoading();
        RemoveDoneAssets();
    }

    private void UpdateWaiting()
    {
        if (m_WaitingQueue.Count <= 0)
            return;

        if (LoadingCount > MAX_LOADING_COUNT)
            return;

        AssetObject asset = m_WaitingQueue.Dequeue();
        asset.CreateWWW();
        m_LoadingList.Add(asset);
    }

    private void UpdateLoading()
    {
        if (LoadingCount <= 0)
            return;

        for (int i=0; i<m_LoadingList.Count; i++)
        {
            AssetObject asset = m_LoadingList[i];
            if (!asset.IsDone)
            {
                asset.OnProgress();
                continue;
            }
            asset.ParseAsset();
        }
    }

    private void RemoveDoneAssets()
    {
        if (LoadingCount <= 0)
            return;

        tmp_LoadingList.Clear();
        for (int i=0; i < m_LoadingList.Count; i++)
        {
            AssetObject asset = m_LoadingList[i];
            if (asset.IsDone)
                asset.DisposeWWW();
            else
                tmp_LoadingList.Add(asset);
        }

        if (tmp_LoadingList.Count != m_LoadingList.Count)
        {
            m_LoadingList.Clear();
            m_LoadingList.AddRange(tmp_LoadingList.ToArray());
        }
        tmp_LoadingList.Clear();
    }

    public enum AssetType
    {
        None,
        Text,
        Texture,
        Model,
        Audio
    }

    public class AssetObject
    {
        public string flag;
        public string url;
        public bool needUnload = true;
        public AssetType type = AssetType.None;
        public Texture2D texture;
        public string text;
        public byte[] bytes;
        public AudioClip audioClip;
        public WWW www;

        public Action<AssetObject> OnCompletedCallback;
        public Action<AssetObject> OnProgressCallback;
        public Action<AssetObject> OnErrorCallback;

        public void CreateWWW()
        {
            www = new WWW(url);
        }

        public bool IsDone
        {
            get
            {
                if (www == null)
                    return false;
                return www.isDone;
            }
        }

        public bool IsError
        {
            get
            {
                if (www == null)
                    return false;
                return !string.IsNullOrEmpty(www.error);
            }
        }

        public void OnProgress()
        {
            if (OnProgressCallback != null)
                OnProgressCallback(this);
        }

        public void ParseAsset()
        {
            if (www == null || !www.isDone)
                return;

            if (!string.IsNullOrEmpty(www.error))
            {
                if (OnErrorCallback != null)
                    OnErrorCallback(this);

                string url = www.url;
                string error = www.error;
                DisposeWWW();

                Debug.LogErrorFormat("Load asset failed from {0}.\n{1}", url, error);
                return;
            }

            text = www.text;
            bytes = www.bytes;
            texture = www.texture;
            if (type == AssetType.Audio)
                audioClip = www.GetAudioClip();

            if (OnCompletedCallback != null)
                OnCompletedCallback(this);

            // 释放镜像资源
            // 如果加载的资源不是AssetBundle,当调用www.assetBundle时会报如下错:
            // Failed to decompress data for the AssetBundle 'Memory'
            if (needUnload && www.assetBundle != null)
                www.assetBundle.Unload(false);

            Dispose();
        }

        public void DisposeWWW()
        {
            if (www != null)
                www.Dispose();
            www = null;
            OnCompletedCallback = null;
            OnProgressCallback = null;
            OnErrorCallback = null;
        }

        public void Dispose()
        {
            DisposeWWW();
            bytes = null;
            text = string.Empty;
            texture = null;
        }
    }
}


示例三:加载语言包

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// 语言包
/// 富文本标签 https://docs.unity3d.com/cn/2021.3/Manual/StyledText.html
/// </summary>
public class Language : MonoBehaviour
{
    public static Language instance { get; private set; }
    private Dictionary<int, string> dic = new Dictionary<int, string>();

    void Awake()
    {
        instance = this;
        DontDestroyOnLoad(gameObject);
        StartCoroutine(Load());
    }

    IEnumerator Load()
    {
        yield return null;
        string url = string.Format("{0}/language.txt", Application.streamingAssetsPath);
        WWW www = new WWW(url);
        while(!www.isDone)
            yield return www;
        string text = www.text;
        Debug.Log(text);
        string[] rows = text.Split("\r\n");
        for (int i = 0; i < rows.Length; i++)
        {
            string[] arr = rows[i].Split('\t');
            int id = int.Parse(arr[0]);
            string value = arr[1];
            value = value.Replace("\\r\\n", "\r\n");
            if (dic.ContainsKey(id))
            {
                Debug.LogErrorFormat("language id({0}) duplicate", id);
                continue;
            }
            dic.Add(id, value);
        }
        Debug.LogFormat("*** language load completed! rows={0}", rows.Length);

        //测试
#if UNITY_EDITOR
        UnitTest();
#endif
    }

    public static string GetValue(int id)
    {
        if (instance == null)
            return string.Empty;
        if (!instance.dic.ContainsKey(id))
            return string.Empty;
        return instance.dic[id];
    }

    public static string GetValueFormat(int id, params object[] args)
    {
        string value = GetValue(id);
        if (string.IsNullOrEmpty(value))
            return string.Empty;
        value = string.Format(value, args);
        return value;
    }

    //单元测试
    public void UnitTest()
    {
        string value1001 = GetValue(1001);
        string value1003 = GetValueFormat(1003, "小李", 29);
        Debug.LogFormat("1001={0}", value1001);
        Debug.LogFormat("1003={0}", value1003);
    }
}

语言包路径:Assets/StreamingAssets/language.txt
2222.png

标签: Unity3d

Powered by emlog  蜀ICP备18021003号-1   sitemap

川公网安备 51019002001593号