1. 程式人生 > >Unity微端場景載入(二)場景資源的下載和顯示

Unity微端場景載入(二)場景資源的下載和顯示

上文中我們已經把場景中的結點全部自動完成打包,生產的有一批的資源包和結點配置檔案.Xml,我們需要把資源和配置檔案上傳到網路上,專案製作中購買了百度網盤,上傳到了網盤上,然後需要記錄每一個資源以及配置檔案的連結路徑,可儲存成txt檔案,然後一起上傳上去。

在資源下載前先將Xml檔案和txt檔案下載下來,這樣就知道了每個節點位置資訊,以及節點資源的連結資訊,具體程式碼如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;
using System.Collections;
using System.Xml;
using System.IO;



class DynamicCreateNode : MonoBehaviour
{
    public string xmlPath;
    public string bundlesUrl;
    private XmlDocument xmlDocument;
    private XmlNodeList xmlNodeList;
    private Queue<string> urlQueue;
    private string[] urlInfo;
    private bool beginLoad;
    private bool IsLoad;
    private int threadCount;

    private  string line;
    private  string url;
    private  string version;

    void Start()
    {
        beginLoad = false;
        threadCount = 0;
        xmlDocument = new XmlDocument();
        urlQueue = new Queue<string>();
        StartCoroutine(DownLoadXml());
        StartCoroutine(DownLoadText());

    }

    void Update()
    {
        if (beginLoad && threadCount < 10 && IsLoad)
        {
            StartCoroutine(DownLoadBundles());
            threadCount++;
        }

    }
    IEnumerator DownLoadBundles()
    {

        int count = urlQueue.Count;
        while (urlQueue.Count > 0 && urlQueue.Count == count)
        {
            line = urlQueue.Dequeue();
            
            urlInfo = line.Split('\t');
            if (urlInfo != null)
            {
                url = urlInfo[0];
                version = urlInfo[1];
            }

            int intVer = int.Parse(version);
            AssetBundle bundle = null;

            WWW www = WWW.LoadFromCacheOrDownload(url, intVer);

            yield return www;
            if (www.error != null)
            {
                Debug.Log("www error = " + www.error);
            }
            if (www.assetBundle.mainAsset != null)
                bundle = www.assetBundle;
            if (bundle.mainAsset != null)
            {
              //  UnityEngine.Object prefab = bundle.LoadAsset(bundle.mainAsset.name) as UnityEngine.Object;
                Debug.Log("www.assetBundle name = " + bundle.mainAsset.name + "  www url = " + url);
                foreach (XmlNode xmlNode in xmlNodeList)
                {
                    string gameObjectName = xmlNode.Attributes["objectName"].Value;
                    string prefabName = xmlNode.Attributes["objectAsset"].Value;
                    string objectGuid = xmlNode.Attributes["objectGuId"].Value;
                    if (prefabName == bundle.mainAsset.name)
                    {
                        GameObject obj = GameObject.Find(objectGuid);
                        UnityEngine.Object prefab = bundle.LoadAsset(bundle.mainAsset.name) as UnityEngine.Object;
                        if (prefab && obj)
                        {
                            Debug.Log("prefab name = " + prefab.name);


                                GameObject loadObj = (GameObject)GameObject.Instantiate(prefab);
                                loadObj.transform.position = obj.transform.position;
                                loadObj.transform.localScale = obj.transform.localScale;
                                loadObj.transform.rotation = obj.transform.rotation;
                                loadObj.transform.parent = obj.transform.parent;
                                loadObj.name = gameObjectName;
                                Destroy(obj);
                        

                        }
                                        
                    }

                }
                if (bundle.mainAsset.name != null)
                {
                    bundle.mainAsset.name = null;
                }

                count = urlQueue.Count;
            }

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

            if (bundle)
            {

                bundle.Unload(false);
            }
        }

    }
    IEnumerator DownLoadXml()
    {

        WWW www = new WWW(xmlPath);
        yield return www;
        byte[] array = www.bytes;
        MemoryStream stream = new MemoryStream(array);             //convert stream 2 string      
        //StreamReader reader = new StreamReader(stream);

        xmlDocument.Load(stream);

        // 使用 XPATH 獲取所有 gameObject 節點
        xmlNodeList = xmlDocument.SelectNodes("//gameObject");
        foreach (XmlNode xmlNode in xmlNodeList)
        {
            string gameObjectName = xmlNode.Attributes["objectName"].Value;
            string prefabName = xmlNode.Attributes["objectAsset"].Value;
            string parentName = xmlNode.Attributes["objectParent"].Value;
            string objectGuid = xmlNode.Attributes["objectGuId"].Value;

            GameObject gameObject = new GameObject(prefabName);
            // 使用 XPATH 獲取 位置、旋轉、縮放資料
            XmlNode positionXmlNode = xmlNode.SelectSingleNode("descendant::position");
            XmlNode rotationXmlNode = xmlNode.SelectSingleNode("descendant::rotation");
            XmlNode scaleXmlNode = xmlNode.SelectSingleNode("descendant::scale");

            if (positionXmlNode != null && rotationXmlNode != null && scaleXmlNode != null)
            {
                gameObject.transform.position = new Vector3(float.Parse(positionXmlNode.Attributes["x"].Value), float.Parse(positionXmlNode.Attributes["y"].Value), float.Parse(positionXmlNode.Attributes["z"].Value));
                gameObject.transform.rotation = Quaternion.Euler(new Vector3(float.Parse(rotationXmlNode.Attributes["x"].Value), float.Parse(rotationXmlNode.Attributes["y"].Value), float.Parse(rotationXmlNode.Attributes["z"].Value)));
                gameObject.transform.localScale = new Vector3(float.Parse(scaleXmlNode.Attributes["x"].Value), float.Parse(scaleXmlNode.Attributes["y"].Value), float.Parse(scaleXmlNode.Attributes["z"].Value));

                GameObject parentObj = GameObject.Find(parentName);
                if (parentObj)
                {
                    gameObject.transform.parent = parentObj.transform;
                    TextMesh mesh = gameObject.AddComponent<TextMesh>();
                    if (mesh != null)
                    {
                        mesh.text = gameObject.name;
                    }

                    gameObject.name = objectGuid;
                }

            }


        }

        beginLoad = true;

    }

    IEnumerator DownLoadText()
    {

        WWW www = new WWW(bundlesUrl);
        yield return www;
        string testurl = www.text;
        Dictionary<string, string> dic = www.responseHeaders;
        Debug.Log("testurl = " + testurl + "end");
        string[] sArr = testurl.Split(new string[] { "\n" }, StringSplitOptions.RemoveEmptyEntries);
        for (int i = 0; i < sArr.Length; i++)
        {
            //Debug.LogFormat("sArr[{0}] = {1}", i, sArr[i]);
            urlQueue.Enqueue(sArr[i]);
        }
        IsLoad = true;

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

    }
    
}

每個場景資源都放一個單獨的目錄,所以需要兩個公有變數來記錄不同場景的連結資訊,在保留場景中做好配置即可。專案製作中做了特效,在資源未下載完成時可以用一個動畫代替,等正真的資源下載成功並顯示後將動畫刪除。如果不需要可以不做位置節點的顯示和刪除。