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!");
}
}
}
Common/LuaBehaviour
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);
}
}
}
Common/LuaLoader
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 = ;
public const int GameFrameRate = ; //游戏帧频 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 = ; //Socket服务器端口
public static string SocketAddress = string.Empty; //Socket服务器地址 public static string FrameworkRoot {
get {
return Application.dataPath + "/" + AppName;
}
}
}
}
ConstDefine/AppConst
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";
}
}
ConstDefine/ManagerName
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"; //更新进度
}
ConstDefine/NotiConst
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;
}
}
}
Controller/Command/SocketCommand
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);
}
}
Controller/Command/StartUpCommand
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 == ) 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 == ) 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;
}
}
}
Framework/Core/Base
/*
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 = ; i < count; i++) {
RegisterCommand(commandNames[i], commandType);
}
} public void RemoveMultiCommand(params string[] commandName) {
int count = commandName.Length;
for (int i = ; 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);
}
}
Framework/Core/ControllerCommand, Facade
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 () { }
}
Framework/Core/Manager
/*
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;
}
Framework/Core/Message
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) {
}
}
Framework/Core/View
/*
LuaFramework Code By Jarjin lee
*/
using System; public interface ICommand {
void Execute(IMessage message);
}
Framework/Interface/ICommand
/*
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);
}
Framework/Interface/IController
/*
LuaFramework Code By Jarjin leeibution 3.0 License
*/ using UnityEngine;
using System.Collections; public interface IManager {
}
Framework/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();
}
Framework/Interface/IMessage
using System; public interface IView {
void OnMessage(IMessage message);
}
Framework/Interface/IView
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);
}
}
Framework/AppFacade
using System;
using System.Collections; namespace LuaFramework {
public interface ITimerBehaviour {
void TimerUpdate();
}
}
Manager/Interface
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 ;
} 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[]; //
outfile = dataPath + fs[]; message = "正在解包文件:>" + fs[];
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 ;
} 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 = ; i < files.Length; i++) {
if (string.IsNullOrEmpty(files[i])) continue;
string[] keyValue = files[i].Split('|');
string f = keyValue[];
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[].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[] { 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", , 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", , , 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");
}
}
}
Manager/GameManager
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(); 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(-, "cjson"); lua.OpenLibs(LuaDLL.luaopen_cjson_safe);
lua.LuaSetField(-, "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;
}
}
}
Manager/LuaManager
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 > ) {
while (mEvents.Count > ) {
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");
}
}
}
Manager/NetworkManager
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);
}
}
}
}
Manager/ObjectPoolManager
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 == ) return;
GameObject prefab = objs[] 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);
}
}
}
Manager/PanelManager
#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 = ;
}
} 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 > ) {
m_AssetBundleManifest = objs[] 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 = ; i < m_AllManifest.Length; i++) {
int index = m_AllManifest[i].LastIndexOf('/');
string path = m_AllManifest[i].Remove(, index + ); //字符串操作函数都会产生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 = ; i < list.Count; i++) {
string[] assetNames = list[i].assetNames;
List<UObject> result = new List<UObject>(); AssetBundle ab = bundleInfo.m_AssetBundle;
for (int j = ; 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 > ) {
m_Dependencies.Add(abName, dependencies);
for (int i = ; 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), );
}
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 <= ) {
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 = ; 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 == ) return; for (int i = ; i < dependencies.Length; i++)
dependencies[i] = RemapVariantName(dependencies[i]); // Record and load all dependencies.
for (int i = ; 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) < )
return assetBundleName; string[] split = assetBundleName.Split('.'); int bestFit = int.MaxValue;
int bestFitIndex = -;
// Loop all the assetBundles with variant to find the best fit variant assetBundle.
for (int i = ; i < bundlesWithVariant.Length; i++) {
string[] curSplit = bundlesWithVariant[i].Split('.');
if (curSplit[] != split[])
continue; int found = System.Array.IndexOf(m_Variants, curSplit[]);
if (found != - && found < bestFit) {
bestFit = found;
bestFitIndex = i;
}
}
if (bestFitIndex != -)
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
Manager/ResourceManager, AssetBundleInfo
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, );
return i == ;
} /// <summary>
/// 播放背景音乐
/// </summary>
/// <param name="canPlay"></param>
public void PlayBacksound(string name, bool canPlay) {
if (audio.clip != null) {
if (name.IndexOf(audio.clip.name) > -) {
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, );
return i == ;
} /// <summary>
/// 播放音频剪辑
/// </summary>
/// <param name="clip"></param>
/// <param name="position"></param>
public void Play(AudioClip clip, Vector3 position) {
if (!CanPlaySoundEffect()) return;
AudioSource.PlayClipAtPoint(clip, position);
}
}
}
Manager/SoundManager
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 > ) {
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();
}
} /// <summary>
/// 下载文件
/// </summary>
void OnDownloadFile(List<object> evParams) {
string url = evParams[].ToString();
currDownFile = evParams[].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 == && 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();
}
}
}
Manager/ThreadManager, ThreadEvent, NotiData
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 = ;
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", , 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 == ) return;
for (int i = ; 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 - ; i >= ; i--) {
if (objects[i].delete) { objects.Remove(objects[i]); }
}
}
}
}
Manager/TimerManager, TimerInfo
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, ));
} public void WriteDouble(double v) {
byte[] temp = BitConverter.GetBytes(v);
Array.Reverse(temp);
writer.Write(BitConverter.ToDouble(temp, ));
} 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, );
} public double ReadDouble() {
byte[] temp = BitConverter.GetBytes(reader.ReadDouble());
Array.Reverse(temp);
return BitConverter.ToDouble(temp, );
} 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();
}
}
}
Network/ByteBuffer
/*
* 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 >> )
| (0x0000FF00) & (value >> )
| (0x00FF0000) & (value << )
| (0xFF000000) & (value << ));
return swap;
} private static Int64 swapByteOrder(Int64 value) {
UInt64 uvalue = (UInt64)value;
UInt64 swap = ((0x00000000000000FF) & (uvalue >> )
| (0x000000000000FF00) & (uvalue >> )
| (0x0000000000FF0000) & (uvalue >> )
| (0x00000000FF000000) & (uvalue >> )
| (0x000000FF00000000) & (uvalue << )
| (0x0000FF0000000000) & (uvalue << )
| (0x00FF000000000000) & (uvalue << )
| (0xFF00000000000000) & (uvalue << )); return (Int64)swap;
} private static UInt16 swapByteOrder(UInt16 value) {
return (UInt16)((0x00FF & (value >> ))
| (0xFF00 & (value << )));
} private static UInt32 swapByteOrder(UInt32 value) {
UInt32 swap = ((0x000000FF) & (value >> )
| (0x0000FF00) & (value >> )
| (0x00FF0000) & (value << )
| (0xFF000000) & (value << ));
return swap;
} private static Double swapByteOrder(Double value) {
Byte[] buffer = BitConverter.GetBytes(value);
Array.Reverse(buffer, , buffer.Length);
return BitConverter.ToDouble(buffer, );
}
}
}
Network/Converter
namespace LuaFramework {
public class Protocal {
///BUILD TABLE
public const int Connect = ; //连接服务器
public const int Exception = ; //异常掉线
public const int Disconnect = ; //正常断线
}
}
Network/Protocal
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 = ;
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 == ) {
Debug.LogError("host invalid");
return;
}
if (address[].AddressFamily == AddressFamily.InterNetworkV6) {
client = new TcpClient(AddressFamily.InterNetworkV6);
}
else {
client = new TcpClient(AddressFamily.InterNetwork);
}
client.SendTimeout = ;
client.ReceiveTimeout = ;
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, , 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 = ;
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, , payload.Length, new AsyncCallback(OnWrite), null);
} else {
Debug.LogError("client.connected----->>false");
}
}
} /// <summary>
/// 读取消息
/// </summary>
void OnRead(IAsyncResult asr) {
int bytesRead = ;
try {
lock (client.GetStream()) { //读取字节流到缓冲区
bytesRead = client.GetStream().EndRead(asr);
}
if (bytesRead < ) { //包尺寸有问题,断线处理
OnDisconnected(DisType.Disconnect, "bytesRead < 1");
return;
}
OnReceive(byteBuffer, bytesRead); //分析数据包内容,抛给逻辑层
lock (client.GetStream()) { //分析完,再次监听服务器发过来的新消息
Array.Clear(byteBuffer, , byteBuffer.Length); //清空数组
client.GetStream().BeginRead(byteBuffer, , 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 = ; 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(, SeekOrigin.End);
memStream.Write(bytes, , length);
//Reset to beginning
memStream.Seek(, SeekOrigin.Begin);
while (RemainingBytes() > ) {
ushort messageLen = reader.ReadUInt16();
if (RemainingBytes() >= messageLen) {
MemoryStream ms = new MemoryStream();
BinaryWriter writer = new BinaryWriter(ms);
writer.Write(reader.ReadBytes(messageLen));
ms.Seek(, SeekOrigin.Begin);
OnReceivedMessage(ms);
} else {
//Back up the position two bytes
memStream.Position = memStream.Position - ;
break;
}
}
//Create a new stream with any leftover bytes
byte[] leftover = reader.ReadBytes((int)RemainingBytes());
memStream.SetLength(); //Clear
memStream.Write(leftover, , 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();
}
}
Network/SocketClient, DisType
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 = ; 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 > ) {
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));
}
}
}
}
ObjectPool/GameObjectPool, PoolInfo
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 > && 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);
}
}
}
ObjectPool/ObjectPool
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);
}
}
}
ObjectPool/TestObjectClass
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);
}
}
}
Utility/LuaHelper
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), );
} 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(, position + );
} public static long GetTime() {
TimeSpan ts = new TimeSpan(DateTime.UtcNow.Ticks - new DateTime(, , , , , ).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 = ; 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, , data.Length);
md5.Clear(); string destString = "";
for (int i = ; i < md5Data.Length; i++) {
destString += System.Convert.ToString(md5Data[i], ).PadLeft(, '');
}
destString = destString.PadLeft(, '');
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 = ; 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 - ; i >= ; 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(, i + ) + 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 ;
string streamDir = Application.dataPath + "/StreamingAssets/";
if (!Directory.Exists(streamDir)) {
return -;
} else {
string[] files = Directory.GetFiles(streamDir);
if (files.Length == ) return -; if (!File.Exists(streamDir + "files.txt")) {
return -;
}
}
string sourceDir = AppConst.FrameworkRoot + "/ToLua/Source/Generate/";
if (!Directory.Exists(sourceDir)) {
return -;
} else {
string[] files = Directory.GetFiles(sourceDir);
if (files.Length == ) return -;
}
return ;
} /// <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 == -) {
Debug.LogError("没有找到框架所需要的资源,单击Game菜单下Build xxx Resource生成!!");
EditorApplication.isPlaying = false;
return false;
} else if (resultId == -) {
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;
}
}
}
Utility/Util
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(, , , ), message); GUI.Label(new Rect(, , , ), "(1) 单击 \"Lua/Gen Lua Wrap Files\"。");
GUI.Label(new Rect(, , , ), "(2) 运行Unity游戏");
GUI.Label(new Rect(, , , ), "PS: 清除缓存,单击\"Lua/Clear LuaBinder File + Wrap Files\"。");
GUI.Label(new Rect(, , , ), "PS: 若运行到真机,请设置Const.DebugMode=false,本地调试请设置Const.DebugMode=true");
GUI.Label(new Rect(, , , ), "PS: 加Unity+ulua技术讨论群:>>341746602");
}
}
View/AppView
using UnityEngine;
using System.Collections; namespace LuaFramework { /// <summary>
/// </summary>
public class Main : MonoBehaviour { void Start() {
AppFacade.Instance.StartUp(); //启动游戏
}
}
}
Main
LuaFramework 学习的更多相关文章
- Unity3D热更新之LuaFramework篇[10]--总结篇
背景 19年年初的时候,进到一家新单位,公司正准备将现有的游戏做成支持热更的版本.于是寻找热更方案的任务就落在了我头上. 经过搜索了解,能做Unity热更的方案是有好几种,但是要么不够成熟,要么不支持 ...
- Unity3D热更新之LuaFramework篇[04]--自定义UI监听方法
时隔一个多月我又回来啦! 坚持真的是很难的一件事,其它事情稍忙,就很容易说服自己把写博客的计划给推迟了. 好在终于克服了自己的惰性,今天又开始了. 本篇继续我的Luaframework学习之路. 一. ...
- Unity3D热更新之LuaFramework篇[02]--用Lua创建自己的面板
在上篇文章 Unity3D热更新之LuaFramework篇[01]--从零开始 中,我们了解了怎么获得一个可用的LuaFramework框架. 本篇将我会先介绍一下如何配置Lua开发环境,然后分析在 ...
- Unity3D热更新之LuaFramework篇[08]--热更新原理及热更服务器搭建
前言 前面铺垫了这么久,终于要开始写热更新了. Unity游戏热更新包含两个方面,一个是资源的更新,一个是脚本的更新. 资源更新是Unity本来就支持的,在各大平台也都能用.而脚本的热更新在iOS平台 ...
- Unity3D热更新之LuaFramework篇[09]--资源热更新与代码热更新的具体实现
前言 在上一篇文章 Unity3D热更新之LuaFramework篇[08]--热更新原理及热更服务器搭建 中,我介绍了热更新的基本原理,并且着手搭建一台服务器. 本篇就做一个实战练习,真正的来实现热 ...
- 从直播编程到直播教育:LiveEdu.tv开启多元化的在线学习直播时代
2015年9月,一个叫Livecoding.tv的网站在互联网上引起了编程界的注意.缘于Pingwest品玩的一位编辑在上网时无意中发现了这个网站,并写了一篇文章<一个比直播睡觉更奇怪的网站:直 ...
- Angular2学习笔记(1)
Angular2学习笔记(1) 1. 写在前面 之前基于Electron写过一个Markdown编辑器.就其功能而言,主要功能已经实现,一些小的不影响使用的功能由于时间关系还没有完成:但就代码而言,之 ...
- ABP入门系列(1)——学习Abp框架之实操演练
作为.Net工地搬砖长工一名,一直致力于挖坑(Bug)填坑(Debug),但技术却不见长进.也曾热情于新技术的学习,憧憬过成为技术大拿.从前端到后端,从bootstrap到javascript,从py ...
- 消息队列——RabbitMQ学习笔记
消息队列--RabbitMQ学习笔记 1. 写在前面 昨天简单学习了一个消息队列项目--RabbitMQ,今天趁热打铁,将学到的东西记录下来. 学习的资料主要是官网给出的6个基本的消息发送/接收模型, ...
随机推荐
- webpack打包优化实践
事情缘由 近段时间在做基于scratch3.0的改造项目.基于scratch-gui改造,项目本身已经很大了,然后里面还要用到scratch-blocks,scratch-vm,scratch-ren ...
- linux--新装机图形化界面遇到的问题
1 许可证信息 q 退出 c 继续 r 刷新 按以下顺序正确输入即可: 1 ------ 2 ----- q ----- yes
- Saiku上线部署准备(三十)
Saiku上线部署准备 零零散散琢磨了快5个月了,终于快要上线了哈哈哈哈哈..... 激动!!! 以下是本地打包编译saiku至部署到服务器上使用的完整步骤哦 saiku部署到服务器 源码编译需要注 ...
- H5生成二维码
要用H5生成二维码: 1.引入js库,可自行点击链接复制使用 <script type="text/javascript" src="http://static.r ...
- json数据格式与字典数据类型之间的相互转换
import json class HandleJson: ''' 定义一个json格式数据处理类 ''' @staticmethod def loads_data(data): ''' 将json数 ...
- 打开Github网站反应慢的问题
解决办法: 为了提高速度,可以使用HOSTS加速对Github网站加载的资源网站域名解析. 具体做法: 修改 C:\Windows\System32\drivers\etc 中的hosts文件(P ...
- Pull Request找原作者做review
最近对代码库进行了一次全局替换,改了150个左右的文件,发了PR后需要找原作者确认一下,于是写了个工具做git blame,地址在这里 写完发现一个问题,如果只是新增一个函数,没有调用,是应该不用找原 ...
- 这篇文章带你彻底理解synchronized
本人免费整理了Java高级资料,涵盖了Java.Redis.MongoDB.MySQL.Zookeeper.Spring Cloud.Dubbo高并发分布式等教程,一共30G,需要自己领取.传送门:h ...
- Java日期时间API系列2-----Jdk7及以前的日期时间类在mysql数据库中的应用
1.java中与数据库相关的时间类 java提供与mysql方便交互的三种数据类型: java.sql.Date java.sql.Time java.sql.Timestamp 它们都是继承java ...
- 在vcs中编译及运行测试E203例子
E203的Makefile默认是调用 iverilog编译rtl,我们可以做如下修改,使其支持vcs编译. 1. 首先修改e200_opensource/tb/tb_top.v, 增加dump波形的两 ...