天天看點

遊戲的加載類要點和架構

不管是端遊,頁遊還是手遊,加載類都是底層重要的一個基本功能,其原理大體都是一樣,隻不過用不同的語言C++,Flash,C#等分别實作而已。這段時間研讀了各種遊戲底層,提煉出一些加載類的共性。由于加載類考慮點較多,容易遺忘。不想遺忘,也不想被人遺忘,不想像op742《我會永遠陪在你身邊》裡的居魯士一樣,中了童樂魔咒,被家人遺忘。

遊戲的加載類要點和架構

事實上,大多數時候都會遺忘,也會被人遺忘。。。

題外話了。作為備忘,本文記錄一個比較成熟的加載類架構和其要點。

考慮線上情況,一般遊戲的加載類需要包括以下幾點需求:

1.  并行加載(2-3個)

2.  重複的url

3.  加密解密

4.  fail重試

5.  優先級

6.  預加載

架構上用三個類劃分,IzLoader(封裝一個基本的附加元件,記錄加載位址,失敗重試次數,優先級,版本号,加載成功回調函數,加載失敗回調函數,加載過程中的回調函數)。IzLoaderPipeLine(待加載的流水線,儲存IzLoader隊列,管理隊列中的IzLoader優先級,重排隊列,并實作下載下傳完畢後的銷毀工作)。IzLoaderTread(挂載在GameObject,用Update每幀檢查IzLoaderPipeLine裡面有沒有待加載的Loader項,有則用www方式加載)。

IzLoader類如下

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

// 異步加載,内部用 WWW 加載
public class IzLoader
{
    public static int ms_iRetryCount = 3;       // 失敗重試次數
    public WWW m_kWWW;  //U3D的www類,其他語言用其他的加載類
    public string m_strURL;//加載位址
    public int m_iPriority;//優先級
    public int m_iVersion;//版本号

    public int m_iRetryCount; //重試次數

    protected List<FINISH_CALLBACK_INFO> m_listFinish;  //成功回調函數隊列
    protected List<FAILED_CALLBACK_INFO> m_listFailed;// 失敗回調函數隊列
    protected List<PROCESS_CALLBACK_INFO> m_listProcess;  //過程處理函數隊列
   
    public IzLoader()
    {
        m_iRetryCount = 0;
    }

    public void AddFinishCallback()
    {
        //添加成功下載下傳回調函數
    }

    public bool RemoveFinishCallback()
    {
        //移除成功下載下傳回調函數
    }

    public void AddFailedCallback()
    {
        //添加失敗下載下傳回調函數
    }

    public bool RemoveFailedCallback()
    {
        //移除失敗下載下傳回調函數
    }

    public void RemoveAllFailedCallback()
    {
        //移除所有失敗下載下傳回調函數
    }

    public void AddProcessCallback()
    {
        //添加下載下傳中回調函數
    }

    public bool RemoveProcessCallback()
    {
        //移除下載下傳中回調函數
    }

    public void RemoveAllProcessCallback()
    {
        //移除下載下傳中所有的回調函數
    }

    public void RemoveAllCallbacks()
    {
        //移除所有回調函數
    }

    public void Load( string strURL, int iPriority = 0, int iVersion = 0 )
    {
        m_strURL = strURL;
        m_iPriority = iPriority;
        m_iVersion = iVersion;

        IzLoadPipeline.ms_kSig.AddItem(this);
    }  
}
           

IzLoaderPipeLine如下

using UnityEngine;
using System.Collections.Generic;

public class IzLoadPipeline
{
    public static IzLoadPipeline ms_kSig;//單例

    private List<IzLoader> m_listLrd;//加載loader項隊列
    private int m_iParallelLoadCount;//并行加載數量
    private int m_iLoadingCount;//正在下載下傳項數量

    public IzLoadPipeline()
    {
        if (ms_kSig != null)
        {
            Debug.LogError("IzLoadPipeline is a singlon!");
            return;
        }
        ms_kSig = this;
        m_listLrd = new List<IzLoader>();
        m_iParallelLoadCount = 2;
        m_iLoadingCount = 0;
    }

    public void SetParallelLoadCount(int iCount)
    {
        //設定并行加載數量
    }

    public void AddItem( IzLoader kLrd )
    {
        //添加一個IzLoader,優先級調整隊列順序
    }

    public void Update()
    {
        /*
         * 檢查是正在加載數是否大于最大值
         * 小于最大值則從下載下傳隊列中取出最優一項
         * 添加OnLoadFinish,OnLoadFailed作為成功和失敗的回調函數,用語去掉附加元件自身的回調函數,并實作失敗重傳
        */
    }

    private void OnLoadFinish(IzLoader kLrd )
    {
        //移除loader的成功和失敗回調函數
    }

    private void OnLoadFailed(IzLoader kLrd )
    {
        //如果重試次數小于最大值,則重新加入到隊列,再試一次
        //如果重試次數大于等于最大值,則放棄,移除所有回調函數
    }
}
           

IzLoderTread類

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

// 此類用于協程加載
// 注意:此類須置于GameObject上最先初始化
public class IzLoadThread : MonoBehaviour
{
    public static IzLoadThread ms_kSig;

    private const float ms_fLoadPercentCheck = 0.05f;

    void Awake()
    {
        if (ms_kSig != null)
        {
            Debug.LogError("IzLoadThread is a singlon!");
            return;
        }
        ms_kSig = this;

        new IzLoadPipeline();
    }
    //調用協程加載
    public void BeginLoad(IzLoader kLrd)
    {
        StartCoroutine("OnRealLoad", kLrd);
    }

    private IEnumerator OnRealLoad(object kArg)
    {
        //www初始化

        //www處理過程中
        while (!www.isDone)
        {
            //執行IzLoader的處理過程中的回調函數
            yield return 1;
        }

        //成功加載
        if (string.IsNullOrEmpty(www.error))
        {
            //執行IzLoader的成功回調函數
        }
        //失敗加載
        else
        {
            //之行IzLoader的失敗回調函數       
        }
    }
    //每幀到IzLoadPipeline加載隊列中抽出可行的附加元件加載
	void Update ()
    {
        IzLoadPipeline.ms_kSig.Update();	
	}    
}
           

總結,這是一個比較輕量的加載架構,基于U3D,沒有實作加密解密過程,但是能滿足一般的需求了。

繼續閱讀