Lua快速入门(XLua拓展)(Yanlz+热更新+XLua+[LuaCallCSharp]+[CSharpCallLua]+LuaEnv+LuaTable+MetaTable+LuaManager)

        《Lua热更新》

##《Lua热更新》发布说明:git

++++“Lua热更新”开始了,立钻哥哥终于开始此部分的探索了。github

++++做为游戏发布迭代的重要技术:Lua热更新在网络游戏迭代更新中很是重要,特别是对于AppStore这样的平台,咱们只须要按期更新主App,原则上能够随时灵活更新咱们的以Lua热更新框架为基础的代码。数据库

++++固然,做为一项新引入的技术,咱们一般是以【快速入门】=>【基础夯实】=>【中级进阶】=>【高级实战】=>【立钻哥哥带您学Lua热更新】等几个阶段进行探索。编程

 

##《Lua热更新》目录:canvas

#第一篇:Lua快速入门篇设计模式

#第二篇:Lua基础夯实篇api

#第三篇:Lua中级进阶篇服务器

#第四篇:Lua高级实战篇babel

#第五篇:立钻哥哥带您学Lua热更新网络

 

++++Lua快速入门篇(Xlua拓展):http://www.noobyard.com/article/p-pycycddx-cm.html

++++Lua快速入门篇(XLua教程):http://www.noobyard.com/article/p-plflyruo-ho.html

++++Lua快速入门篇(基础概述)http://www.noobyard.com/article/p-pyzbbriu-u.html

 

 

 

#第一篇:Lua快速入门篇

#第一篇:Lua快速入门篇

++++第一章:Lua基础概述

++++第二章:xLua教程

++++第三章:Lua基础拓展

++++第四章:立钻哥哥带您学Lua热更新

 

 

##第二章:xLua教程

++第二章:xLua教程

++++https://github.com/Tencent/xLua

++++xLua为Unity、.Net、Mono等C#环境增长Lua脚本编程的能力,借助xLua,这些Lua代码能够方便的和C#相互调用。

++++2.一、xLua教程

++++2.二、xLua的配置

++++2.三、热补丁操做指南

++++2.四、XLua增长删除第三方lua库

++++2.五、xLua API

++++2.六、生成引擎二次开发指南

++++2.七、xLua常见问题

++++2.八、xLua示例参考

++++2.九、xLua拓展总结

++++2.十、立钻哥哥带您学xLua

 

 

 

###2.九、xLua拓展总结

###2.九、xLua拓展总结

++2.九、xLua拓展总结

++++立钻哥哥:xLua是Unity的一个插件:Tencent/xLua(腾讯GitHub开源)。

++++C#下Lua编程支持:xLua为Unity、.Net、Mono等C#环境增长Lua脚本编程的能力,借助xLua,这些代码能够方便的和C#相互调用。

++++VS中的Lua插件:babelua。

 

++2.9.一、ExampleGenConfig.cs(lua中使用到C#库的配置)

++++【xLua的配置:静态列表】:有时咱们没法直接给一个类型打标签,好比系统api,没源码的库,或者实例化的泛化类型,这是能够在一个静态类里声明一个静态字段,该字段的类型除[BlackList]和[AdditionalProperties]以外只要实现了IEnumerable<Type>就能够了,而后为这字段加上标签:

[LuaCallCSharp]

public static List<Type> mymodule_lua_call_cs_list = new List<Type>(){

typeof(GameObject),

typeof(Dictionary<string, int>),

};

++++立钻哥哥:这个字段须要放到静态类中,建议放到Editor目录。

++++ExampleGenConfig.cs(xLua-master\Assets\XLua\Examples\ExampleGenConfig.cs)

//立钻哥哥:lua中使用到C#库的配置

using System.Collections.Generic;

using System;

using UnityEngine;

using XLua;

 

public static class ExampleGenConfig{

    //立钻哥哥:lua中要使用到C#库的配置,好比C#标准库,或者Unity API,第三方库

    [LuaCallCSharp]

    public static List<Type> LuaCallCSharp = new List<Type>(){

        typeof(System.Object),

        typeof(UnityEngine.Object),

        typeof(Vector2),

        typeof(Vector3),

        typeof(Vector4),

        typeof(Quaternion),

        typeof(Color),

        typeof(Ray),

        typeof(Bounds),

        typeof(Ray2D),

        typeof(Time),

        typeof(GameObject),

        typeof(Component),

        typeof(Behaviour),

        typeof(Transform),

        typeof(Resources),

        typeof(TextAsset),

        typeof(Keyframe),

        typeof(AnimationCurve),

        typeof(AnimationClip),

        typeof(MonoBehaviour),

        typeof(ParticleSystem),

        typeof(SkinnedMeshRenderer),

        typeof(Renderer),

        typeof(WWW),

        typeof(Light),

        typeof(Mathf),

        typeof(System.Collection.Generic.List<int>),

        typeof(Action<string>),

        typeof(UnityEngine.Debug),

    };    //立钻哥哥:public static List<Type> LuaCallCSharp = new List<Type>(){}

 

    //立钻哥哥:C #静态调用Lua的配置(包括事件的原型),仅能够配delegate,interface

    [CSharpCallLua]

    public static List<Type> CSharpCallLua = new List<Type>(){

        typeof(Action),

        typeof(Func<double, double, double>),

        typeof(Action<string>),

        typeof(Action<double>),

        typeof(UnityEngine.Events.UnityAction),

        typeof(System.Collections.IEnumerator),

    };    //立钻哥哥:public static List<Type> CSharpCallLua = new list<Type>(){}

 

    //立钻哥哥:黑名单

    [BlackList]

    public static List<List<string>> BlackList = new List<List<string>>(){

        new List<string>(){  System.Xml.XmlNodeList, ItemOf  },

        new List<string>(){  UnityEngine.WWW, movie  },

    

        #if UNITY_WEBGL

            new List<string>(){  UnityEngine.WWW, threadPriority  },

        #endif

 

        new List<string>(){  UnityEngine.Texture2D, alphaIsTransparency  },

        new List<string>(){  UnityEngine.Security, GetChainOfTrustVaue  },

        new List<string>(){  UnityEngine.CanvasRenderer, onRequestRebuild  },

        new List<string>(){  UnityEngine.Light,  areaSize},

    };    //立钻哥哥:public static List<List<string>> BlackList = new List<List<string>>(){}

 

}    //立钻哥哥:public static class ExampleGenConfig{}

 

++2.9.二、LuaBehaviour.cs(立钻哥哥:很是重要)

//立钻哥哥:很是重要(\Assets\XLua\Examples\02_U3DScripting\LuaBehaviour.cs)

using UnityEngine;

using System.Collections;

using System.Collections.Generic;

using XLua;

using System;

 

[System.Serializable]

public class Injection{

    public string name;

    public GameObject value;

}    //立钻哥哥:public class Injecton{}

 

[LuaCallCSharp]

public class LuaBehaviour : MonoBehaviour{

    public TextAsset luaScript;

    public Injection[] injections;

 

    internal static LuaEnv luaEnv = new LuaEnv();  //all lua behaviour shared one luaenv only

    internal static float lastGCTime = 0;

    internal const float GCInterval = 1;    //1 second

 

    private Action luaStart;

    private Action luaUpdate;

    private Action luaOnDestroy;

 

    private LuaTable scriptEnv;

 

    void Awake(){

        scriptEnv = luaEnv.NewTable();

    

        //立钻哥哥:为每一个脚本设置一个独立的环境,可必定程度上防止脚本间全局变量、函数冲突

        LuaTable meta = luaEnv.NewTable();

        meta.Set(__index, luaEnv.Global);

        scriptEnv.SetMetaTable(meta);

        meta.Dispose();

 

        scriptEnv.Set(self, this);

        foreach(var injection in injections){

            scriptEnv.Set(injection.name, injection.value);

        }

 

        luaEnv.DoString(luaScript.text, LuaBehaviour, scriptEnv);

 

        Action luaAwake = scriptEnv.Get<Action>(awake);

        scriptEnv.Get(start, out luaStart);

        scriptEnv.Get(update, out luaUpdate);

        scriptEnv.Get(ondestroy, out luaOnDestroy);

 

        if(luaAwake != null){

            luaAwake();

        }

    }

 

    //Use this for initialization

    void Start(){

        if(luaStart != null){

            luaStart();

        }

    }

 

    //Update is called once per frame

    void Update(){

        if(luaUpdate != null){

            luaUpdate();

        }

 

        if(Time.time - LuaBehaviour.lastGCTime > GCInterval){

            luaEnv.Tick();

            LuaBehaviour.lastGCTime = Time.time;

        }

    }

 

    void OnDestroy(){

        if(luaOnDestroy != null){

            luaOnDestroy();

        }

 

        luaOnDestroy = null;

        luaUpdate = null;

        luaStart = null;

        scriptEnv.Dispose();

        Injections = null;

    }

 

}    //立钻哥哥:public class LuaBehaviour : MonoBehaviour{}

 

++2.9.三、LuaEnv(all lua hehaviour shared one luaenv only)

++++立钻哥哥:能够利用一个LuaMananger来管理全局惟一的LuaEnv。

++++internal static LuaEnv lueEnv = new LuaEnv();

 

++2.9.四、LuaTable(表)

++++private LuaTable scriptEnv;

++++scriptEnv = luaEnv.NewTable();

++++scrptEnv.Set(self, this);

++++luaEnv.DoString(luaScript.text, LuaBehaviour, scriptEnv);

 

++2.9.六、获取生命周期函数(Awake()、Start()、Update()、OnDestroy()等)

++++private Action luaState;

++++private Action luaUpdate;

++++private Action luaOnDestroy;

++++Action luaAwake = scriptEnv.Get<Action>(awake);

++++scriptEnv.Get(start, out luaStart);    //等同:luaStart = scriptEnv.Get<Action>(start);

++++scriptEnv.Get(update, out luaUpdate);

++++scriptEnv.Get(ondestroy, out luaOnDestroy);

 

++2.9.七、热更新流程

++++立钻哥哥:热更新流程:

--【第一步:游戏运行】(检测资源,进行对比更新)

    ----游戏要更新了,就打包,放到服务器目录下。

    ----客户端运行的时候,先下载服务器的校验文件(对比本地文件的md5码)。

    ----有更新,就下载这些文件替换本地文件。

--【第二步:加载资源,开始游戏的主逻辑】

 

++2.9.八、建立校验文件

++++立钻哥哥:建立校验文件(包括资源和lua等信息),供热更新下载。

//立钻哥哥:建立校验文件(AssetBundleEditor.cs)

public class AssetBundleEditor{

   

    //立钻哥哥:打包

    [MenuItem(AssetBundle/Build AssetBundles)]

    static void BuildAllAssetBundle(){

        string outPath = PathUtil.GetAssetBundleOutPath();

        BuildPipeline.BuildAssetBundler(outPath, 0, BuildTarget.StandaloneWindows64);

    }

 

    //立钻哥哥:建立校验文件

    [MenuItem(Tools/Create Files)]

    static void CreateFiles(){

        string outPath = PathUtil.GetAssetBundleOutPath();  //StreamingAssets/Windows

        string filePath = outPath + /files.txt;  //校验文件的路径

 

        if(File.Exists(filePath)){

            File.Delete(filePath);

        }

 

        //遍历这个文件夹下面的全部文件

        List<string> fileList = new List<string>();

        listFiles(new DirectoryInfo(outPath), ref fileList);

 

        FileStream fs = new FileStream(filePath, FileMode.CreateNew);

        StreamWriter sw = new StreamWriter(fs);

 

        for(int i = 0; i < fileList.Count; i++){

            string file = fileList[i];

            string ext = Path.GetExtension(file);    //立钻哥哥:获取后缀

            if(ext.EndsWith(.meta)){

                continue;    //立钻哥哥:不包括Unity的垃圾配置.meta

            }

 

            //生成这个文件对应的md5值

            string md5 = getFileMd5(file);

            string value = file.Replace(outPath + /, string.Empty); //立钻哥哥:仅取文件名

            sw.WriteLine(value + | + md5);    //写入到文件

        }

 

        sw.Close();

        fs.Close();   //立钻哥哥:记得释放

    }

 

    //立钻哥哥:遍历文件夹下的全部文件

    static void listFiles(FileSystemInfo fileSystemInfo, ref List<string> fileList){

        DirectoryInfo directoryInfo = fileSystemInfo as DirectoryInfo;

        FileSystemInfo[] infos = directoryInfo.GetFileSystemInfos();  //获取全部的文件系统

    

        foreach(var info in infos){

            FileInfo fileInfo = info as FileInfo;

 

            if(fileInfo != null){

                fileList.Add(fileInfo.FullName.Replace(\\, /));    //若是是文件

            }else{

                listFiles(info, fileList);    //立钻哥哥:递归调用读取文件夹下全部文件

            }

        }

    }

 

    //立钻哥哥:获取文件的md5值

    static void getFileMd5(string filePath){

        FileStream fs = new FileStream(filePath, FileMode.Open);

        MD5 md5 = new MD5CryptoServiceProvider();

 

        byte[] result = md5.ComputeHash(fs);

 

        fs.Close();

 

        StringBuilder sb = new StringBuilder();

        for(int i = 0;  i < result.Length;  i++){

            sb.Append(result[i].ToString(x2));

        }

 

        return sb.ToString();

    }

 

}    //立钻哥哥:public class AssetBundleEditor{}

 

 

++2.9.九、GameInit功能完善

++++立钻哥哥:GameInit.cs功能完善

//立钻哥哥:更新资源

using System.Collections;

using System.Collections.Generic;

using UnityEngine;

using UnityEngine.UI;

using System.IO;

using System.Text;

 

//立钻哥哥:这个脚本是最早执行的

public class GameInit : MonoBehaviour{

    private string downloadPath;    //立钻哥哥:不要在此赋值(仅声明,Awake赋值)

 

    void Awake(){

        downloadPath = PathUtil.GetAssetBundleOutPath();   //立钻哥哥:赋值在Awake

 

        //检测资源进行对比跟新

        StartCoroutine(downloadRes());

 

        //开始游戏的主逻辑

 

    }

 

    //立钻哥哥:检测资源

    private IEnumerator downloadRes(){

        string url = http://立钻哥哥:6066/Path/;

 

        string fileUrl = url + files.txt;

        WWW www = new WWW(fileUrl);

        yield return www;

 

        //进行一些网络检测

        if(www.error != null){

            Debug.LogError(www.error);

        }

 

        //判断本地有没有这个目录

        //立钻哥哥:若是发布到手机上:游戏一运行,就把streamingAssets的文件拷贝到persistentDataPath路径下

 

        if(!Directory.Exists(downloadPath)){

            Directory.CreateDirectory(downloadPath);

        }

 

        //把下载的文件写入本地

        File.WriteAllBytes(downloadPath + /files.txt, www.bytes);

 

        //读取files里面的内容

        string filesText = www.text;

        string[] lines = filesText.Split(\n);

 

        for(int i = 0;  i < lines.Length;  i++){

            if(string.IsNullOrEmpty(lines[i])){

                continue;

            }

 

            string[] kv = lines[i].Split(|);

            string fileName = kv[0];

 

            //拿到本地的这个文件

            string localFile = (downloadPath + / + fileName).Trim();

 

            //若是本地文件没有,须要下载了

            if(!File.Exists(localFile)){

                string dir = Path.GetDirectoryName(localFile);

                Directory.CreateDirectory(dir);

 

                //开始网络下载

                string tmpUrl = url + fileName;

                www = new WWW(tmpUrl);

                yield return www;

    

                //进行一些网络的检测

                if(www.error != null){

                    Debug.LogError(www.error);

                }

 

                   File.WriteAllBytes(localFile, www.bytes);

              }else{

                //若是文件有,开始比对md5(做用:检测是否须要更新)

 

                string md5 = kv[1];

                string localMd5 = getFileMd5(localFile);

 

                if(md5 == localMd5){

                    //若是md5同样的话,那么就没更新

 

                }else{

                    //若是不同的话,说明更新了

                    File.Delete(localFile);    //删除本地原来的旧文件

    

                    //下载新文件

                    string tmpUrl = url + fileName;

                    www = new WWW(tmpUrl);

                    yield return www;

 

                    //进行一些网络检测

                   if(www.error != null){

                        Debug.LogError(www.error);

                    }

 

                    File.WriteAllBytes(localFile, www.bytes);

                }

            }

        }

 

        yield return new WaitForEndOfFrame();

 

        Debug.Log(立钻哥哥:更新完成,能够开始游戏了!);

 

    }    //立钻哥哥:private IEnumerator downloadRes(){ }

 

 

    //获取文件的md5值

    private string getFileMd5(string filePath){

        FileStream fs = new FileStream(filePath, FileMode.Open);

        MD5 md5 = new MD5CryptoServiceProvider();

    

        byte[] result = md5.ComputeHash(fs);

        fs.Close();

    

        StringBuilder sb = new StringBuilder();

        for(int i = 0;  i < result.Length;  i++){

            sb.Append(result[i].ToString(x2));

        }

 

        return sb.ToString();

    }    //立钻哥哥:private string getFileMd5(){}

 

}    //立钻哥哥:public class GameInit:MonoBehaviour{}

 

//立钻哥哥:加载资源包(AssetBundleLoader.cs)

//加载资源包

public IEnumerator Load(){

    www = new WWW(bundlePath);

 

    //AssetBundleCreateRequest abcr = AssetBundle.loadFromFileAsync(bundlePath);

    //yield return abcr;

 

    while(!www.isDone){

        this.progress = www.progress;

    

        //每一帧来调用一次,更新加载进度

        if(lp != null){

            lp(bundleName, progress);

        }

 

        yield return www;

    }

 

    progress = www.progress;

 

    if(progress >= 1f){

        //加载完成了

        assetLoader = new AssetLoader();

        assetLoader.AssetBundle = www.assetBundle;

 

        //每一帧来调用一次,更新加载进度

        if(lp != null){

            pp(bundleName, progress);

        }

 

        if(lc != null){

            lc(bundleName);

        }

    }

 

}    //立钻哥哥:public IEnumerator Load(){}

 

 

++2.9.十、dowloadRes4Test()本地模拟测试

++++立钻哥哥:检测资源本机测试

private IEnumerator downloadRes4Test(){

    string url = C:/YanlzLuaServer;

    string fileUrl = url + files.txt;

 

    //判断本地没有这个文件

    if(!Directory.Exists(downloadPath)){

        Directory.CreateDirectory(downloadPath);

    }

 

    //读取files里面的内容

    string[] lines = File.ReadAllLines(fileUrl);

 

    for(int i = 0;  i < lines.Length;  i++){

        if(string.IsNullOrEmpty(lines[i])){

            continue;

        }

 

        string[] kv = lines[i].Split(|);

        string fileName = kv[0];

 

        //拿到本地的这个文件

        string localFile = (downloadPath + / + fileName).Trim();

 

        //若是本地文件没有,须要下载

        if(!File.Exists(localFile)){

            Debug.Log(立钻哥哥:本地没有  + fileName +   去服务器下载了);

 

            string dir = Path.GetDirectoryName(localFile);

            Directory.CreateDirectory(dir);

 

            //开始网络下载

            string tmpUrl = url + / + fileName;

            string tmpText = File.ReadAllText(tmpUrl);

            File.WriteAllText(localFile, tmpText);

 

        }else{

            //若是文件files有,开始比对md5(做用:检测是否须要更新)

            string md5 = kv[1];

            string localMd5 = getFileMd5(localFile);

            if(md5 == localMd5){

                //立钻哥哥:若是md5同样的话,就不须要更新

                Debug.Log(立钻哥哥:本地有  + fileName +  并且不须要更新);

            }else{

                Debug.Log(立钻哥哥:本地有 +fileName + 须要更新,去服务器下载);

 

                //若是不同的话,须要更新

                File.Delete(localFile);    //删除本地原来的旧文件

    

                //下载新文件

                string tmpUrl = url + / + fileName;

                string tmpText = File.ReadAllText(tmpUrl);

                File.WriteAllText(localFile, tmpText);

            }

        }

    }

 

    yield return new WaitForEndOfFrame();

 

    Debug.Log(立钻哥哥:更新完成了,能够开始游戏了。);

 

}    //立钻哥哥:private IEnumerator downloadRes4Test(){}

 

 

 

++2.9.十一、热更新LuaManager

++++立钻哥哥:建立UI:【Scene】=>【Canvas】=>【Image】/【Text】

++++lua热更新框架:xLua(Assets/Plugins + Assets/XLua)

++++LuaManager管理全部lua脚本

//立钻哥哥:添加LuaManager

//GameInit.cs

using System.Collections;

using UnityEngine;

 

public class GameInit : MonoBehaviour{

    private string downloadPath;

 

    void Awake(){

        downloadPath = PathUtil.GetAssetBundleOutPath();

    

        //检测资源进行比对跟新

        StartCoroutine(downloadRes4Test());

 

        //开始游戏的主逻辑

        gameObject.AddComponent<AssetBundleManager>();

        gameObject.AddComponent<LuaManager>();    //立钻哥哥:添加LuaManager

        LuaManager.Instance.DoString(require MyLuaGameInit’”);

    }

 

}    //立钻哥哥:public class GameInit : MonoBehaviour{}

 

//立钻哥哥:LuaManager

using System.Collections;

using System.Collections.Generic;

using UnityEngine;

using UnityEngine.UI;

using XLua;

 

//立钻哥哥Lua管理

public class LuaManager : MonoBehaviour{

    public static LuaManager Instance;

 

    private LuaEnv luaEnv = new LuaEnv();

 

    private void Awake(){

        Instance = this;

 

        luaEnv.AddLoader(myCustomLoader);    //立钻哥哥:注册自定义loader

    }

 

    //立钻哥哥:执行lua代码

    public void DoString(string chunk, string chunkName = chunk, LuaTable env = null){

        luaEnv.DoString(chunk, chunkName, env);

    }

 

    //立钻哥哥:调用lua方法

    public object[] CallLuaFunction(string luaName, string methodName, params object[] args){

        LuaTable table = luaEnv.Global.Get<LuaTable>(luaName);

        LuaFunction function = table.Get<LuaFunction>(methodName);

        return function.Call(args);

    }

 

    Dictionary<string byte[]> dict = new Dictionary<string, byte[]>();

 

    private byte[] myCustomLoader(ref string fileName){

        //获取lua所在的目录

        string luaPath = PathUtil.GetAssetBundleOutPath() + /Lua;

 

        if(dict.ContainKey(fileName)){

            return dict[fileName];

        }

    

        return processDir(new DirectoryInfo(luaPath), fileName);

    }

 

    private byte[] processDir(FileSystemInfo fileSystemInfo, string fileName){

        DirectoryInfo directoryInfo = fileSystemInfo as DirectoryInfo;

        FileSystemInfo[] files = directoryInfo.GetFileSystemInfo();

        foreach(var item in files){

            FileInfo file = item as FileInfo;

            if(file == null){

                processDir(item, fileName);    //不是文件,是文件夹的话,递归执行

            }else{

                string tmpName = item.Name.Split(.)[0];    //仅取文件名,不要后缀

                if(item.Extension == .meta || tmpName != fileName){

                    continue;

                }

 

                byte[] bytes = File.ReadAllBytes(file.FullName);

                dict.Add(fileName, bytes);    //思路:利用空间换时间(存入Dictionary)

                return bytes;

            }

        }

 

        return null;

    }    //立钻哥哥:private byte[] processDir(){}

 

}    //立钻哥哥:public class LuaManager : MonoBehaviour{}

 

//立钻哥哥:lua文件

//xLua除了原生的loader外,还添加了从Resource加载的loader,须要注意的是:Resource只支持有限的后缀,放Resources下的lua文件得加上txt后缀。

//可是:lua文件是从热更新下来的,通常不在Resources目录下,因此须要自定义Loader,自定义涉及接口:public delegate byte[] CustomLoader(ref string filepath);

//public void LuaEnv.AddLoader(CustomLoader loader); 经过AddLoader能够注册一个回调,该回调参数是字符串,lua代码里头调用require时,参数将会透传给回调,回调中就能够根据这个参数去加载指定文件。

//MyLuaGameInit.lua.txt

print(立钻哥哥)

 

 

 

++2.9.十二、AssetBundleManager.cs

++++立钻哥哥:AB管理器

using System.Collections;

using System.Collections.Generic;

using UnityEngine;

using UnityEngine.UI;

 

//立钻哥哥:AssetBundle管理类

public class AssetBundleManager : MonoBehaviour{

    private static AssetBundleManager instance;

 

    //单例模式

    public static AssetBundleManager Instance{

        get{  return instance;  };

     }

 

    void Awake(){

        instance = this;

    

        //先加载mainfest文件

        StartCoroutine(AssetBundleMainfestLoader.Instance.Load());

    }

 

    void OnDestroy(){

        nameSceneDict.Clear();

        Resource.UnloadUnusedAssets();

        System.CS.Collect();

    }

 

    //场景名 和 场景里面全部包的管理 的映射

    Dictionary<string, SceneManager> nameSceneDict = new Dictionary<string, SceneManager>();

 

    //加载资源包

    public void LoadAssetBundle(string sceneName, string folderName, LoadProgress lp){

        if(!nameSceneDict.ContainKey(sceneName)){

            //若是没有这个场景,先建立这个场景,再读取一下

            createSceneAssetBundles(sceneName);

        }

 

        SceneManager sceneManager = nameSceneDict[sceneName];

 

        //开始加载

        sceneManager.LoadAssetBundle(folderName, lp, loadAssetBundleCallback);

    }

 

    //建立一个场景对应的包

    private void createSceneAssetBundles(string sceneName){

        SceneManager scene = new SceneManager(sceneName);

        scene.ReadRecord(sceneName);    //读取记录文件

    

        nameSceneDict.Add(sceneName, scene);

    }

 

    //加载资源的回调

    private void loadAssetBundleCallback(string sceneName, string bundleName){

        if(nameSceneDict.ContainsKey(sceneName)){

            SceneManager sceneManager = nameSceneDict[sceneName];

            StartCoroutine(sceneManager.Load(bundleName));

 

        }else{

            Debug.Log(立钻哥哥:不存在这个场景:   + sceneName);

        }

    }

 

    //获取完整包名

    public string GetBundleName(string sceneName, string folderName){

        if(nameSceneDict.ContainsKey(sceneName)){

            SceneManager sceneManager = nameSceneDict[sceneName];

            return sceneManger.GetBundleName(folderName);

 

        }else{

            Debug.Log(立钻哥哥:不存在这个场景:  + sceneName);

            return null;

        }

    }

 

    //是否加载了这个包

    public bool IsLoading(string sceneName, string folderName){

        if(nameSceneDict.ContainsKey(sceneName)){

            SceneManager sceneManager = nameSceneDict[sceneName];

            return sceneManager.IsLoading(folderName);

 

        }else{

            Debug.LoaError(立钻哥哥:不存在这个场景: + sceneName);

            return false;

        }

    }

 

    //是否加载完成这个包

    public bool IsFinish(string sceneName, string folderName){

        if(nameSceneDict.ContainsKey(sceneName)){

            SceneManager sceneManager = nameSceneDict[sceneName];

            return sceneManager.IsFinish(folderName);

 

        }else{

            Debug.Log(立钻哥哥:不存在这个场景: + sceneName);

            return false;

        }

    }

 

}    //立钻哥哥:public class AssetBundleManager : MonoBehaviour{}

 

 

 

++2.9.1三、AssetUtil.cs

++++立钻哥哥:工具类

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

 

//加载进度

public delegate void LoadProgress(string bundleName, float progress);

 

//加载完成时候的调用

public delegate void LoadComplete(string bundleName);

 

//加载assetbundle的回调

public delegate void LoadAssetBundleCallBack(string sceneName, string bundleName);

 

public class AssetUtil{

}    //立钻哥哥:public class AssetUtil{}

 

 

 

++2.9.1四、SceneManager:LoadAssetBundle()

++++立钻哥哥:场景管理器

//加载资源包

public void LoadAssetBundle(string folderName, LoadProgress lp, LoadAssetBundleCallback labcb){

    if(folderBundleDict.ContainsKey(folderName)){

        string bundleName = folderBundleDict[folderName];    //获取包名

        sceneAssetBundles.LoadAssetBundle(bundName, lp, labcb);

 

    }else{

        Debug.Log(立钻哥哥:找不到这个文件夹: + folderName +  对应的包);

    }

}

 

 

 

++2.9.1五、OneSceneAssetBundles:LoadAssetBundle()

++++立钻哥哥:加载资源包

//加载资源包

public void LoadAssetBundle(string bundleName, LoadProgress lp, LoadAssetBundleCallback labcb){

    //若是这个包已经被加载了,就提示

    if(nameBundleDict.ContainsKey(bundleName)){

        Debug.Log(立钻哥哥:此包已经加载了:  + bundleName);

        return;

 

    }else{

        //没有被加载

        AssetBundleRelation assetBundleRelation = new AssetBundleRelation(bundleName, lp);

        nameBundleDic.Add(bundleName, assetBundleRelation);    //保存到字典

        //StartCoroutine(Load, bundleName);

 

        //开始加载

        labcb(sceneName, bundleName);

    }

}

 

//加载包

public IEnumerator Load(string bundleName){

    while(!AssetBundleManifestLoader.Instance.Finish){

         yield return null;

    }

 

    AssetBundleRelation assetBundleRelation = nameBundleDict[bundleName];

 

    //先获取这个包的全部依赖关系

    string[] dependenceBundles = AssetBundleManifestLoader.Instance.GetDependencies(bundleName);

 

    //添加他的依赖关系

    foreach(var dependencebundleName in dependenceBundles){

        assetBundleRelation.AddDependence(dependenceBundleName);

 

        //加载这个包的全部依赖关系

        yield return LoadDependence(dependencebundleName, bundleName, assetBundleRelation.LoadProgress);

    }

 

    //开始加载这个包

    yield return assetBundleRelation.Load()

}

 

//加载依赖的包

private IEnumerator LoadDependence(string bundleName, string referenceBundleName, LoadProgress lp){

    if(nameBundleDict.ContainsKey(bundleName)){

        //已经加载过 就直接添加他的被依赖关系

        AssetBundleRelation assetBundleRelation = nameBundleDict[bundleName];

 

        //添加这个包的被依赖关系

        assetBundleRelation.AddReference(referenceBundleName);

 

    }else{

        //没有加载过 就建立一个新的

        AssetBundleRelation assetBundleRelation = new AssetBundleRelation(bundleName, lp);

 

        //添加这个包的被依赖关系

        assetBundleRelation.AddReference(referenceBundleName);

        nameBundleDict.Add(bundleName, assetBundleRelation);    //保存到字典

    }

}    //立钻哥哥:private IEumerator LoadDependence(){}

 

 

 

++2.9.1六、AssetBundleRelation

//立钻哥哥:构造函数

public AssetBundleRelation(string bundleName, LoadProgress lp){

    this.bundleName = bundleName;

    this.lp = lp;

    this.finish = false;

 

    assetBundleLoder = new AssetBundleLoader(onLoadComplete, lp, bundleName);

 

    dependenceBundleList = new List<string>();

    referenceBundleList = new List<string>();

}

 

 

 

++2.9.1七、AssetBundleLoader

private AssetLoader assetLoader;    //包里的资源

private WWW www;    //WWW对象

private string bundleName;    //包名

private string bundlePath;    //包的路径

private float progress;    //进度

private LoadProgress lp;    //加载进度回调

private LoadComplete lc;    //加载完成回调

 

//立钻哥哥:构造函数

public AssetBundleLoader(LoadComplete lc, LoadProgress lp, string bundleName){

    this.lc = lc;

    this.lp = lp;

    this.bundleName = bundleName;

    this.progress = 0f;

 

    //TODO

    this.bundlePath = PathUtil.GetWWWPath() + / + bundleName;

    this.www = null;

    this.assetLoader = null;

}

 

//加载资源包

public IEnumerator Load(){

    www = new WWW(bundlePath);

 

    //AssetBundleCreateRequest abcr = AssetBundle.LoadFromFileAsync(bundlePath);

    //yield return abcr;

 

    while(!www.isDone){

        this.progress = www.progress;

 

        //每一帧来调用一次,更新加载进度

        if(lp != null){

            lp(bundleName, progress);

        }

 

        yield return www;

    }

 

    progress = www.progress;

    if(progress >= 1f){

        //加载完成了

        assetLoader = new AssetLoader();

        assetLoader.AssetBundle = www.assetBundle;

 

        //每一帧来调用一次,更新加载进度

        if(lp != null){

            lp(bundleName, progress);

        }

 

        if(lc != null){

            lc(bundleName);

        }

    }

}    //立钻哥哥:public IEnumerator Load(){}

 

 

 

++2.9.1八、MyLuaGameInit.lua

++++立钻哥哥:lua文件

MyLuaGameInit = {}

local this = MyLuaGameInit

 

//立钻哥哥:相似C#单例模式的演绎

function MyLuaGameInit : GetInstance()

    return this

end

 

MyLuaGameInit.lp = function(name, process)

    print(name, process)

end

 

function MyLuaGameInit : Init()

    CS.AssetBundleManager.Instance.LoadAssetBundle(main, UI, this.lp);

end

 

//立钻哥哥:GameInit.cs调用Lua

public class GameInit : MonoBehaviour{

    private string downloadPath;

 

    void Awake(){

        downloadPath = PathUtil.GetAssetBundleOutPath();

    

        //检测资源进行比对更新

        StartCoroutine(downloadRes4Test());

 

        //开始游戏的主逻辑

        gameObject.AddComponent<AssetBundleManager>();

        gameObject.AddComponent<LuaManager>();

        LuaManager.Instance.DoString(require MyLuaGameInit’”);    //执行lua脚本

        LuaManager.Instance.CallLuaFunction(MyLuaGameInit, Init);

    }

 

}    //立钻哥哥:public class GameInit : MonoBehaviour{}

 

 

 

++2.9.1九、MyLuaGameInit.lua完善

++++立钻哥哥:完整lua脚本

MyLuaGameInit = {}

 

local this = MyLuaGameInit

 

function MyLuaGameInit : GetInstance()

    return this

end

 

MyLuaGameInit.lp = function(name, process)

    print(name, process)

 

    if process >= 1 then

        local prefab = CS.AssetBundleManager.Instance.LoadAsset(Main, UI, Canvas)

        print(prefab.name)

        local canvas = CS.UnityEngine.GameObject.Instantiate(prefab)  //静态方法.(:)

        canvas.transform:Find(txtCont):GetComponent(typeof(CS.UnityEngine.UI.Text)).text = 立钻哥哥:今日有更新

    end

end

 

function MyLuaGameInit:Init()

    CS.AssetBundleManager.Instance:LoadAssetBundle(Main, UI, this.lp);

end

 

 

 

++2.9.20、PathUtil.cs(路径相关工具类)

using UnityEngine;

using System.IO;

 

//立钻哥哥:路径

public class PathUtil{

    //获取assetbundle的输出目录

    public static string GetAssetBundleOutPath(){

        string outPath = getPlatformPath() + / + GetPlatformName();

    

        if(!Directory.Exists(outPath)){

            Directory.CreateDirectory(outPath);

        }

 

        return outPath;

    }    //立钻哥哥:public static string GetAssetBundleOutPath(){}

 

    //自动获取对应平台的路径

    private static string getPlatformPath(){

        switch(Application.platform){

            case RuntimePlatform.WindowsPlayer:

            case RuntimePlatform.WindowsEditor:

                return Appliction.streamingAssetsPath;

            case RuntimePlatform.Android:

                return Applictiaon.persistentDataPath;

            default:

                return null;

        }

    }    //立钻哥哥:private static string getPlatformPath(){}

 

    //立钻哥哥:获取对应平台的名字

    public static string GetPlatformName(){

        switch(Application.platform){

            case RuntimePlatform.WindowsPlayer:

            case RuntimePlatform.WindowsEditor:

                return Windows;

            case RuntimePlatform.Android:

                return Android;

            default:

                return null;

        }

    }    //立钻哥哥:public static string GetPlatformName(){}

 

}    //立钻哥哥:public class PathUtil{}

 

 

 

 

++立钻哥哥推荐的拓展学习连接(Link_Url)

++++立钻哥哥Unity 学习空间: http://blog.csdn.net/VRunSoftYanlz/

++++Lua快速入门篇(Xlua拓展):http://www.noobyard.com/article/p-pycycddx-cm.html

++++Lua快速入门篇(XLua教程):http://www.noobyard.com/article/p-plflyruo-ho.html

++++Lua快速入门篇(基础概述)http://www.noobyard.com/article/p-pyzbbriu-u.html

++++框架知识点http://www.noobyard.com/article/p-pjzrrjmm-u.html

++++游戏框架(UI框架夯实篇)http://www.noobyard.com/article/p-nnroewdy-cu.html

++++游戏框架(初探篇)http://www.noobyard.com/article/p-klkilyrt-hy.html

++++设计模式简单整理http://www.noobyard.com/article/p-scmbzocc-hg.html

++++U3D小项目参考https://blog.csdn.net/vrunsoftyanlz/article/details/80141811

++++UML类图http://www.noobyard.com/article/p-aakurcwi-bm.html

++++Unity知识点0001http://www.noobyard.com/article/p-bqmetnys-ep.html

++++Unity知识点0008http://www.noobyard.com/article/p-etezylqh-gu.html

++++U3D_Shader编程(第一篇:快速入门篇)http://www.noobyard.com/article/p-ptwlpwbc-gz.html

++++U3D_Shader编程(第二篇:基础夯实篇)http://www.noobyard.com/article/p-dadqpvvp-hv.html

++++Unity引擎基础http://www.noobyard.com/article/p-ggcuedyq-ka.html

++++Unity面向组件开发http://www.noobyard.com/article/p-eiunlkzw-dt.html

++++Unity物理系统http://www.noobyard.com/article/p-mcqnwufb-kd.html

++++Unity2D平台开发http://www.noobyard.com/article/p-brjbvtac-hs.html

++++UGUI基础http://www.noobyard.com/article/p-nvzrvath-mc.html

++++UGUI进阶http://www.noobyard.com/article/p-tpspjolu-gt.html

++++UGUI综合http://www.noobyard.com/article/p-nfgrebqx-gg.html

++++Unity动画系统基础http://www.noobyard.com/article/p-otjpnbzz-dq.html

++++Unity动画系统进阶http://www.noobyard.com/article/p-hxghrtgb-bp.html

++++Navigation导航系统http://www.noobyard.com/article/p-skpvrobt-t.html

++++Unity特效渲染http://www.noobyard.com/article/p-sudpqrhk-bp.html

++++Unity数据存储http://www.noobyard.com/article/p-ybvcceul-m.html

++++Unity中Sqlite数据库http://www.noobyard.com/article/p-vxpuqxev-ca.html

++++WWW类和协程http://www.noobyard.com/article/p-alggjlwu-cy.html

++++Unity网络http://www.noobyard.com/article/p-bjvfgzwg-dw.html

++++C#事件http://www.noobyard.com/article/p-dietpjzv-gm.html

++++C#委托http://www.noobyard.com/article/p-oiohmxtc-gh.html

++++C#集合http://www.noobyard.com/article/p-vdfpislb-ex.html

++++C#泛型http://www.noobyard.com/article/p-vujvnprk-ee.html

++++C#接口http://www.noobyard.com/article/p-emexlwmu-dm.html

++++C#静态类https://blog.csdn.net/vrunsoftyanlz/article/details/78630979

++++C#中System.String类http://www.noobyard.com/article/p-uchiaxzw-cq.html

++++C#数据类型http://www.noobyard.com/article/p-kqtbvoyq-ba.html

++++Unity3D默认的快捷键http://www.noobyard.com/article/p-gbllyjbs-s.html

++++游戏相关缩写http://www.noobyard.com/article/p-pzpxsztf-gm.html

++++立钻哥哥Unity 学习空间: http://blog.csdn.net/VRunSoftYanlz/

 

--_--VRunSoft : lovezuanzuan--_--