LuaFramework 学习
LuaFramework_UGUI_V2 https://github.com/jarjin/LuaFramework_UGUI_V2
using UnityEngine; using LuaInterface; using System.Collections; using System.Collections.Generic; using System; using UnityEngine.UI; namespace LuaFramework { public class LuaBehaviour : View { private string data = null; private Dictionary<string, LuaFunction> buttons = new Dictionary<string, LuaFunction>(); protected void Awake() { Util.CallMethod(name, "Awake", gameObject); } protected void Start() { Util.CallMethod(name, "Start"); } protected void OnClick() { Util.CallMethod(name, "OnClick"); } protected void OnClickEvent(GameObject go) { Util.CallMethod(name, "OnClick", go); } /// <summary> /// 添加单击事件 /// </summary> public void AddClick(GameObject go, LuaFunction luafunc) { if (go == null || luafunc == null) return; buttons.Add(go.name, luafunc); go.GetComponent<Button>().onClick.AddListener( delegate() { luafunc.Call(go); } ); } /// <summary> /// 删除单击事件 /// </summary> /// <param name="go"></param> public void RemoveClick(GameObject go) { if (go == null) return; LuaFunction luafunc = null; if (buttons.TryGetValue(go.name, out luafunc)) { luafunc.Dispose(); luafunc = null; buttons.Remove(go.name); } } /// <summary> /// 清除单击事件 /// </summary> public void ClearClick() { foreach (var de in buttons) { if (de.Value != null) { de.Value.Dispose(); } } buttons.Clear(); } //----------------------------------------------------------------- protected void OnDestroy() { ClearClick(); #if ASYNC_MODE string abName = name.ToLower().Replace("panel", ""); ResManager.UnloadAssetBundle(abName + AppConst.ExtName); #endif Util.ClearMemory(); Debug.Log("~" + name + " was destroy!"); } } }
using UnityEngine; using System.Collections; using System.IO; using LuaInterface; namespace LuaFramework { /// <summary> /// 集成自LuaFileUtils,重写里面的ReadFile, /// </summary> public class LuaLoader : LuaFileUtils { private ResourceManager m_resMgr; ResourceManager resMgr { get { if (m_resMgr == null) m_resMgr = AppFacade.Instance.GetManager<ResourceManager>(ManagerName.Resource); return m_resMgr; } } // Use this for initialization public LuaLoader() { instance = this; beZip = AppConst.LuaBundleMode; } /// <summary> /// 添加打入Lua代码的AssetBundle /// </summary> /// <param name="bundle"></param> public void AddBundle(string bundleName) { string url = Util.DataPath + bundleName.ToLower(); if (File.Exists(url)) { var bytes = File.ReadAllBytes(url); // 已注释, CreateFromMemoryImmediate从5.3开始改为LoadFromMemory,需要用的请自行取消注释~ // AssetBundle bundle = AssetBundle.CreateFromMemoryImmediate(bytes); AssetBundle bundle = AssetBundle.LoadFromMemory(bytes); if (bundle != null) { bundleName = bundleName.Replace("lua/", "").Replace(".unity3d", ""); base.AddSearchBundle(bundleName.ToLower(), bundle); } } } /// <summary> /// 当LuaVM加载Lua文件的时候,这里就会被调用, /// 用户可以自定义加载行为,只要返回byte[]即可。 /// </summary> /// <param name="fileName"></param> /// <returns></returns> public override byte[] ReadFile(string fileName) { return base.ReadFile(fileName); } } }
using UnityEngine; using System; using System.Collections; using System.Collections.Generic; namespace LuaFramework { public class AppConst { public const bool DebugMode = false; //调试模式-用于内部测试 /// <summary> /// 如果想删掉框架自带的例子,那这个例子模式必须要 /// 关闭,否则会出现一些错误。 /// </summary> public const bool ExampleMode = true; //例子模式 /// <summary> /// 如果开启更新模式,前提必须启动框架自带服务器端。 /// 否则就需要自己将StreamingAssets里面的所有内容 /// 复制到自己的Webserver上面,并修改下面的WebUrl。 /// </summary> public const bool UpdateMode = false; //更新模式-默认关闭 public const bool LuaByteMode = false; //Lua字节码模式-默认关闭 public const bool LuaBundleMode = true; //Lua代码AssetBundle模式 public const int TimerInterval = 1; public const int GameFrameRate = 30; //游戏帧频 public const string AppName = "LuaFramework"; //应用程序名称 public const string LuaTempDir = "Lua/"; //临时目录 public const string AppPrefix = AppName + "_"; //应用程序前缀 public const string ExtName = ".unity3d"; //素材扩展名 public const string AssetDir = "StreamingAssets"; //素材目录 public const string WebUrl = "http://localhost:6688/"; //测试更新地址 public static string UserId = string.Empty; //用户ID public static int SocketPort = 0; //Socket服务器端口 public static string SocketAddress = string.Empty; //Socket服务器地址 public static string FrameworkRoot { get { return Application.dataPath + "/" + AppName; } } } }
using UnityEngine; using System.Collections; namespace LuaFramework { public class ManagerName { public const string Lua = "LuaManager"; public const string Game = "GameManager"; public const string Timer = "TimeManager"; public const string Sound = "SoundManager"; public const string Panel = "PanelManager"; public const string Network = "NetworkManager"; public const string Resource = "ResourceManager"; public const string Thread = "ThreadManager"; public const string ObjectPool = "ObjectPoolManager"; } }
using UnityEngine; using System.Collections; public class NotiConst { /// <summary> /// Controller层消息通知 /// </summary> public const string START_UP = "StartUp"; //启动框架 public const string DISPATCH_MESSAGE = "DispatchMessage"; //派发信息 /// <summary> /// View层消息通知 /// </summary> public const string UPDATE_MESSAGE = "UpdateMessage"; //更新消息 public const string UPDATE_EXTRACT = "UpdateExtract"; //更新解包 public const string UPDATE_DOWNLOAD = "UpdateDownload"; //更新下载 public const string UPDATE_PROGRESS = "UpdateProgress"; //更新进度 }
using UnityEngine; using System.Collections; using System.Collections.Generic; using LuaFramework; public class SocketCommand : ControllerCommand { public override void Execute(IMessage message) { object data = message.Body; if (data == null) return; KeyValuePair<int, ByteBuffer> buffer = (KeyValuePair<int, ByteBuffer>)data; switch (buffer.Key) { default: Util.CallMethod("Network", "OnSocket", buffer.Key, buffer.Value); break; } } }
using UnityEngine; using System.Collections; using LuaFramework; public class StartUpCommand : ControllerCommand { public override void Execute(IMessage message) { if (!Util.CheckEnvironment()) return; GameObject gameMgr = GameObject.Find("GlobalGenerator"); if (gameMgr != null) { AppView appView = gameMgr.AddComponent<AppView>(); } //-----------------关联命令----------------------- AppFacade.Instance.RegisterCommand(NotiConst.DISPATCH_MESSAGE, typeof(SocketCommand)); //-----------------初始化管理器----------------------- AppFacade.Instance.AddManager<LuaManager>(ManagerName.Lua); AppFacade.Instance.AddManager<PanelManager>(ManagerName.Panel); AppFacade.Instance.AddManager<SoundManager>(ManagerName.Sound); AppFacade.Instance.AddManager<TimerManager>(ManagerName.Timer); AppFacade.Instance.AddManager<NetworkManager>(ManagerName.Network); AppFacade.Instance.AddManager<ResourceManager>(ManagerName.Resource); AppFacade.Instance.AddManager<ThreadManager>(ManagerName.Thread); AppFacade.Instance.AddManager<ObjectPoolManager>(ManagerName.ObjectPool); AppFacade.Instance.AddManager<GameManager>(ManagerName.Game); } }
using UnityEngine; using System.Collections; using LuaFramework; using System.Collections.Generic; public class Base : MonoBehaviour { private AppFacade m_Facade; private LuaManager m_LuaMgr; private ResourceManager m_ResMgr; private NetworkManager m_NetMgr; private SoundManager m_SoundMgr; private TimerManager m_TimerMgr; private ThreadManager m_ThreadMgr; private ObjectPoolManager m_ObjectPoolMgr; /// <summary> /// 注册消息 /// </summary> /// <param name="view"></param> /// <param name="messages"></param> protected void RegisterMessage(IView view, List<string> messages) { if (messages == null || messages.Count == 0) return; Controller.Instance.RegisterViewCommand(view, messages.ToArray()); } /// <summary> /// 移除消息 /// </summary> /// <param name="view"></param> /// <param name="messages"></param> protected void RemoveMessage(IView view, List<string> messages) { if (messages == null || messages.Count == 0) return; Controller.Instance.RemoveViewCommand(view, messages.ToArray()); } protected AppFacade facade { get { if (m_Facade == null) { m_Facade = AppFacade.Instance; } return m_Facade; } } protected LuaManager LuaManager { get { if (m_LuaMgr == null) { m_LuaMgr = facade.GetManager<LuaManager>(ManagerName.Lua); } return m_LuaMgr; } } protected ResourceManager ResManager { get { if (m_ResMgr == null) { m_ResMgr = facade.GetManager<ResourceManager>(ManagerName.Resource); } return m_ResMgr; } } protected NetworkManager NetManager { get { if (m_NetMgr == null) { m_NetMgr = facade.GetManager<NetworkManager>(ManagerName.Network); } return m_NetMgr; } } protected SoundManager SoundManager { get { if (m_SoundMgr == null) { m_SoundMgr = facade.GetManager<SoundManager>(ManagerName.Sound); } return m_SoundMgr; } } protected TimerManager TimerManager { get { if (m_TimerMgr == null) { m_TimerMgr = facade.GetManager<TimerManager>(ManagerName.Timer); } return m_TimerMgr; } } protected ThreadManager ThreadManager { get { if (m_ThreadMgr == null) { m_ThreadMgr = facade.GetManager<ThreadManager>(ManagerName.Thread); } return m_ThreadMgr; } } protected ObjectPoolManager ObjPoolManager { get { if (m_ObjectPoolMgr == null) { m_ObjectPoolMgr = facade.GetManager<ObjectPoolManager>(ManagerName.ObjectPool); } return m_ObjectPoolMgr; } } }
/* LuaFramework Code By Jarjin lee */ using System; using System.Collections.Generic; using UnityEngine; /// <summary> /// 事件命令 /// </summary> public class ControllerCommand : ICommand { public virtual void Execute(IMessage message) { } } public class Facade { protected IController m_controller; static GameObject m_GameManager; static Dictionary<string, object> m_Managers = new Dictionary<string, object>(); GameObject AppGameManager { get { if (m_GameManager == null) { m_GameManager = GameObject.Find("GameManager"); } return m_GameManager; } } protected Facade() { InitFramework(); } protected virtual void InitFramework() { if (m_controller != null) return; m_controller = Controller.Instance; } public virtual void RegisterCommand(string commandName, Type commandType) { m_controller.RegisterCommand(commandName, commandType); } public virtual void RemoveCommand(string commandName) { m_controller.RemoveCommand(commandName); } public virtual bool HasCommand(string commandName) { return m_controller.HasCommand(commandName); } public void RegisterMultiCommand(Type commandType, params string[] commandNames) { int count = commandNames.Length; for (int i = 0; i < count; i++) { RegisterCommand(commandNames[i], commandType); } } public void RemoveMultiCommand(params string[] commandName) { int count = commandName.Length; for (int i = 0; i < count; i++) { RemoveCommand(commandName[i]); } } public void SendMessageCommand(string message, object body = null) { m_controller.ExecuteCommand(new Message(message, body)); } /// <summary> /// 添加管理器 /// </summary> public void AddManager(string typeName, object obj) { if (!m_Managers.ContainsKey(typeName)) { m_Managers.Add(typeName, obj); } } /// <summary> /// 添加Unity对象 /// </summary> public T AddManager<T>(string typeName) where T : Component { object result = null; m_Managers.TryGetValue(typeName, out result); if (result != null) { return (T)result; } Component c = AppGameManager.AddComponent<T>(); m_Managers.Add(typeName, c); return default(T); } /// <summary> /// 获取系统管理器 /// </summary> public T GetManager<T>(string typeName) where T : class { if (!m_Managers.ContainsKey(typeName)) { return default(T); } object manager = null; m_Managers.TryGetValue(typeName, out manager); return (T)manager; } /// <summary> /// 删除管理器 /// </summary> public void RemoveManager(string typeName) { if (!m_Managers.ContainsKey(typeName)) { return; } object manager = null; m_Managers.TryGetValue(typeName, out manager); Type type = manager.GetType(); if (type.IsSubclassOf(typeof(MonoBehaviour))) { GameObject.Destroy((Component)manager); } m_Managers.Remove(typeName); } }
using UnityEngine; using System.Collections; using LuaFramework; public class Manager : Base, IManager { // Use this for initialization void Start () { } // Update is called once per frame void Update () { } }
/* LuaFramework Code By Jarjin lee */ using System; public class Message : IMessage { public Message(string name) : this(name, null, null) { } public Message(string name, object body) : this(name, body, null) { } public Message(string name, object body, string type) { m_name = name; m_body = body; m_type = type; } /// <summary> /// Get the string representation of the <c>Notification instance</c> /// </summary> /// <returns>The string representation of the <c>Notification</c> instance</returns> public override string ToString() { string msg = "Notification Name: " + Name; msg += "\nBody:" + ((Body == null) ? "null" : Body.ToString()); msg += "\nType:" + ((Type == null) ? "null" : Type); return msg; } /// <summary> /// The name of the <c>Notification</c> instance /// </summary> public virtual string Name { get { return m_name; } } /// <summary> /// The body of the <c>Notification</c> instance /// </summary> /// <remarks>This accessor is thread safe</remarks> public virtual object Body { get { // Setting and getting of reference types is atomic, no need to lock here return m_body; } set { // Setting and getting of reference types is atomic, no need to lock here m_body = value; } } /// <summary> /// The type of the <c>Notification</c> instance /// </summary> /// <remarks>This accessor is thread safe</remarks> public virtual string Type { get { // Setting and getting of reference types is atomic, no need to lock here return m_type; } set { // Setting and getting of reference types is atomic, no need to lock here m_type = value; } } /// <summary> /// The name of the notification instance /// </summary> private string m_name; /// <summary> /// The type of the notification instance /// </summary> private string m_type; /// <summary> /// The body of the notification instance /// </summary> private object m_body; }
using UnityEngine; using System; using System.Collections; using System.Collections.Generic; using LuaInterface; using LuaFramework; public class View : Base, IView { public virtual void OnMessage(IMessage message) { } }
/* LuaFramework Code By Jarjin lee */ using System; public interface ICommand { void Execute(IMessage message); }
/* LuaFramework Code By Jarjin leeibution 3.0 License */ using System; using System.Collections.Generic; public interface IController { void RegisterCommand(string messageName, Type commandType); void RegisterViewCommand(IView view, string[] commandNames); void ExecuteCommand(IMessage message); void RemoveCommand(string messageName); void RemoveViewCommand(IView view, string[] commandNames); bool HasCommand(string messageName); }
/* LuaFramework Code By Jarjin leeibution 3.0 License */ using UnityEngine; using System.Collections; public interface IManager { }
/* LuaFramework Code By Jarjin lee */ using System; public interface IMessage { string Name { get; } object Body { get; set; } string Type { get; set; } string ToString(); }
using System; public interface IView { void OnMessage(IMessage message); }
using UnityEngine; using System; using System.Collections; using System.Collections.Generic; public class AppFacade : Facade { private static AppFacade _instance; public AppFacade() : base() { } public static AppFacade Instance { get{ if (_instance == null) { _instance = new AppFacade(); } return _instance; } } override protected void InitFramework() { base.InitFramework(); RegisterCommand(NotiConst.START_UP, typeof(StartUpCommand)); } /// <summary> /// 启动框架 /// </summary> public void StartUp() { SendMessageCommand(NotiConst.START_UP); RemoveMultiCommand(NotiConst.START_UP); } }
using System; using System.Collections; namespace LuaFramework { public interface ITimerBehaviour { void TimerUpdate(); } }
using UnityEngine; using System; using System.Collections; using System.Collections.Generic; using LuaInterface; using System.Reflection; using System.IO; namespace LuaFramework { public class GameManager : Manager { protected static bool initialize = false; private List<string> downloadFiles = new List<string>(); /// <summary> /// 初始化游戏管理器 /// </summary> void Awake() { Init(); } /// <summary> /// 初始化 /// </summary> void Init() { DontDestroyOnLoad(gameObject); //防止销毁自己 CheckExtractResource(); //释放资源 Screen.sleepTimeout = SleepTimeout.NeverSleep; Application.targetFrameRate = AppConst.GameFrameRate; } /// <summary> /// 释放资源 /// </summary> public void CheckExtractResource() { bool isExists = Directory.Exists(Util.DataPath) && Directory.Exists(Util.DataPath + "lua/") && File.Exists(Util.DataPath + "files.txt"); if (isExists || AppConst.DebugMode) { StartCoroutine(OnUpdateResource()); return; //文件已经解压过了,自己可添加检查文件列表逻辑 } StartCoroutine(OnExtractResource()); //启动释放协成 } IEnumerator OnExtractResource() { string dataPath = Util.DataPath; //数据目录 string resPath = Util.AppContentPath(); //游戏包资源目录 if (Directory.Exists(dataPath)) Directory.Delete(dataPath, true); Directory.CreateDirectory(dataPath); string infile = resPath + "files.txt"; string outfile = dataPath + "files.txt"; if (File.Exists(outfile)) File.Delete(outfile); string message = "正在解包文件:>files.txt"; Debug.Log(infile); Debug.Log(outfile); if (Application.platform == RuntimePlatform.Android) { WWW www = new WWW(infile); yield return www; if (www.isDone) { File.WriteAllBytes(outfile, www.bytes); } yield return 0; } else File.Copy(infile, outfile, true); yield return new WaitForEndOfFrame(); //释放所有文件到数据目录 string[] files = File.ReadAllLines(outfile); foreach (var file in files) { string[] fs = file.Split('|'); infile = resPath + fs[0]; // outfile = dataPath + fs[0]; message = "正在解包文件:>" + fs[0]; Debug.Log("正在解包文件:>" + infile); facade.SendMessageCommand(NotiConst.UPDATE_MESSAGE, message); string dir = Path.GetDirectoryName(outfile); if (!Directory.Exists(dir)) Directory.CreateDirectory(dir); if (Application.platform == RuntimePlatform.Android) { WWW www = new WWW(infile); yield return www; if (www.isDone) { File.WriteAllBytes(outfile, www.bytes); } yield return 0; } else { if (File.Exists(outfile)) { File.Delete(outfile); } File.Copy(infile, outfile, true); } yield return new WaitForEndOfFrame(); } message = "解包完成!!!"; facade.SendMessageCommand(NotiConst.UPDATE_MESSAGE, message); yield return new WaitForSeconds(0.1f); message = string.Empty; //释放完成,开始启动更新资源 StartCoroutine(OnUpdateResource()); } /// <summary> /// 启动更新下载,这里只是个思路演示,此处可启动线程下载更新 /// </summary> IEnumerator OnUpdateResource() { if (!AppConst.UpdateMode) { OnResourceInited(); yield break; } string dataPath = Util.DataPath; //数据目录 string url = AppConst.WebUrl; string message = string.Empty; string random = DateTime.Now.ToString("yyyymmddhhmmss"); string listUrl = url + "files.txt?v=" + random; Debug.LogWarning("LoadUpdate---->>>" + listUrl); WWW www = new WWW(listUrl); yield return www; if (www.error != null) { OnUpdateFailed(string.Empty); yield break; } if (!Directory.Exists(dataPath)) { Directory.CreateDirectory(dataPath); } File.WriteAllBytes(dataPath + "files.txt", www.bytes); string filesText = www.text; string[] files = filesText.Split('\n'); for (int i = 0; i < files.Length; i++) { if (string.IsNullOrEmpty(files[i])) continue; string[] keyValue = files[i].Split('|'); string f = keyValue[0]; string localfile = (dataPath + f).Trim(); string path = Path.GetDirectoryName(localfile); if (!Directory.Exists(path)) { Directory.CreateDirectory(path); } string fileUrl = url + f + "?v=" + random; bool canUpdate = !File.Exists(localfile); if (!canUpdate) { string remoteMd5 = keyValue[1].Trim(); string localMd5 = Util.md5file(localfile); canUpdate = !remoteMd5.Equals(localMd5); if (canUpdate) File.Delete(localfile); } if (canUpdate) { //本地缺少文件 Debug.Log(fileUrl); message = "downloading>>" + fileUrl; facade.SendMessageCommand(NotiConst.UPDATE_MESSAGE, message); /* www = new WWW(fileUrl); yield return www; if (www.error != null) { OnUpdateFailed(path); // yield break; } File.WriteAllBytes(localfile, www.bytes); */ //这里都是资源文件,用线程下载 BeginDownload(fileUrl, localfile); while (!(IsDownOK(localfile))) { yield return new WaitForEndOfFrame(); } } } yield return new WaitForEndOfFrame(); message = "更新完成!!"; facade.SendMessageCommand(NotiConst.UPDATE_MESSAGE, message); OnResourceInited(); } void OnUpdateFailed(string file) { string message = "更新失败!>" + file; facade.SendMessageCommand(NotiConst.UPDATE_MESSAGE, message); } /// <summary> /// 是否下载完成 /// </summary> bool IsDownOK(string file) { return downloadFiles.Contains(file); } /// <summary> /// 线程下载 /// </summary> void BeginDownload(string url, string file) { //线程下载 object[] param = new object[2] { url, file }; ThreadEvent ev = new ThreadEvent(); ev.Key = NotiConst.UPDATE_DOWNLOAD; ev.evParams.AddRange(param); ThreadManager.AddEvent(ev, OnThreadCompleted); //线程下载 } /// <summary> /// 线程完成 /// </summary> /// <param name="data"></param> void OnThreadCompleted(NotiData data) { switch (data.evName) { case NotiConst.UPDATE_EXTRACT: //解压一个完成 // break; case NotiConst.UPDATE_DOWNLOAD: //下载一个完成 downloadFiles.Add(data.evParam.ToString()); break; } } /// <summary> /// 资源初始化结束 /// </summary> public void OnResourceInited() { #if ASYNC_MODE ResManager.Initialize(AppConst.AssetDir, delegate() { Debug.Log("Initialize OK!!!"); this.OnInitialize(); }); #else ResManager.Initialize(); this.OnInitialize(); #endif } void OnInitialize() { LuaManager.InitStart(); LuaManager.DoFile("Logic/Game"); //加载游戏 LuaManager.DoFile("Logic/Network"); //加载网络 NetManager.OnInit(); //初始化网络 Util.CallMethod("Game", "OnInitOK"); //初始化完成 initialize = true; //类对象池测试 var classObjPool = ObjPoolManager.CreatePool<TestObjectClass>(OnPoolGetElement, OnPoolPushElement); //方法1 //objPool.Release(new TestObjectClass("abcd", 100, 200f)); //var testObj1 = objPool.Get(); //方法2 ObjPoolManager.Release<TestObjectClass>(new TestObjectClass("abcd", 100, 200f)); var testObj1 = ObjPoolManager.Get<TestObjectClass>(); Debugger.Log("TestObjectClass--->>>" + testObj1.ToString()); //游戏对象池测试 var prefab = Resources.Load("TestGameObjectPrefab", typeof(GameObject)) as GameObject; var gameObjPool = ObjPoolManager.CreatePool("TestGameObject", 5, 10, prefab); var gameObj = Instantiate(prefab) as GameObject; gameObj.name = "TestGameObject_01"; gameObj.transform.localScale = Vector3.one; gameObj.transform.localPosition = Vector3.zero; ObjPoolManager.Release("TestGameObject", gameObj); var backObj = ObjPoolManager.Get("TestGameObject"); backObj.transform.SetParent(null); Debug.Log("TestGameObject--->>>" + backObj); } /// <summary> /// 当从池子里面获取时 /// </summary> /// <param name="obj"></param> void OnPoolGetElement(TestObjectClass obj) { Debug.Log("OnPoolGetElement--->>>" + obj); } /// <summary> /// 当放回池子里面时 /// </summary> /// <param name="obj"></param> void OnPoolPushElement(TestObjectClass obj) { Debug.Log("OnPoolPushElement--->>>" + obj); } /// <summary> /// 析构函数 /// </summary> void OnDestroy() { if (NetManager != null) { NetManager.Unload(); } if (LuaManager != null) { LuaManager.Close(); } Debug.Log("~GameManager was destroyed"); } } }
using UnityEngine; using System.Collections; using LuaInterface; namespace LuaFramework { public class LuaManager : Manager { private LuaState lua; private LuaLoader loader; private LuaLooper loop = null; // Use this for initialization void Awake() { loader = new LuaLoader(); lua = new LuaState(); this.OpenLibs(); lua.LuaSetTop(0); LuaBinder.Bind(lua); DelegateFactory.Init(); LuaCoroutine.Register(lua, this); } public void InitStart() { InitLuaPath(); InitLuaBundle(); this.lua.Start(); //启动LUAVM this.StartMain(); this.StartLooper(); } void StartLooper() { loop = gameObject.AddComponent<LuaLooper>(); loop.luaState = lua; } //cjson 比较特殊,只new了一个table,没有注册库,这里注册一下 protected void OpenCJson() { lua.LuaGetField(LuaIndexes.LUA_REGISTRYINDEX, "_LOADED"); lua.OpenLibs(LuaDLL.luaopen_cjson); lua.LuaSetField(-2, "cjson"); lua.OpenLibs(LuaDLL.luaopen_cjson_safe); lua.LuaSetField(-2, "cjson.safe"); } void StartMain() { lua.DoFile("Main.lua"); LuaFunction main = lua.GetFunction("Main"); main.Call(); main.Dispose(); main = null; } /// <summary> /// 初始化加载第三方库 /// </summary> void OpenLibs() { lua.OpenLibs(LuaDLL.luaopen_pb); lua.OpenLibs(LuaDLL.luaopen_sproto_core); lua.OpenLibs(LuaDLL.luaopen_protobuf_c); lua.OpenLibs(LuaDLL.luaopen_lpeg); lua.OpenLibs(LuaDLL.luaopen_bit); lua.OpenLibs(LuaDLL.luaopen_socket_core); this.OpenCJson(); } /// <summary> /// 初始化Lua代码加载路径 /// </summary> void InitLuaPath() { if (AppConst.DebugMode) { string rootPath = AppConst.FrameworkRoot; lua.AddSearchPath(rootPath + "/Lua"); lua.AddSearchPath(rootPath + "/ToLua/Lua"); } else { lua.AddSearchPath(Util.DataPath + "lua"); } } /// <summary> /// 初始化LuaBundle /// </summary> void InitLuaBundle() { if (loader.beZip) { loader.AddBundle("lua/lua.unity3d"); loader.AddBundle("lua/lua_math.unity3d"); loader.AddBundle("lua/lua_system.unity3d"); loader.AddBundle("lua/lua_system_reflection.unity3d"); loader.AddBundle("lua/lua_unityengine.unity3d"); loader.AddBundle("lua/lua_common.unity3d"); loader.AddBundle("lua/lua_logic.unity3d"); loader.AddBundle("lua/lua_view.unity3d"); loader.AddBundle("lua/lua_controller.unity3d"); loader.AddBundle("lua/lua_misc.unity3d"); loader.AddBundle("lua/lua_protobuf.unity3d"); loader.AddBundle("lua/lua_3rd_cjson.unity3d"); loader.AddBundle("lua/lua_3rd_luabitop.unity3d"); loader.AddBundle("lua/lua_3rd_pbc.unity3d"); loader.AddBundle("lua/lua_3rd_pblua.unity3d"); loader.AddBundle("lua/lua_3rd_sproto.unity3d"); } } public void DoFile(string filename) { lua.DoFile(filename); } // Update is called once per frame public object[] CallFunction(string funcName, params object[] args) { LuaFunction func = lua.GetFunction(funcName); if (func != null) { return func.LazyCall(args); } return null; } public void LuaGC() { lua.LuaGC(LuaGCOptions.LUA_GCCOLLECT); } public void Close() { loop.Destroy(); loop = null; lua.Dispose(); lua = null; loader = null; } } }
using UnityEngine; using System; using System.Collections; using System.Collections.Generic; using LuaInterface; namespace LuaFramework { public class NetworkManager : Manager { private SocketClient socket; static readonly object m_lockObject = new object(); static Queue<KeyValuePair<int, ByteBuffer>> mEvents = new Queue<KeyValuePair<int, ByteBuffer>>(); SocketClient SocketClient { get { if (socket == null) socket = new SocketClient(); return socket; } } void Awake() { Init(); } void Init() { SocketClient.OnRegister(); } public void OnInit() { CallMethod("Start"); } public void Unload() { CallMethod("Unload"); } /// <summary> /// 执行Lua方法 /// </summary> public object[] CallMethod(string func, params object[] args) { return Util.CallMethod("Network", func, args); } ///------------------------------------------------------------------------------------ public static void AddEvent(int _event, ByteBuffer data) { lock (m_lockObject) { mEvents.Enqueue(new KeyValuePair<int, ByteBuffer>(_event, data)); } } /// <summary> /// 交给Command,这里不想关心发给谁。 /// </summary> void Update() { if (mEvents.Count > 0) { while (mEvents.Count > 0) { KeyValuePair<int, ByteBuffer> _event = mEvents.Dequeue(); facade.SendMessageCommand(NotiConst.DISPATCH_MESSAGE, _event); } } } /// <summary> /// 发送链接请求 /// </summary> public void SendConnect() { SocketClient.SendConnect(); } /// <summary> /// 发送SOCKET消息 /// </summary> public void SendMessage(ByteBuffer buffer) { SocketClient.SendMessage(buffer); } /// <summary> /// 析构函数 /// </summary> new void OnDestroy() { SocketClient.OnRemove(); Debug.Log("~NetworkManager was destroy"); } } }
using UnityEngine; using System.Collections; using System.Collections.Generic; using UnityEngine.Events; namespace LuaFramework { /// <summary> /// 对象池管理器,分普通类对象池+资源游戏对象池 /// </summary> public class ObjectPoolManager : Manager { private Transform m_PoolRootObject = null; private Dictionary<string, object> m_ObjectPools = new Dictionary<string, object>(); private Dictionary<string, GameObjectPool> m_GameObjectPools = new Dictionary<string, GameObjectPool>(); Transform PoolRootObject { get { if (m_PoolRootObject == null) { var objectPool = new GameObject("ObjectPool"); objectPool.transform.SetParent(transform); objectPool.transform.localScale = Vector3.one; objectPool.transform.localPosition = Vector3.zero; m_PoolRootObject = objectPool.transform; } return m_PoolRootObject; } } public GameObjectPool CreatePool(string poolName, int initSize, int maxSize, GameObject prefab) { var pool = new GameObjectPool(poolName, prefab, initSize, maxSize, PoolRootObject); m_GameObjectPools[poolName] = pool; return pool; } public GameObjectPool GetPool(string poolName) { if (m_GameObjectPools.ContainsKey(poolName)) { return m_GameObjectPools[poolName]; } return null; } public GameObject Get(string poolName) { GameObject result = null; if (m_GameObjectPools.ContainsKey(poolName)) { GameObjectPool pool = m_GameObjectPools[poolName]; result = pool.NextAvailableObject(); if (result == null) { Debug.LogWarning("No object available in pool. Consider setting fixedSize to false.: " + poolName); } } else { Debug.LogError("Invalid pool name specified: " + poolName); } return result; } public void Release(string poolName, GameObject go) { if (m_GameObjectPools.ContainsKey(poolName)) { GameObjectPool pool = m_GameObjectPools[poolName]; pool.ReturnObjectToPool(poolName, go); } else { Debug.LogWarning("No pool available with name: " + poolName); } } ///----------------------------------------------------------------------------------------------- public ObjectPool<T> CreatePool<T>(UnityAction<T> actionOnGet, UnityAction<T> actionOnRelease) where T : class { var type = typeof(T); var pool = new ObjectPool<T>(actionOnGet, actionOnRelease); m_ObjectPools[type.Name] = pool; return pool; } public ObjectPool<T> GetPool<T>() where T : class { var type = typeof(T); ObjectPool<T> pool = null; if (m_ObjectPools.ContainsKey(type.Name)) { pool = m_ObjectPools[type.Name] as ObjectPool<T>; } return pool; } public T Get<T>() where T : class { var pool = GetPool<T>(); if (pool != null) { return pool.Get(); } return default(T); } public void Release<T>(T obj) where T : class { var pool = GetPool<T>(); if (pool != null) { pool.Release(obj); } } } }
using UnityEngine; using System.Collections; using System.Collections.Generic; using UnityEngine.UI; using LuaInterface; namespace LuaFramework { public class PanelManager : Manager { private Transform parent; Transform Parent { get { if (parent == null) { GameObject go = GameObject.FindWithTag("GuiCamera"); if (go != null) parent = go.transform; } return parent; } } /// <summary> /// ������壬������Դ������ /// </summary> /// <param name="type"></param> public void CreatePanel(string name, LuaFunction func = null) { string assetName = name + "Panel"; string abName = name.ToLower() + AppConst.ExtName; if (Parent.Find(name) != null) return; #if ASYNC_MODE ResManager.LoadPrefab(abName, assetName, delegate(UnityEngine.Object[] objs) { if (objs.Length == 0) return; GameObject prefab = objs[0] as GameObject; if (prefab == null) return; GameObject go = Instantiate(prefab) as GameObject; go.name = assetName; go.layer = LayerMask.NameToLayer("Default"); go.transform.SetParent(Parent); go.transform.localScale = Vector3.one; go.transform.localPosition = Vector3.zero; go.AddComponent<LuaBehaviour>(); if (func != null) func.Call(go); Debug.LogWarning("CreatePanel::>> " + name + " " + prefab); }); #else GameObject prefab = ResManager.LoadAsset<GameObject>(name, assetName); if (prefab == null) return; GameObject go = Instantiate(prefab) as GameObject; go.name = assetName; go.layer = LayerMask.NameToLayer("Default"); go.transform.SetParent(Parent); go.transform.localScale = Vector3.one; go.transform.localPosition = Vector3.zero; go.AddComponent<LuaBehaviour>(); if (func != null) func.Call(go); Debug.LogWarning("CreatePanel::>> " + name + " " + prefab); #endif } /// <summary> /// �ر���� /// </summary> /// <param name="name"></param> public void ClosePanel(string name) { var panelName = name + "Panel"; var panelObj = Parent.Find(panelName); if (panelObj == null) return; Destroy(panelObj.gameObject); } } }
#if ASYNC_MODE using UnityEngine; using System.Collections; using System.Collections.Generic; using System; using System.IO; using LuaInterface; using UObject = UnityEngine.Object; public class AssetBundleInfo { public AssetBundle m_AssetBundle; public int m_ReferencedCount; public AssetBundleInfo(AssetBundle assetBundle) { m_AssetBundle = assetBundle; m_ReferencedCount = 0; } } namespace LuaFramework { public class ResourceManager : Manager { string m_BaseDownloadingURL = ""; string[] m_AllManifest = null; AssetBundleManifest m_AssetBundleManifest = null; Dictionary<string, string[]> m_Dependencies = new Dictionary<string, string[]>(); Dictionary<string, AssetBundleInfo> m_LoadedAssetBundles = new Dictionary<string, AssetBundleInfo>(); Dictionary<string, List<LoadAssetRequest>> m_LoadRequests = new Dictionary<string, List<LoadAssetRequest>>(); class LoadAssetRequest { public Type assetType; public string[] assetNames; public LuaFunction luaFunc; public Action<UObject[]> sharpFunc; } // Load AssetBundleManifest. public void Initialize(string manifestName, Action initOK) { m_BaseDownloadingURL = Util.GetRelativePath(); LoadAsset<AssetBundleManifest>(manifestName, new string[] { "AssetBundleManifest" }, delegate(UObject[] objs) { if (objs.Length > 0) { m_AssetBundleManifest = objs[0] as AssetBundleManifest; m_AllManifest = m_AssetBundleManifest.GetAllAssetBundles(); } if (initOK != null) initOK(); }); } public void LoadPrefab(string abName, string assetName, Action<UObject[]> func) { LoadAsset<GameObject>(abName, new string[] { assetName }, func); } public void LoadPrefab(string abName, string[] assetNames, Action<UObject[]> func) { LoadAsset<GameObject>(abName, assetNames, func); } public void LoadPrefab(string abName, string[] assetNames, LuaFunction func) { LoadAsset<GameObject>(abName, assetNames, null, func); } string GetRealAssetPath(string abName) { if (abName.Equals(AppConst.AssetDir)) { return abName; } abName = abName.ToLower(); if (!abName.EndsWith(AppConst.ExtName)) { abName += AppConst.ExtName; } if (abName.Contains("/")) { return abName; } //string[] paths = m_AssetBundleManifest.GetAllAssetBundles(); 产生GC,需要缓存结果 for (int i = 0; i < m_AllManifest.Length; i++) { int index = m_AllManifest[i].LastIndexOf('/'); string path = m_AllManifest[i].Remove(0, index + 1); //字符串操作函数都会产生GC if (path.Equals(abName)) { return m_AllManifest[i]; } } Debug.LogError("GetRealAssetPath Error:>>" + abName); return null; } /// <summary> /// 载入素材 /// </summary> void LoadAsset<T>(string abName, string[] assetNames, Action<UObject[]> action = null, LuaFunction func = null) where T : UObject { abName = GetRealAssetPath(abName); LoadAssetRequest request = new LoadAssetRequest(); request.assetType = typeof(T); request.assetNames = assetNames; request.luaFunc = func; request.sharpFunc = action; List<LoadAssetRequest> requests = null; if (!m_LoadRequests.TryGetValue(abName, out requests)) { requests = new List<LoadAssetRequest>(); requests.Add(request); m_LoadRequests.Add(abName, requests); StartCoroutine(OnLoadAsset<T>(abName)); } else { requests.Add(request); } } IEnumerator OnLoadAsset<T>(string abName) where T : UObject { Debug.Log(abName); AssetBundleInfo bundleInfo = GetLoadedAssetBundle(abName); if (bundleInfo == null) { yield return StartCoroutine(OnLoadAssetBundle(abName, typeof(T))); bundleInfo = GetLoadedAssetBundle(abName); if (bundleInfo == null) { m_LoadRequests.Remove(abName); Debug.LogError("OnLoadAsset--->>>" + abName); yield break; } } List<LoadAssetRequest> list = null; if (!m_LoadRequests.TryGetValue(abName, out list)) { m_LoadRequests.Remove(abName); yield break; } for (int i = 0; i < list.Count; i++) { string[] assetNames = list[i].assetNames; List<UObject> result = new List<UObject>(); AssetBundle ab = bundleInfo.m_AssetBundle; for (int j = 0; j < assetNames.Length; j++) { string assetPath = assetNames[j]; AssetBundleRequest request = ab.LoadAssetAsync(assetPath, list[i].assetType); yield return request; result.Add(request.asset); //T assetObj = ab.LoadAsset<T>(assetPath); //result.Add(assetObj); } if (list[i].sharpFunc != null) { list[i].sharpFunc(result.ToArray()); list[i].sharpFunc = null; } if (list[i].luaFunc != null) { list[i].luaFunc.Call((object)result.ToArray()); list[i].luaFunc.Dispose(); list[i].luaFunc = null; } bundleInfo.m_ReferencedCount++; } m_LoadRequests.Remove(abName); } IEnumerator OnLoadAssetBundle(string abName, Type type) { string url = m_BaseDownloadingURL + abName; WWW download = null; if (type == typeof(AssetBundleManifest)) download = new WWW(url); else { string[] dependencies = m_AssetBundleManifest.GetAllDependencies(abName); if (dependencies.Length > 0) { m_Dependencies.Add(abName, dependencies); for (int i = 0; i < dependencies.Length; i++) { string depName = dependencies[i]; AssetBundleInfo bundleInfo = null; if (m_LoadedAssetBundles.TryGetValue(depName, out bundleInfo)) { bundleInfo.m_ReferencedCount++; } else if (!m_LoadRequests.ContainsKey(depName)) { yield return StartCoroutine(OnLoadAssetBundle(depName, type)); } } } download = WWW.LoadFromCacheOrDownload(url, m_AssetBundleManifest.GetAssetBundleHash(abName), 0); } yield return download; AssetBundle assetObj = download.assetBundle; if (assetObj != null) { m_LoadedAssetBundles.Add(abName, new AssetBundleInfo(assetObj)); } } AssetBundleInfo GetLoadedAssetBundle(string abName) { AssetBundleInfo bundle = null; m_LoadedAssetBundles.TryGetValue(abName, out bundle); if (bundle == null) return null; // No dependencies are recorded, only the bundle itself is required. string[] dependencies = null; if (!m_Dependencies.TryGetValue(abName, out dependencies)) return bundle; // Make sure all dependencies are loaded foreach (var dependency in dependencies) { AssetBundleInfo dependentBundle; m_LoadedAssetBundles.TryGetValue(dependency, out dependentBundle); if (dependentBundle == null) return null; } return bundle; } /// <summary> /// 此函数交给外部卸载专用,自己调整是否需要彻底清除AB /// </summary> /// <param name="abName"></param> /// <param name="isThorough"></param> public void UnloadAssetBundle(string abName, bool isThorough = false) { abName = GetRealAssetPath(abName); Debug.Log(m_LoadedAssetBundles.Count + " assetbundle(s) in memory before unloading " + abName); UnloadAssetBundleInternal(abName, isThorough); UnloadDependencies(abName, isThorough); Debug.Log(m_LoadedAssetBundles.Count + " assetbundle(s) in memory after unloading " + abName); } void UnloadDependencies(string abName, bool isThorough) { string[] dependencies = null; if (!m_Dependencies.TryGetValue(abName, out dependencies)) return; // Loop dependencies. foreach (var dependency in dependencies) { UnloadAssetBundleInternal(dependency, isThorough); } m_Dependencies.Remove(abName); } void UnloadAssetBundleInternal(string abName, bool isThorough) { AssetBundleInfo bundle = GetLoadedAssetBundle(abName); if (bundle == null) return; if (--bundle.m_ReferencedCount <= 0) { if (m_LoadRequests.ContainsKey(abName)) { return; //如果当前AB处于Async Loading过程中,卸载会崩溃,只减去引用计数即可 } bundle.m_AssetBundle.Unload(isThorough); m_LoadedAssetBundles.Remove(abName); Debug.Log(abName + " has been unloaded successfully"); } } } } #else using UnityEngine; using System.Collections; using System.Collections.Generic; using System.IO; using LuaFramework; using LuaInterface; using UObject = UnityEngine.Object; namespace LuaFramework { public class ResourceManager : Manager { private string[] m_Variants = { }; private AssetBundleManifest manifest; private AssetBundle shared, assetbundle; private Dictionary<string, AssetBundle> bundles; void Awake() { } /// <summary> /// 初始化 /// </summary> public void Initialize() { byte[] stream = null; string uri = string.Empty; bundles = new Dictionary<string, AssetBundle>(); uri = Util.DataPath + AppConst.AssetDir; if (!File.Exists(uri)) return; stream = File.ReadAllBytes(uri); assetbundle = AssetBundle.CreateFromMemoryImmediate(stream); manifest = assetbundle.LoadAsset<AssetBundleManifest>("AssetBundleManifest"); } /// <summary> /// 载入素材 /// </summary> public T LoadAsset<T>(string abname, string assetname) where T : UnityEngine.Object { abname = abname.ToLower(); AssetBundle bundle = LoadAssetBundle(abname); return bundle.LoadAsset<T>(assetname); } public void LoadPrefab(string abName, string[] assetNames, LuaFunction func) { abName = abName.ToLower(); List<UObject> result = new List<UObject>(); for (int i = 0; i < assetNames.Length; i++) { UObject go = LoadAsset<UObject>(abName, assetNames[i]); if (go != null) result.Add(go); } if (func != null) func.Call((object)result.ToArray()); } /// <summary> /// 载入AssetBundle /// </summary> /// <param name="abname"></param> /// <returns></returns> public AssetBundle LoadAssetBundle(string abname) { if (!abname.EndsWith(AppConst.ExtName)) { abname += AppConst.ExtName; } AssetBundle bundle = null; if (!bundles.ContainsKey(abname)) { byte[] stream = null; string uri = Util.DataPath + abname; Debug.LogWarning("LoadFile::>> " + uri); LoadDependencies(abname); stream = File.ReadAllBytes(uri); bundle = AssetBundle.CreateFromMemoryImmediate(stream); //关联数据的素材绑定 bundles.Add(abname, bundle); } else { bundles.TryGetValue(abname, out bundle); } return bundle; } /// <summary> /// 载入依赖 /// </summary> /// <param name="name"></param> void LoadDependencies(string name) { if (manifest == null) { Debug.LogError("Please initialize AssetBundleManifest by calling AssetBundleManager.Initialize()"); return; } // Get dependecies from the AssetBundleManifest object.. string[] dependencies = manifest.GetAllDependencies(name); if (dependencies.Length == 0) return; for (int i = 0; i < dependencies.Length; i++) dependencies[i] = RemapVariantName(dependencies[i]); // Record and load all dependencies. for (int i = 0; i < dependencies.Length; i++) { LoadAssetBundle(dependencies[i]); } } // Remaps the asset bundle name to the best fitting asset bundle variant. string RemapVariantName(string assetBundleName) { string[] bundlesWithVariant = manifest.GetAllAssetBundlesWithVariant(); // If the asset bundle doesn't have variant, simply return. if (System.Array.IndexOf(bundlesWithVariant, assetBundleName) < 0) return assetBundleName; string[] split = assetBundleName.Split('.'); int bestFit = int.MaxValue; int bestFitIndex = -1; // Loop all the assetBundles with variant to find the best fit variant assetBundle. for (int i = 0; i < bundlesWithVariant.Length; i++) { string[] curSplit = bundlesWithVariant[i].Split('.'); if (curSplit[0] != split[0]) continue; int found = System.Array.IndexOf(m_Variants, curSplit[1]); if (found != -1 && found < bestFit) { bestFit = found; bestFitIndex = i; } } if (bestFitIndex != -1) return bundlesWithVariant[bestFitIndex]; else return assetBundleName; } /// <summary> /// 销毁资源 /// </summary> void OnDestroy() { if (shared != null) shared.Unload(true); if (manifest != null) manifest = null; Debug.Log("~ResourceManager was destroy!"); } } } #endif
using UnityEngine; using System.Collections; using System.Collections.Generic; namespace LuaFramework { public class SoundManager : Manager { private AudioSource audio; private Hashtable sounds = new Hashtable(); void Start() { audio = GetComponent<AudioSource>(); } /// <summary> /// 添加一个声音 /// </summary> void Add(string key, AudioClip value) { if (sounds[key] != null || value == null) return; sounds.Add(key, value); } /// <summary> /// 获取一个声音 /// </summary> AudioClip Get(string key) { if (sounds[key] == null) return null; return sounds[key] as AudioClip; } /// <summary> /// 载入一个音频 /// </summary> public AudioClip LoadAudioClip(string path) { AudioClip ac = Get(path); if (ac == null) { ac = (AudioClip)Resources.Load(path, typeof(AudioClip)); Add(path, ac); } return ac; } /// <summary> /// 是否播放背景音乐,默认是1:播放 /// </summary> /// <returns></returns> public bool CanPlayBackSound() { string key = AppConst.AppPrefix + "BackSound"; int i = PlayerPrefs.GetInt(key, 1); return i == 1; } /// <summary> /// 播放背景音乐 /// </summary> /// <param name="canPlay"></param> public void PlayBacksound(string name, bool canPlay) { if (audio.clip != null) { if (name.IndexOf(audio.clip.name) > -1) { if (!canPlay) { audio.Stop(); audio.clip = null; Util.ClearMemory(); } return; } } if (canPlay) { audio.loop = true; audio.clip = LoadAudioClip(name); audio.Play(); } else { audio.Stop(); audio.clip = null; Util.ClearMemory(); } } /// <summary> /// 是否播放音效,默认是1:播放 /// </summary> /// <returns></returns> public bool CanPlaySoundEffect() { string key = AppConst.AppPrefix + "SoundEffect"; int i = PlayerPrefs.GetInt(key, 1); return i == 1; } /// <summary> /// 播放音频剪辑 /// </summary> /// <param name="clip"></param> /// <param name="position"></param> public void Play(AudioClip clip, Vector3 position) { if (!CanPlaySoundEffect()) return; AudioSource.PlayClipAtPoint(clip, position); } } }
using System.Collections; using System.Threading; using System.Collections.Generic; using System.IO; using System.Diagnostics; using System.Net; using System; public class ThreadEvent { public string Key; public List<object> evParams = new List<object>(); } public class NotiData { public string evName; public object evParam; public NotiData(string name, object param) { this.evName = name; this.evParam = param; } } namespace LuaFramework { /// <summary> /// 当前线程管理器,同时只能做一个任务 /// </summary> public class ThreadManager : Manager { private Thread thread; private Action<NotiData> func; private Stopwatch sw = new Stopwatch(); private string currDownFile = string.Empty; static readonly object m_lockObject = new object(); static Queue<ThreadEvent> events = new Queue<ThreadEvent>(); delegate void ThreadSyncEvent(NotiData data); private ThreadSyncEvent m_SyncEvent; void Awake() { m_SyncEvent = OnSyncEvent; thread = new Thread(OnUpdate); } // Use this for initialization void Start() { thread.Start(); } /// <summary> /// 添加到事件队列 /// </summary> public void AddEvent(ThreadEvent ev, Action<NotiData> func) { lock (m_lockObject) { this.func = func; events.Enqueue(ev); } } /// <summary> /// 通知事件 /// </summary> /// <param name="state"></param> private void OnSyncEvent(NotiData data) { if (this.func != null) func(data); //回调逻辑层 facade.SendMessageCommand(data.evName, data.evParam); //通知View层 } // Update is called once per frame void OnUpdate() { while (true) { lock (m_lockObject) { if (events.Count > 0) { ThreadEvent e = events.Dequeue(); try { switch (e.Key) { case NotiConst.UPDATE_EXTRACT: { //解压文件 OnExtractFile(e.evParams); } break; case NotiConst.UPDATE_DOWNLOAD: { //下载文件 OnDownloadFile(e.evParams); } break; } } catch (System.Exception ex) { UnityEngine.Debug.LogError(ex.Message); } } } Thread.Sleep(1); } } /// <summary> /// 下载文件 /// </summary> void OnDownloadFile(List<object> evParams) { string url = evParams[0].ToString(); currDownFile = evParams[1].ToString(); using (WebClient client = new WebClient()) { sw.Start(); client.DownloadProgressChanged += new DownloadProgressChangedEventHandler(ProgressChanged); client.DownloadFileAsync(new System.Uri(url), currDownFile); } } private void ProgressChanged(object sender, DownloadProgressChangedEventArgs e) { //UnityEngine.Debug.Log(e.ProgressPercentage); /* UnityEngine.Debug.Log(string.Format("{0} MB's / {1} MB's", (e.BytesReceived / 1024d / 1024d).ToString("0.00"), (e.TotalBytesToReceive / 1024d / 1024d).ToString("0.00"))); */ //float value = (float)e.ProgressPercentage / 100f; string value = string.Format("{0} kb/s", (e.BytesReceived / 1024d / sw.Elapsed.TotalSeconds).ToString("0.00")); NotiData data = new NotiData(NotiConst.UPDATE_PROGRESS, value); if (m_SyncEvent != null) m_SyncEvent(data); if (e.ProgressPercentage == 100 && e.BytesReceived == e.TotalBytesToReceive) { sw.Reset(); data = new NotiData(NotiConst.UPDATE_DOWNLOAD, currDownFile); if (m_SyncEvent != null) m_SyncEvent(data); } } /// <summary> /// 调用方法 /// </summary> void OnExtractFile(List<object> evParams) { UnityEngine.Debug.LogWarning("Thread evParams: >>" + evParams.Count); ///------------------通知更新面板解压完成-------------------- NotiData data = new NotiData(NotiConst.UPDATE_DOWNLOAD, null); if (m_SyncEvent != null) m_SyncEvent(data); } /// <summary> /// 应用程序退出 /// </summary> void OnDestroy() { thread.Abort(); } } }
using UnityEngine; using System.Collections; using System.Collections.Generic; namespace LuaFramework { public class TimerInfo { public long tick; public bool stop; public bool delete; public Object target; public string className; public TimerInfo(string className, Object target) { this.className = className; this.target = target; delete = false; } } public class TimerManager : Manager { private float interval = 0; private List<TimerInfo> objects = new List<TimerInfo>(); public float Interval { get { return interval; } set { interval = value; } } // Use this for initialization void Start() { StartTimer(AppConst.TimerInterval); } /// <summary> /// 启动计时器 /// </summary> /// <param name="interval"></param> public void StartTimer(float value) { interval = value; InvokeRepeating("Run", 0, interval); } /// <summary> /// 停止计时器 /// </summary> public void StopTimer() { CancelInvoke("Run"); } /// <summary> /// 添加计时器事件 /// </summary> /// <param name="name"></param> /// <param name="o"></param> public void AddTimerEvent(TimerInfo info) { if (!objects.Contains(info)) { objects.Add(info); } } /// <summary> /// 删除计时器事件 /// </summary> /// <param name="name"></param> public void RemoveTimerEvent(TimerInfo info) { if (objects.Contains(info) && info != null) { info.delete = true; } } /// <summary> /// 停止计时器事件 /// </summary> /// <param name="info"></param> public void StopTimerEvent(TimerInfo info) { if (objects.Contains(info) && info != null) { info.stop = true; } } /// <summary> /// 继续计时器事件 /// </summary> /// <param name="info"></param> public void ResumeTimerEvent(TimerInfo info) { if (objects.Contains(info) && info != null) { info.delete = false; } } /// <summary> /// 计时器运行 /// </summary> void Run() { if (objects.Count == 0) return; for (int i = 0; i < objects.Count; i++) { TimerInfo o = objects[i]; if (o.delete || o.stop) { continue; } ITimerBehaviour timer = o.target as ITimerBehaviour; timer.TimerUpdate(); o.tick++; } /////////////////////////清除标记为删除的事件/////////////////////////// for (int i = objects.Count - 1; i >= 0; i--) { if (objects[i].delete) { objects.Remove(objects[i]); } } } } }
using UnityEngine; using System.Collections; using System.IO; using System.Text; using System; using LuaInterface; namespace LuaFramework { public class ByteBuffer { MemoryStream stream = null; BinaryWriter writer = null; BinaryReader reader = null; public ByteBuffer() { stream = new MemoryStream(); writer = new BinaryWriter(stream); } public ByteBuffer(byte[] data) { if (data != null) { stream = new MemoryStream(data); reader = new BinaryReader(stream); } else { stream = new MemoryStream(); writer = new BinaryWriter(stream); } } public void Close() { if (writer != null) writer.Close(); if (reader != null) reader.Close(); stream.Close(); writer = null; reader = null; stream = null; } public void WriteByte(byte v) { writer.Write(v); } public void WriteInt(int v) { writer.Write((int)v); } public void WriteShort(ushort v) { writer.Write((ushort)v); } public void WriteLong(long v) { writer.Write((long)v); } public void WriteFloat(float v) { byte[] temp = BitConverter.GetBytes(v); Array.Reverse(temp); writer.Write(BitConverter.ToSingle(temp, 0)); } public void WriteDouble(double v) { byte[] temp = BitConverter.GetBytes(v); Array.Reverse(temp); writer.Write(BitConverter.ToDouble(temp, 0)); } public void WriteString(string v) { byte[] bytes = Encoding.UTF8.GetBytes(v); writer.Write((ushort)bytes.Length); writer.Write(bytes); } public void WriteBytes(byte[] v) { writer.Write((int)v.Length); writer.Write(v); } public void WriteBuffer(LuaByteBuffer strBuffer) { WriteBytes(strBuffer.buffer); } public byte ReadByte() { return reader.ReadByte(); } public int ReadInt() { return (int)reader.ReadInt32(); } public ushort ReadShort() { return (ushort)reader.ReadInt16(); } public long ReadLong() { return (long)reader.ReadInt64(); } public float ReadFloat() { byte[] temp = BitConverter.GetBytes(reader.ReadSingle()); Array.Reverse(temp); return BitConverter.ToSingle(temp, 0); } public double ReadDouble() { byte[] temp = BitConverter.GetBytes(reader.ReadDouble()); Array.Reverse(temp); return BitConverter.ToDouble(temp, 0); } public string ReadString() { ushort len = ReadShort(); byte[] buffer = new byte[len]; buffer = reader.ReadBytes(len); return Encoding.UTF8.GetString(buffer); } public byte[] ReadBytes() { int len = ReadInt(); return reader.ReadBytes(len); } public LuaByteBuffer ReadBuffer() { byte[] bytes = ReadBytes(); return new LuaByteBuffer(bytes); } public byte[] ToBytes() { writer.Flush(); return stream.ToArray(); } public void Flush() { writer.Flush(); } } }
/* * Copyright (c) 2008 Jonathan Wagner * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ using System; namespace LuaFramework { public class Converter { public static Int32 GetBigEndian(Int32 value) { if (BitConverter.IsLittleEndian) { return swapByteOrder(value); } else { return value; } } public static UInt16 GetBigEndian(UInt16 value) { if (BitConverter.IsLittleEndian) { return swapByteOrder(value); } else { return value; } } public static UInt32 GetBigEndian(UInt32 value) { if (BitConverter.IsLittleEndian) { return swapByteOrder(value); } else { return value; } } public static Int64 GetBigEndian(Int64 value) { if (BitConverter.IsLittleEndian) { return swapByteOrder(value); } else { return value; } } public static Double GetBigEndian(Double value) { if (BitConverter.IsLittleEndian) { return swapByteOrder(value); } else { return value; } } public static float GetBigEndian(float value) { if (BitConverter.IsLittleEndian) { return swapByteOrder((int)value); } else { return value; } } public static Int32 GetLittleEndian(Int32 value) { if (BitConverter.IsLittleEndian) { return value; } else { return swapByteOrder(value); } } public static UInt32 GetLittleEndian(UInt32 value) { if (BitConverter.IsLittleEndian) { return value; } else { return swapByteOrder(value); } } public static UInt16 GetLittleEndian(UInt16 value) { if (BitConverter.IsLittleEndian) { return value; } else { return swapByteOrder(value); } } public static Double GetLittleEndian(Double value) { if (BitConverter.IsLittleEndian) { return value; } else { return swapByteOrder(value); } } private static Int32 swapByteOrder(Int32 value) { Int32 swap = (Int32)((0x000000FF) & (value >> 24) | (0x0000FF00) & (value >> 8) | (0x00FF0000) & (value << 8) | (0xFF000000) & (value << 24)); return swap; } private static Int64 swapByteOrder(Int64 value) { UInt64 uvalue = (UInt64)value; UInt64 swap = ((0x00000000000000FF) & (uvalue >> 56) | (0x000000000000FF00) & (uvalue >> 40) | (0x0000000000FF0000) & (uvalue >> 24) | (0x00000000FF000000) & (uvalue >> 8) | (0x000000FF00000000) & (uvalue << 8) | (0x0000FF0000000000) & (uvalue << 24) | (0x00FF000000000000) & (uvalue << 40) | (0xFF00000000000000) & (uvalue << 56)); return (Int64)swap; } private static UInt16 swapByteOrder(UInt16 value) { return (UInt16)((0x00FF & (value >> 8)) | (0xFF00 & (value << 8))); } private static UInt32 swapByteOrder(UInt32 value) { UInt32 swap = ((0x000000FF) & (value >> 24) | (0x0000FF00) & (value >> 8) | (0x00FF0000) & (value << 8) | (0xFF000000) & (value << 24)); return swap; } private static Double swapByteOrder(Double value) { Byte[] buffer = BitConverter.GetBytes(value); Array.Reverse(buffer, 0, buffer.Length); return BitConverter.ToDouble(buffer, 0); } } }
namespace LuaFramework { public class Protocal { ///BUILD TABLE public const int Connect = 101; //连接服务器 public const int Exception = 102; //异常掉线 public const int Disconnect = 103; //正常断线 } }
using UnityEngine; using System; using System.IO; using System.Net; using System.Net.Sockets; using System.Collections; using System.Collections.Generic; using LuaFramework; public enum DisType { Exception, Disconnect, } public class SocketClient { private TcpClient client = null; private NetworkStream outStream = null; private MemoryStream memStream; private BinaryReader reader; private const int MAX_READ = 8192; private byte[] byteBuffer = new byte[MAX_READ]; public static bool loggedIn = false; // Use this for initialization public SocketClient() { } /// <summary> /// 注册代理 /// </summary> public void OnRegister() { memStream = new MemoryStream(); reader = new BinaryReader(memStream); } /// <summary> /// 移除代理 /// </summary> public void OnRemove() { this.Close(); reader.Close(); memStream.Close(); } /// <summary> /// 连接服务器 /// </summary> void ConnectServer(string host, int port) { client = null; try { IPAddress[] address = Dns.GetHostAddresses(host); if (address.Length == 0) { Debug.LogError("host invalid"); return; } if (address[0].AddressFamily == AddressFamily.InterNetworkV6) { client = new TcpClient(AddressFamily.InterNetworkV6); } else { client = new TcpClient(AddressFamily.InterNetwork); } client.SendTimeout = 1000; client.ReceiveTimeout = 1000; client.NoDelay = true; client.BeginConnect(host, port, new AsyncCallback(OnConnect), null); } catch (Exception e) { Close(); Debug.LogError(e.Message); } } /// <summary> /// 连接上服务器 /// </summary> void OnConnect(IAsyncResult asr) { outStream = client.GetStream(); client.GetStream().BeginRead(byteBuffer, 0, MAX_READ, new AsyncCallback(OnRead), null); NetworkManager.AddEvent(Protocal.Connect, new ByteBuffer()); } /// <summary> /// 写数据 /// </summary> void WriteMessage(byte[] message) { MemoryStream ms = null; using (ms = new MemoryStream()) { ms.Position = 0; BinaryWriter writer = new BinaryWriter(ms); ushort msglen = (ushort)message.Length; writer.Write(msglen); writer.Write(message); writer.Flush(); if (client != null && client.Connected) { //NetworkStream stream = client.GetStream(); byte[] payload = ms.ToArray(); outStream.BeginWrite(payload, 0, payload.Length, new AsyncCallback(OnWrite), null); } else { Debug.LogError("client.connected----->>false"); } } } /// <summary> /// 读取消息 /// </summary> void OnRead(IAsyncResult asr) { int bytesRead = 0; try { lock (client.GetStream()) { //读取字节流到缓冲区 bytesRead = client.GetStream().EndRead(asr); } if (bytesRead < 1) { //包尺寸有问题,断线处理 OnDisconnected(DisType.Disconnect, "bytesRead < 1"); return; } OnReceive(byteBuffer, bytesRead); //分析数据包内容,抛给逻辑层 lock (client.GetStream()) { //分析完,再次监听服务器发过来的新消息 Array.Clear(byteBuffer, 0, byteBuffer.Length); //清空数组 client.GetStream().BeginRead(byteBuffer, 0, MAX_READ, new AsyncCallback(OnRead), null); } } catch (Exception ex) { //PrintBytes(); OnDisconnected(DisType.Exception, ex.Message); } } /// <summary> /// 丢失链接 /// </summary> void OnDisconnected(DisType dis, string msg) { Close(); //关掉客户端链接 int protocal = dis == DisType.Exception ? Protocal.Exception : Protocal.Disconnect; ByteBuffer buffer = new ByteBuffer(); buffer.WriteShort((ushort)protocal); NetworkManager.AddEvent(protocal, buffer); Debug.LogError("Connection was closed by the server:>" + msg + " Distype:>" + dis); } /// <summary> /// 打印字节 /// </summary> /// <param name="bytes"></param> void PrintBytes() { string returnStr = string.Empty; for (int i = 0; i < byteBuffer.Length; i++) { returnStr += byteBuffer[i].ToString("X2"); } Debug.LogError(returnStr); } /// <summary> /// 向链接写入数据流 /// </summary> void OnWrite(IAsyncResult r) { try { outStream.EndWrite(r); } catch (Exception ex) { Debug.LogError("OnWrite--->>>" + ex.Message); } } /// <summary> /// 接收到消息 /// </summary> void OnReceive(byte[] bytes, int length) { memStream.Seek(0, SeekOrigin.End); memStream.Write(bytes, 0, length); //Reset to beginning memStream.Seek(0, SeekOrigin.Begin); while (RemainingBytes() > 2) { ushort messageLen = reader.ReadUInt16(); if (RemainingBytes() >= messageLen) { MemoryStream ms = new MemoryStream(); BinaryWriter writer = new BinaryWriter(ms); writer.Write(reader.ReadBytes(messageLen)); ms.Seek(0, SeekOrigin.Begin); OnReceivedMessage(ms); } else { //Back up the position two bytes memStream.Position = memStream.Position - 2; break; } } //Create a new stream with any leftover bytes byte[] leftover = reader.ReadBytes((int)RemainingBytes()); memStream.SetLength(0); //Clear memStream.Write(leftover, 0, leftover.Length); } /// <summary> /// 剩余的字节 /// </summary> private long RemainingBytes() { return memStream.Length - memStream.Position; } /// <summary> /// 接收到消息 /// </summary> /// <param name="ms"></param> void OnReceivedMessage(MemoryStream ms) { BinaryReader r = new BinaryReader(ms); byte[] message = r.ReadBytes((int)(ms.Length - ms.Position)); //int msglen = message.Length; ByteBuffer buffer = new ByteBuffer(message); int mainId = buffer.ReadShort(); NetworkManager.AddEvent(mainId, buffer); } /// <summary> /// 会话发送 /// </summary> void SessionSend(byte[] bytes) { WriteMessage(bytes); } /// <summary> /// 关闭链接 /// </summary> public void Close() { if (client != null) { if (client.Connected) client.Close(); client = null; } loggedIn = false; } /// <summary> /// 发送连接请求 /// </summary> public void SendConnect() { ConnectServer(AppConst.SocketAddress, AppConst.SocketPort); } /// <summary> /// 发送消息 /// </summary> public void SendMessage(ByteBuffer buffer) { SessionSend(buffer.ToBytes()); buffer.Close(); } }
using UnityEngine; using System; using System.Collections; using System.Collections.Generic; namespace LuaFramework { [Serializable] public class PoolInfo { public string poolName; public GameObject prefab; public int poolSize; public bool fixedSize; } public class GameObjectPool { private int maxSize; private int poolSize; private string poolName; private Transform poolRoot; private GameObject poolObjectPrefab; private Stack<GameObject> availableObjStack = new Stack<GameObject>(); public GameObjectPool(string poolName, GameObject poolObjectPrefab, int initCount, int maxSize, Transform pool) { this.poolName = poolName; this.poolSize = initCount; this.maxSize = maxSize; this.poolRoot = pool; this.poolObjectPrefab = poolObjectPrefab; //populate the pool for(int index = 0; index < initCount; index++) { AddObjectToPool(NewObjectInstance()); } } //o(1) private void AddObjectToPool(GameObject go) { //add to pool go.SetActive(false); availableObjStack.Push(go); go.transform.SetParent(poolRoot, false); } private GameObject NewObjectInstance() { return GameObject.Instantiate(poolObjectPrefab) as GameObject; } public GameObject NextAvailableObject() { GameObject go = null; if(availableObjStack.Count > 0) { go = availableObjStack.Pop(); } else { Debug.LogWarning("No object available & cannot grow pool: " + poolName); } go.SetActive(true); return go; } //o(1) public void ReturnObjectToPool(string pool, GameObject po) { if (poolName.Equals(pool)) { AddObjectToPool(po); } else { Debug.LogError(string.Format("Trying to add object to incorrect pool {0} ", poolName)); } } } }
using System.Collections.Generic; using UnityEngine; using UnityEngine.Events; namespace LuaFramework { public class ObjectPool<T> where T : class { private readonly Stack<T> m_Stack = new Stack<T>(); private readonly UnityAction<T> m_ActionOnGet; private readonly UnityAction<T> m_ActionOnRelease; public int countAll { get; private set; } public int countActive { get { return countAll - countInactive; } } public int countInactive { get { return m_Stack.Count; } } public ObjectPool(UnityAction<T> actionOnGet, UnityAction<T> actionOnRelease) { m_ActionOnGet = actionOnGet; m_ActionOnRelease = actionOnRelease; } public T Get() { T element = m_Stack.Pop(); if (m_ActionOnGet != null) m_ActionOnGet(element); return element; } public void Release(T element) { if (m_Stack.Count > 0 && ReferenceEquals(m_Stack.Peek(), element)) Debug.LogError("Internal error. Trying to destroy object that is already released to pool."); if (m_ActionOnRelease != null) m_ActionOnRelease(element); m_Stack.Push(element); } } }
using UnityEngine; using System.Collections; namespace LuaFramework { public class TestObjectClass { public string name; public int value1; public float value2; // Use this for initialization public TestObjectClass(string name, int value1, float value2) { this.name = name; this.value1 = value1; this.value2 = value2; } public string ToString() { return string.Format("name={0} value1={1} = value2={2}", name, value1, value2); } } }
using UnityEngine; using System.Collections.Generic; using System.Reflection; using LuaInterface; using System; namespace LuaFramework { public static class LuaHelper { /// <summary> /// getType /// </summary> /// <param name="classname"></param> /// <returns></returns> public static System.Type GetType(string classname) { Assembly assb = Assembly.GetExecutingAssembly(); //.GetExecutingAssembly(); System.Type t = null; t = assb.GetType(classname); ; if (t == null) { t = assb.GetType(classname); } return t; } /// <summary> /// 面板管理器 /// </summary> public static PanelManager GetPanelManager() { return AppFacade.Instance.GetManager<PanelManager>(ManagerName.Panel); } /// <summary> /// 资源管理器 /// </summary> public static ResourceManager GetResManager() { return AppFacade.Instance.GetManager<ResourceManager>(ManagerName.Resource); } /// <summary> /// 网络管理器 /// </summary> public static NetworkManager GetNetManager() { return AppFacade.Instance.GetManager<NetworkManager>(ManagerName.Network); } /// <summary> /// 音乐管理器 /// </summary> public static SoundManager GetSoundManager() { return AppFacade.Instance.GetManager<SoundManager>(ManagerName.Sound); } /// <summary> /// pbc/pblua函数回调 /// </summary> /// <param name="func"></param> public static void OnCallLuaFunc(LuaByteBuffer data, LuaFunction func) { if (func != null) func.Call(data); Debug.LogWarning("OnCallLuaFunc length:>>" + data.buffer.Length); } /// <summary> /// cjson函数回调 /// </summary> /// <param name="data"></param> /// <param name="func"></param> public static void OnJsonCallFunc(string data, LuaFunction func) { Debug.LogWarning("OnJsonCallback data:>>" + data + " lenght:>>" + data.Length); if (func != null) func.Call(data); } } }
using UnityEngine; using System; using System.IO; using System.Text; using System.Collections; using System.Collections.Generic; using System.Security.Cryptography; using System.Text.RegularExpressions; using LuaInterface; using LuaFramework; #if UNITY_EDITOR using UnityEditor; #endif namespace LuaFramework { public class Util { private static List<string> luaPaths = new List<string>(); public static int Int(object o) { return Convert.ToInt32(o); } public static float Float(object o) { return (float)Math.Round(Convert.ToSingle(o), 2); } public static long Long(object o) { return Convert.ToInt64(o); } public static int Random(int min, int max) { return UnityEngine.Random.Range(min, max); } public static float Random(float min, float max) { return UnityEngine.Random.Range(min, max); } public static string Uid(string uid) { int position = uid.LastIndexOf('_'); return uid.Remove(0, position + 1); } public static long GetTime() { TimeSpan ts = new TimeSpan(DateTime.UtcNow.Ticks - new DateTime(1970, 1, 1, 0, 0, 0).Ticks); return (long)ts.TotalMilliseconds; } /// <summary> /// 搜索子物体组件-GameObject版 /// </summary> public static T Get<T>(GameObject go, string subnode) where T : Component { if (go != null) { Transform sub = go.transform.Find(subnode); if (sub != null) return sub.GetComponent<T>(); } return null; } /// <summary> /// 搜索子物体组件-Transform版 /// </summary> public static T Get<T>(Transform go, string subnode) where T : Component { if (go != null) { Transform sub = go.Find(subnode); if (sub != null) return sub.GetComponent<T>(); } return null; } /// <summary> /// 搜索子物体组件-Component版 /// </summary> public static T Get<T>(Component go, string subnode) where T : Component { return go.transform.Find(subnode).GetComponent<T>(); } /// <summary> /// 添加组件 /// </summary> public static T Add<T>(GameObject go) where T : Component { if (go != null) { T[] ts = go.GetComponents<T>(); for (int i = 0; i < ts.Length; i++) { if (ts[i] != null) GameObject.Destroy(ts[i]); } return go.gameObject.AddComponent<T>(); } return null; } /// <summary> /// 添加组件 /// </summary> public static T Add<T>(Transform go) where T : Component { return Add<T>(go.gameObject); } /// <summary> /// 查找子对象 /// </summary> public static GameObject Child(GameObject go, string subnode) { return Child(go.transform, subnode); } /// <summary> /// 查找子对象 /// </summary> public static GameObject Child(Transform go, string subnode) { Transform tran = go.Find(subnode); if (tran == null) return null; return tran.gameObject; } /// <summary> /// 取平级对象 /// </summary> public static GameObject Peer(GameObject go, string subnode) { return Peer(go.transform, subnode); } /// <summary> /// 取平级对象 /// </summary> public static GameObject Peer(Transform go, string subnode) { Transform tran = go.parent.Find(subnode); if (tran == null) return null; return tran.gameObject; } /// <summary> /// 计算字符串的MD5值 /// </summary> public static string md5(string source) { MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider(); byte[] data = System.Text.Encoding.UTF8.GetBytes(source); byte[] md5Data = md5.ComputeHash(data, 0, data.Length); md5.Clear(); string destString = ""; for (int i = 0; i < md5Data.Length; i++) { destString += System.Convert.ToString(md5Data[i], 16).PadLeft(2, '0'); } destString = destString.PadLeft(32, '0'); return destString; } /// <summary> /// 计算文件的MD5值 /// </summary> public static string md5file(string file) { try { FileStream fs = new FileStream(file, FileMode.Open); System.Security.Cryptography.MD5 md5 = new System.Security.Cryptography.MD5CryptoServiceProvider(); byte[] retVal = md5.ComputeHash(fs); fs.Close(); StringBuilder sb = new StringBuilder(); for (int i = 0; i < retVal.Length; i++) { sb.Append(retVal[i].ToString("x2")); } return sb.ToString(); } catch (Exception ex) { throw new Exception("md5file() fail, error:" + ex.Message); } } /// <summary> /// 清除所有子节点 /// </summary> public static void ClearChild(Transform go) { if (go == null) return; for (int i = go.childCount - 1; i >= 0; i--) { GameObject.Destroy(go.GetChild(i).gameObject); } } /// <summary> /// 清理内存 /// </summary> public static void ClearMemory() { GC.Collect(); Resources.UnloadUnusedAssets(); LuaManager mgr = AppFacade.Instance.GetManager<LuaManager>(ManagerName.Lua); if (mgr != null) mgr.LuaGC(); } /// <summary> /// 取得数据存放目录 /// </summary> public static string DataPath { get { string game = AppConst.AppName.ToLower(); if (Application.isMobilePlatform) { return Application.persistentDataPath + "/" + game + "/"; } if (AppConst.DebugMode) { return Application.dataPath + "/" + AppConst.AssetDir + "/"; } if (Application.platform == RuntimePlatform.OSXEditor) { int i = Application.dataPath.LastIndexOf('/'); return Application.dataPath.Substring(0, i + 1) + game + "/"; } return "c:/" + game + "/"; } } public static string GetRelativePath() { if (Application.isEditor) return "file://" + System.Environment.CurrentDirectory.Replace("\\", "/") + "/Assets/" + AppConst.AssetDir + "/"; else if (Application.isMobilePlatform || Application.isConsolePlatform) return "file:///" + DataPath; else // For standalone player. return "file://" + Application.streamingAssetsPath + "/"; } /// <summary> /// 取得行文本 /// </summary> public static string GetFileText(string path) { return File.ReadAllText(path); } /// <summary> /// 网络可用 /// </summary> public static bool NetAvailable { get { return Application.internetReachability != NetworkReachability.NotReachable; } } /// <summary> /// 是否是无线 /// </summary> public static bool IsWifi { get { return Application.internetReachability == NetworkReachability.ReachableViaLocalAreaNetwork; } } /// <summary> /// 应用程序内容路径 /// </summary> public static string AppContentPath() { string path = string.Empty; switch (Application.platform) { case RuntimePlatform.Android: path = "jar:file://" + Application.dataPath + "!/assets/"; break; case RuntimePlatform.IPhonePlayer: path = Application.dataPath + "/Raw/"; break; default: path = Application.dataPath + "/" + AppConst.AssetDir + "/"; break; } return path; } public static void Log(string str) { Debug.Log(str); } public static void LogWarning(string str) { Debug.LogWarning(str); } public static void LogError(string str) { Debug.LogError(str); } /// <summary> /// 防止初学者不按步骤来操作 /// </summary> /// <returns></returns> public static int CheckRuntimeFile() { if (!Application.isEditor) return 0; string streamDir = Application.dataPath + "/StreamingAssets/"; if (!Directory.Exists(streamDir)) { return -1; } else { string[] files = Directory.GetFiles(streamDir); if (files.Length == 0) return -1; if (!File.Exists(streamDir + "files.txt")) { return -1; } } string sourceDir = AppConst.FrameworkRoot + "/ToLua/Source/Generate/"; if (!Directory.Exists(sourceDir)) { return -2; } else { string[] files = Directory.GetFiles(sourceDir); if (files.Length == 0) return -2; } return 0; } /// <summary> /// 执行Lua方法 /// </summary> public static object[] CallMethod(string module, string func, params object[] args) { LuaManager luaMgr = AppFacade.Instance.GetManager<LuaManager>(ManagerName.Lua); if (luaMgr == null) return null; return luaMgr.CallFunction(module + "." + func, args); } /// <summary> /// 检查运行环境 /// </summary> public static bool CheckEnvironment() { #if UNITY_EDITOR int resultId = Util.CheckRuntimeFile(); if (resultId == -1) { Debug.LogError("没有找到框架所需要的资源,单击Game菜单下Build xxx Resource生成!!"); EditorApplication.isPlaying = false; return false; } else if (resultId == -2) { Debug.LogError("没有找到Wrap脚本缓存,单击Lua菜单下Gen Lua Wrap Files生成脚本!!"); EditorApplication.isPlaying = false; return false; } if (Application.loadedLevelName == "Test" && !AppConst.DebugMode) { Debug.LogError("测试场景,必须打开调试模式,AppConst.DebugMode = true!!"); EditorApplication.isPlaying = false; return false; } #endif return true; } } }
using UnityEngine; using LuaFramework; using System.Collections.Generic; public class AppView : View { private string message; ///<summary> /// 监听的消息 ///</summary> List<string> MessageList { get { return new List<string>() { NotiConst.UPDATE_MESSAGE, NotiConst.UPDATE_EXTRACT, NotiConst.UPDATE_DOWNLOAD, NotiConst.UPDATE_PROGRESS, }; } } void Awake() { RemoveMessage(this, MessageList); RegisterMessage(this, MessageList); } /// <summary> /// 处理View消息 /// </summary> /// <param name="message"></param> public override void OnMessage(IMessage message) { string name = message.Name; object body = message.Body; switch (name) { case NotiConst.UPDATE_MESSAGE: //更新消息 UpdateMessage(body.ToString()); break; case NotiConst.UPDATE_EXTRACT: //更新解压 UpdateExtract(body.ToString()); break; case NotiConst.UPDATE_DOWNLOAD: //更新下载 UpdateDownload(body.ToString()); break; case NotiConst.UPDATE_PROGRESS: //更新下载进度 UpdateProgress(body.ToString()); break; } } public void UpdateMessage(string data) { this.message = data; } public void UpdateExtract(string data) { this.message = data; } public void UpdateDownload(string data) { this.message = data; } public void UpdateProgress(string data) { this.message = data; } void OnGUI() { GUI.Label(new Rect(10, 120, 960, 50), message); GUI.Label(new Rect(10, 0, 500, 50), "(1) 单击 \"Lua/Gen Lua Wrap Files\"。"); GUI.Label(new Rect(10, 20, 500, 50), "(2) 运行Unity游戏"); GUI.Label(new Rect(10, 40, 500, 50), "PS: 清除缓存,单击\"Lua/Clear LuaBinder File + Wrap Files\"。"); GUI.Label(new Rect(10, 60, 900, 50), "PS: 若运行到真机,请设置Const.DebugMode=false,本地调试请设置Const.DebugMode=true"); GUI.Label(new Rect(10, 80, 500, 50), "PS: 加Unity+ulua技术讨论群:>>341746602"); } }
using UnityEngine; using System.Collections; namespace LuaFramework { /// <summary> /// </summary> public class Main : MonoBehaviour { void Start() { AppFacade.Instance.StartUp(); //启动游戏 } } }