luascriptmgrscript是什么意思思

Unity的uLua库添加lua-pb实现网络通信 - 简书
<div class="fixed-btn note-fixed-download" data-toggle="popover" data-placement="left" data-html="true" data-trigger="hover" data-content=''>
写了4425字,被19人关注,获得了9个喜欢
Unity的uLua库添加lua-pb实现网络通信
为什么要添加lua-pb模块?
Unity项目中需要使用protocol buffer作为网络通信的序列化格式。本身包含了一些protobuf的处理模块,比如sproto,pblua等等。但是实测下来发现这些预置的模块或多或少都有些严重的缺陷,比较严重的有如下几条:
有的模块不支持default关键字
有的模块解析proto之后会生成一个lua文件,但是如果proto文件很长,生成出来的lua文件会由于local变量太多而解析出错。
这些问题导致现有的模块不能满足项目开发的需求,只能寻求第三方的解决方案。模块是一个开源的protobuf的lua解析模块,功能比较齐全。于是决定把lua-pb模块集成到uLua中,替换掉ulua本身的解析模块。
的源码可以从
下载struct
lua-pb依赖三个lua的扩展库,lpeg,luabitop和struct,前两个已经包含在了ulua中,只需添加struct支持即可。struct是lua的一个c扩展库,为lua提供了c struct的支持。struct的下载地址是
修改uLua工程
不同平台下需要分别编译ulua,至少需要编译windows,mac,ios和android平台的版本。uLua的源码仓库内有每个平台工程的详细文档,需要按照文档操作。windows,mac,ios和android使用了不同的工程和编译工具链来编译,所以需要分别添加struct到对应的工程中。下面截图是mac平台的例子,其它的工程类似。
mac版本使用xcode编译,编译出来的是一个bundle。将这个bundle替换工程中的Plugins目录下原来的uLua.bundle就可以了。ios版本一样使用xcode编译,编译出来的是一个静态库,静态库中需要包含armv7和arm64两个CPU架构。使用编译出来的静态库替换掉Plugins/iOS目录下原来的libulua.a文件就可以了。android版本使用ndk编译,需要编译v7a和x86两个版本,编译出来的是个.so的动态库。替换掉Plugins/Android/libs对应目录下的旧文件就可以了。windows版本在msys环境下编译,msys的下载地址参照ulua编译文档里的说明。需要编译x86和x64两个版本,替换掉Plugins目录下对应的ulua.dll就可以了。
修改uLua的C#源码
LuaDLL.cs:112的LuaDLL类中添加
[DllImport(LUADLL, CallingConvention = CallingConvention.Cdecl)]
public static extern int luaopen_struct(IntPtr L);
LuaScriptMgr.cs:213中LuaScriptMgr的构造函数中添加
LuaDLL.luaopen_struct(lua.L);
使用lua-pb
假如有如下的message定义在proto文件中
message LOGIN_RESULT()
optional int32 cmd_id = 1 [default = 100];
required int32 result = 2;
可以按照如下测试代码在lua中处理消息的序列化和反序列化。序列化之后的字节流一般通过socket发送给服务器。
funciton ProtoTest()
local sendMsg = Protocol.LOGIN_RESULT()
sendMsg.result = 100
local bytes = sendMsg:Serialize()
-- 反序列化
local recvMsg = Protocol.LOGIN_RESULT()
recvMsg:Parse(bytes)
print("received result" ... recvMsg.result)
在ulua中,添加第三方的lua的c语言扩展库是比较简单的,感谢ulua的开发者的工作。添加lua-pb需要改写ulua的源代码,更改之后的ulua源代码也一并上传到了github上,地址是
一直在更新,目前推荐的版本是。本文的内容可能不直接适用,但是原理是类似的。
(全文完)
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
打开微信“扫一扫”,打开网页后点击屏幕右上角分享按钮
被以下专题收入,发现更多相似内容:
如果你是程序员,或者有一颗喜欢写程序的心,喜欢分享技术干货、项目经验、程序员日常囧事等等,欢迎投稿《程序员》专题。
专题主编:小...
· 272968人关注
Unity3D引擎技术讨论专题
· 564人关注
如果你用c语言编程,又学java,lisp,python,还晓得perl,javascript,C#,有时候弄些LaTeX文档,知道B...
· 487人关注
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
选择支付方式:首选去 ulua官网地址上面下载最新的 ulua &
然后后面的文章都会建立在 Unity3d 5.3.1 &#43; ulua1,24 &#43; UGUI的环境下,下载完了如果集成有问题请参考 我的中的第一条,环境搭建完了,ulua的结构这里不讲,自行去里面查看。
使用可以参考其他同学的这个文章,用以跑起来demo&
http://blog.csdn.net/adambieber/article/details/
这里主要说下自己遇到的问题,先创建一个c#类 随便去个名字,比如叫demo,然后敲入如下的代码
public class Demo : MonoBehaviour {
LuaScriptM
// Use this for initialization
void Start () {
mgr = new LuaScriptMgr();
mgr.Start();
string path = Util.LuaPath(&test.lua&);
mgr.DoFile(path);
}然后在工程目录下存放如下的test.lua文件,为何放在这里是有原因的~ 因为LuaScriptMgr.cs 这个脚本封装的lua路径就在这里,test里面的内容可以直接我在里面的即可
接着运行你会发现 unity 控制台会报错为如下的内容。
Loader lua file failed: F:/XProject_FrameWork/XProject_FrameWork/Assets/uLua/lua/test.lua&
由于是第一次使用所以我就参考了demo里面对file这个的使用,然后把我的脚本修改为如下的内容
void Start () {
mgr = new LuaScriptMgr();
mgr.Start();
string path = Util.LuaPath(&test.lua&);
mgr.DoFile(path);
//这样是ok 的
LuaState state = new LuaState ();
state.DoFile (path);
}的确这个时候并没有报错,完整的运行除了结果~~~
这个时候只能自己去调试了(有源码就是好啊,这个时候深深的再次感受到开源是多么的无私)
经过一系列的分析得出了如下的结论
所以以后如果使用LuaScriptMgr的dofile的话就直接传入文件名字即可,在此也可以想象作者其实是在做好事,帮助开发者更方便传入文件路径,只是第一次使用难免会遇到各种各样的问题,这里记录一下~~~以便有相识经历的同学少走弯路。在此感谢ulua的作者~~ 突然感觉我们的动态更新就在&#30524;前了~~
题外话:明天有同事离职了,好忧伤~~一个战壕的队友,一起撸过通宵,一起玩过dota~~再见朋友~~
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:5000次
排名:千里之外05:04:29 UTC
I want to use cpp to call lua function.And I find that cocos2dx 3.0 use the function ScriptHandlerMgr to do this.So in cpp,i write a class that extends Node,and it is singltone.The code is:
//function that call luavoid LoadManager::onEvent(){
if CC_ENABLE_SCRIPT_BINDING
if ( kScriptTypeNone != _scriptType)
BasicScriptData data(this,(void*)&loadingNum);
ScriptEvent scriptEvent(kCallFuncEvent, &data);
auto engine = ScriptEngineManager::getInstance()-&getScriptEngine();
engine-&sendEvent(&scriptEvent);
//ScriptEngineManager::getInstance()-&getScriptEngine()-&sendEvent(&event);
endif // #if CC_ENABLE_SCRIPT_BINDING
then I use tolua,and in lua,the code is:
local function LoadCallBack(loadNum)
currLoaded = currLoaded+1
LoadingLayer:StartLoad()end
local lm = cc.LoadManager:getInstance()ScriptHandlerMgr:getInstance():registerScriptHandler(lm,LoadCallBack,cc.Handler.CALLFUNC )
Almost the above is right,isn`t it?But when I run application,it broken
abnormal program termination...
what`s wrong?
01:42:02 UTC
Is im derived from ref?Can you paste the output of console?程序写累了,就来玩玩酷跑小游戏吧,嘿嘿。
雨松MOMO送你一首歌曲,嘿嘿。
CSLight研究院之学习笔记结合NGUI(一)
CSLight研究院之学习笔记结合NGUI(一)
围观9985次
编辑日期: 字体:
这两天一直在研究CSLight,目前Unity热更新的方式有两种,一种是ulua这个网上的例子已经很多了。还有一种就是CSLight。其实我更希望CSLight可以趋向成熟,因为它的语法就是C#,但是有些C#的标准语法用不了。这两天我学习的做了一个例子,也把我遇到的坑记录一下。
1.在github上下载CSLight,当我把DLL拖进项目的时候会报错。原因是CSLight的dll和NGUI的冲突了,所以我直接把他的core文件夹代码全部拷贝在我的工程里面。
2.脚本可以直接就创建成.cs文件,这样可以利用unity的语法提示。李总真是太聪明了哈哈。
3.脚本与类之间传递参数。。如下脚本所示,调用脚本UIMain中的Start()方法,并且将名子作为参数传递了进去。
12345678910111213
using UnityEngine;using System.Collections;using System.Collections.Generic;using System;&public class UICommon : MonoBehaviour {& void Start () {
ScriptMgr.Instance.LoadProject();
ScriptMgr.Instance.Execute("UIMain.Start(\""+name+"\");"); }}
ScriptMagr是李总封装的脚本管理类,是一个静态类。因为我们在脚本中可能会用到一些数据对象,需要提前注册一下,每次打开界面都去注册一下显然不太好。LoadProject()等于就是开游戏的时候注册一下,以后直接就去用。
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
using UnityEngine;using System.Collections;using System.Collections.Generic;using System;&&/// &summary&/// 这个类实现脚本的Logger接口,脚本编译时的信息会从Log输出出来/// &/summary&class ScriptLogger : CSLE.ICLS_Logger{&&&&&public void Log(string str)&&&&{&&&&&&&&UnityEngine.Debug.Log(str);&&&&}&&&&&public void Log_Error(string str)&&&&{&&&&&&&&Debug.LogError(str);&&&&}&&&&&public void Log_Warn(string str)&&&&{&&&&&&&&Debug.LogWarning(str);&&&&}}&public class ScriptMgr{&&&&/// &summary&&&&&/// ScriptMgr用单例模式,主要是为了提供C#Light Env的初始化&&&&/// &/summary&&&&&public static ScriptMgr Instance&&&&{&&&&&&&&get&&&&&&&&{&&&&&&&&&&&&if (g_this == null)&&&&&&&&&&&&&&&&g_this = new ScriptMgr();&&&&&&&&&&&&return g_this;&&&&&&&&&}&&&&}&&&&#region forInstance&&&&static ScriptMgr g_this;&&&&public CSLE.CLS_Environment env&&&&{&&&&&&&&get;&&&&&&&&private set;&&&&}&&&&private ScriptMgr()&&&&{&&&&&&&&env = new CSLE.CLS_Environment(new ScriptLogger());&&&&&&&&env.logger.Log("C#LightEvil Inited.Ver=" + env.version);&&&&&&&&&RegTypes();&&&&}&&&&#endregion&&&&&&/// &summary&&&&&/// 这里注册脚本有权访问的类型,大部分类型用RegHelper_Type提供即可&&&&/// &/summary&&&&&void RegTypes()&&&&{&&&&&&&&//大部分类型用RegHelper_Type提供即可&&&&&&&&env.RegType(new CSLE.RegHelper_Type(typeof(Vector2)));&&&&&&&&env.RegType(new CSLE.RegHelper_Type(typeof(Vector3)));&&&&&&&&env.RegType(new CSLE.RegHelper_Type(typeof(Vector4)));&&&&&&&&env.RegType(new CSLE.RegHelper_Type(typeof(Time)));&&&&&&&&&env.RegType(new CSLE.RegHelper_Type(typeof(Debug)));&&&&&&&&env.RegType(new CSLE.RegHelper_Type(typeof(GameObject)));&&&&&&&&env.RegType(new CSLE.RegHelper_Type(typeof(Component)));&&&&&&&&env.RegType(new CSLE.RegHelper_Type(typeof(UnityEngine.Object)));&&&&&&&&env.RegType(new CSLE.RegHelper_Type(typeof(Transform)));
env.RegType(new CSLE.RegHelper_Type(typeof(Resources)));&&&&&&&&&//对于AOT环境,比如IOS,get set不能用RegHelper直接提供,就用AOTExt里面提供的对应类替换&&&&&&&&env.RegType(new CSLE.RegHelper_Type(typeof(int[]), "int[]"));//数组要独立注册&&&&&&&&env.RegType(new CSLE.RegHelper_Type(typeof(List&int&), "List&int&"));//模板类要独立注册&&&&&&&&&&&//每一种回调类型要独立注册&&&&&&&&env.RegDeleType(new CSLE.RegHelper_DeleAction("Action")); //unity 用的dotnet 2.0 没有Action&&&&&&&&env.RegDeleType(new CSLE.RegHelper_DeleAction&int&("Action&int&")); ;
env.RegDeleType(new CSLE.RegHelper_DeleAction&GameObject&("Action&GameObject&")); ; &&&&&&&&&env.RegType(new CSLE.RegHelper_Type(typeof(Rect)));&&&&&&&&env.RegType(new CSLE.RegHelper_Type(typeof(PrimitiveType)));
env.RegType(new CSLE.RegHelper_Type(typeof(UICommonEvent)));&&
env.RegType(new CSLE.RegHelper_Type(typeof(UISprite)));&&&&}&&&&&public bool projectLoaded&&&&{&&&&&&&&get;&&&&&&&&private set;&&&&}&&&&public void LoadProject()&&&&{&&&&&&&&if (projectLoaded) return;&&&&&&&&try&&&&&&&&{&&&&&&&&&&&&string[] files = System.IO.Directory.GetFiles(Application.streamingAssetsPath, "*.cs", System.IO.SearchOption.AllDirectories);&&&&&&&&&&&&Dictionary&string, IList&CSLE.Token&& project = new Dictionary&string, IList&CSLE.Token&&();&&&&&&&&&&&&foreach (var v in files)&&&&&&&&&&&&{&&&&&&&&&&&&&&&&var tokens = env.tokenParser.Parse(System.IO.File.ReadAllText(v));&&&&&&&&&&&&&&&&project.Add(v, tokens);&&&&&&&&&&&&}&&&&&&&&&&&&env.Project_Compiler(project, true);&&&&&&&&&&&&projectLoaded = true;&&&&&&&&}&&&&&&&&catch (Exception err)&&&&&&&&{&&&&&&&&&&&&&Debug.LogError("编译脚本项目失败,请检查" + err.ToString());&&&&&&&&}&&&&}&&&&public void Execute(string code)&&&&{&&&&&&&&var content = env.CreateContent();&&&&&&&&&&try&&&&&&&&{&&&&&&&&&&&&var tokens = env.ParserToken(code);&&&&&&&&&&&&var expr = env.Expr_CompilerToken(tokens);&&&&&&&&&&&&expr.ComputeValue(content);&&&&&&&&}&&&&&&&&catch (Exception err)&&&&&&&&{&&&&&&&&&&&&var dumpv = content.DumpValue();&&&&&&&&&&&&var dumps = content.DumpStack(null);&&&&&&&&&&&&var dumpSys = err.ToString();&&&&&&&&&&&&Debug.LogError(dumpv + dumps + dumpSys);&&&&&&&&}&&&&}}
大家注意看RegTypes()里面的注册方法。把你的脚本中用到的类,可以是unity提供的类,可以是NGUI提供的类,也可以是你自己封装的类都在这里注册一下,只有注册了你的脚本里才能使用这些方法。
假如界面Prefab在Assetbundle里面热更新了,那么脚本也对应需要更新,比如之前的界面只有一个按钮,那么新更新一个界面有两个按钮了,那么需要给新增加的按钮加监听事件。先看看下面可以热更新的这条脚本。
123456789101112131415161718192021222324252627282930313233343536373839
using UnityEngine;using System.Collections;&public class UIMain&&{& static GameObject button ; //UICommon里面调用脚本的Start方法,并且传入了名子的字符串 static void Start (string root)
Transform rootUI = GameObject.Find(root).transform;
//在Resources下面读取资源或者 Assetbundle来读取,并且实例化在场景视图中。这一句操作我觉得也可以在Unity的脚本中完成
GameObject prefab&&= Resources.Load("UIMain") as GameObject;
GameObject gameObject = Object.Instantiate(prefab) as GameObject;
//放在UIPanel下面,让坐标在原点
gameObject.transform.parent = rootUI;
gameObject.transform.localPosition = Vector3.zero;
gameObject.transform.localScale = Vector3.one;&
Transform transform = gameObject.transform;
//找到UIPrefab下面的一个Sprite并且修改一下Sprite的名子。
UISprite sprite = transform.Find("Sprite").GetComponent("UISprite")as UISprite;
sprite.spriteName ="Glow";
sprite.transform.localPosition = new Vector3 (10,100,0);
sprite.MakePixelPerfect();&
//获取按钮对象,并且增加按钮的监听
button = transform.Find("Button").gameObject;
UICommonEvent.onClick +=Click;
UICommonEvent.AddOnClick(button); }
//当按钮点击的时候在脚本中得到回调 static void Click(GameObject go) {
if(go.name == button.name){
Debug.Log("雨松MOMO提示,您点击了这个按钮喔");
代码写完你会发现几乎和C#的脚本万全一样,但是有几个比较恶心的地方。
1.不支持范型。
热更新的这样的代码就不能直接使用了。
Resources.Load&GameObject&
gameObject.GetComponent&UISprite&
2.不支持typeof()关键字
3.不支持代理事件。
用NGUI做界面,可能里面用了大量的UIEventListener ,比如按钮、精灵的位移动画等等。这种东西如果硬要在脚本里面写太蛋疼了。我觉得最好还是把代理相关的东西拿出来。
还有就是做界面的时候可能会用到一些定时器,如果用代理来做的话也需要改改,总之向这种delegate回调的地方应该都要封装成方法,然后在回调进脚本里面。
在上面的代码中,我在处理按钮的点击事件的时候。如下代码所示,我写了一条Unity的脚本,在热更新的脚本里面,通过类名.就可以直接访问方法并且传递参数。UIEventListener监听到事件以后,在回调一下热更新脚本中的方法。
class UICommonEvent{ public static event Action&GameObject& onClick; static public void AddOnClick(GameObject button) {
UIEventListener.Get(button).onClick =delegate(GameObject go) {
onClick(go);
注:我也不是CSLight的高手,也是最近开始学。感谢作者给我了很大帮助,他的游戏项目中大量的使用CSLight。据说效率还可以,这两天我在好好测试一下它的效率,希望有经验的朋友可以分享一些。谢谢啦。
最后本文下载:
本文固定链接:
转载请注明:
雨松MOMO提醒您:亲,如果您觉得本文不错,快快将这篇文章分享出去吧 。另外请点击网站顶部彩色广告或者捐赠支持本站发展,谢谢!
作者:雨松MOMO
专注移动互联网,Unity3D游戏开发
如果您愿意花10块钱请我喝一杯咖啡的话,请用手机扫描二维码即可通过支付宝直接向我捐款哦。
您可能还会对这些文章感兴趣!

我要回帖

更多关于 lua gc是什么意思 的文章

 

随机推荐