不管是端遊,頁遊還是手遊,加載類都是底層重要的一個基本功能,其原理大體都是一樣,隻不過用不同的語言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,沒有實作加密解密過程,但是能滿足一般的需求了。