原文:http://game.ceeger.com/forum/read.php?tid=16483&fid=16

看了坛子上同学用Kopilua,以为真的跨平台没问题,就实验了安卓手机,然后就开始铺游戏框架,干了一星期到昨晚想起来到ipad上跑跑,然后我跟我的小Demo一起崩溃了。今天搜索luajit,终于在u3d官方论坛终于发现了真正支持IOS+安卓(老外说web也支持,没测试)的插件,有些小兴奋,还是半信半疑的心态测试了下,果不其然运行在我的ipad2上面了,至少我运行代码非常正常。免费给大家上传我测试过的工程,有问题一起研究吧。补上:安卓也测试了游戏框架么问题,能正常使用的。今天在IOS上测试下更新的游戏框架了,问题不大。最近太忙了,没时间过来,为了方便技术交流,可以加群【Unity Lua技术交流QQ群】:341746602

针对大家的需求,我从当前游戏里剥离出一个迷你游戏框架,传送门: http://game.ceeger.com/forum/read.php?tid=18009&fid=16

感谢大家群策群力,ulua的使用越来越多。我以后会在帖子上贴一些同学们的经验思路,分享给大家。供借鉴。

“ topameng ”同学基于ulua开发的tolua c#版,co2dx同学懂得。极大提升ulua的效率的插件,懂的入,传送门: http://game.ceeger.com/forum/read.php?tid=18827&fid=16

“ topameng ”同学共享出来的ulua bug fix解决方案,大家不要错过,遇到了直接穿越吧,传送: http://game.ceeger.com/forum/read.php?tid=18451&fid=16

“chiuan” 同学再次共享的 Unity3D Lua中使用协程coroutine和计时器timer   传送门: http://game.ceeger.com/forum/read.php?tid=18475&fid=16

" weiyi8248 "同学深入ulua编译文章 uLua运行LuaJIT编译后的bytecode文件  传送门: http://game.ceeger.com/forum/read.php?tid=18464&fid=16

来自UnityLua群里“赵欣悦”同学无私奉献的热更新思路:我从最开始说下我的思路吧。通过版本号来判断是大更新还是小更新,游戏初始化的时候,先下载最新版本号和当前版本号比对。如果需要小更新,那么下载一个需要更新的表,通过表去下载各种资源和脚本的AssetsBundle。其中包括了一个数据文件,是当前版本中,会被lua托管的函数列表。然后以函数名作为key存在一个字典中,准确的说是 类名_函数名,这个也是我们所有lua脚本的文件名。在程序运行的时候,每个函数调用最开始判断一下这个函数是否存在于字典中。如果不存在,执行C#脚本。如果存在,判断字典中当前项的TextAsset是否为空,为空的话,从AB中加载,并DoString。如果不为空,直接DoString。这样就执行了更新上去的Lua脚本了,函数就return掉,不执行C#脚本了。新增的所有面板都用同一个C#脚本去管理,这个C#脚本只是lua的入口,可以通过管理器去赋值。

---------------------------------------------------------------------------------------------------------------------------------------------------- 
但是,发现一些地方需要注意下: 
(1)

 local button = child("buttonName").gameObject; UIEventListener.Get(button).onClick = OnClick; 

这个事件关联代码在iOS下是报错的,不能够正确执行(安卓没事),感谢lx1988cyk同学提示:“这个事件关联代码在iOS下是报错的,不能够正确执行(安卓没事)” ulua的README.txt里最后一段有说明。 所以,只要在CheckType.cs的第一行定义#define __NOGEN__,那么所有平台使用这种代码都会报错了。如果要发布ios平台的话,建议定义上去,方便日常开发。 
后发现坛子同学找到添加托管的方法,抄袭一下,希望不介意哈:uLua扩充对delegate的绑定支持 
参考nlua中的做法,只需要注册一个委托类型即可,作者将这部分代码合并入了ulua

c#: class LuaBoolDelegateEventArgsHandler : LuaInterface.LuaDelegate { bool CallFunction(GameObject go) { object[] args = new object[] { go }; object[] inArgs = new object[] { go }; int[] outArgs = new int[] { }; return (bool)base.callFunction(args, inArgs, outArgs); } }     public delegate bool BoolDelegate(GameObject go); public BoolDelegate OnStart; RegisterLuaDelegateType(typeof(CallbackTest.BoolDelegate), typeof(LuaBoolDelegateEventArgsHandler)); public static void RegisterLuaDelegateType(Type delegateType, Type luaDelegateType)  { m_LuaState.RegisterLuaDelegateType(delegateType, luaDelegateType); }
lua: local callbackTest = test:AddComponent("CallbackTest"); callbackTest.OnStart = function (gameObject) print("callback sucess!"); return gameObject.Name == name; end

但是我们通过Lua通知C#的添加方式,绕过了这个问题。PS:非常感谢chiuan同学的下述代码贡献!!!!解决了此问题。

public static void AddClick(GameObject go,object lua){ UIEventListener.Get(go).onClick += delegate(GameObject o){ LuaFunction func = (LuaFunction)lua; func.Call(); };
}

(2)刚才发现一个有关注释的问题,也一并记录下。Lua代码与注释不用同行,否则lua执行会出错,估计跟中文注释有关系。我们的做法是,最终打包之前把所有txt里面的单独行注释铲除掉,即可运行正常了。(如果你的lua代码有中文,打包之前千万删除掉,今天我们测试print里面也不能有中文) 
非常感谢cnlas同学搞定了中文编码的解决办法呢,非常棒!~,以下是解决方案(借花献佛啦):

Lua.cs Line159
if (LuaDLL.luaL_loadbuffer(L, chunk, chunk.Length, name) != 0)
改为
if (LuaDLL.luaL_loadbuffer(L, chunk, System.Text.Encoding.UTF8.GetByteCount (chunk), name) != 0) Line 225
if (LuaDLL.luaL_loadbuffer(L, chunk, chunk.Length, chunkName) == 0)
改为
if (LuaDLL.luaL_loadbuffer(L, chunk, System.Text.Encoding.UTF8.GetByteCount (chunk), chunkName) == 0) 

原因就是对于中文等双字节字符,string.Length的返回值是把一个汉字当一个计数的,这样底层的库去parser时候就等于没读完整啦~ 
这样一个简单的修改就可以让ulua支持中文了,在楼主给的包里修改出中文输入输出已测试通过。 至于其他的读取接口比如读文件啥的貌似直接都用的bytes.Length,理论上没有问题的。 当然,大前提是lua文件本身的编码要存成UTF8。

(3)看到大家很多人开始使用ulua,觉得自己辛苦没白费,当然ulua作者我也不认识,我就是想把新的插件介绍给大家使用,填补上u3d不能热更新的坑。希望大家把ulua还不是很好的地方跟想法报出来,有种贡献,将来你遇到问题了,别人才能也反过来帮你。lua里面是没有等待时间的,至少我比较笨,没有用lua的协同怎么实现等待时间,但是觉得应该可以。我就用lua通知c#等待一段时间后,再反过来调用lua协调的继续函数,来模拟。可能效率会不好,但是没别的想法,有办法的朋友贴上来,补在这后面也好。

(4)关于有些网友问有了unilua,为啥还需要这个?我在这里回答下,别问了哈。unilua是云风团队阿南的作品,想必云大神的技术必然不会差了,尤其在运行效率下,但是,关于怎么通过unilua调用附加在gameobject上的自定义c#脚步一直闹不明白,而且也跑到他们的开源地址问过了,阿南回答我说他也不清楚。有一个运行lua代码的入口的开发方式使用传统的开发模式应该可以,也就是说要全部用lua开发逻辑,目前我还没想到怎么弄,但是想必大家用ngui或者其他组件的人不少,比如我们的《Q灵三国》就是基于ngui开发的,假如修改一个uilabel的text的内容,就不知道怎么办了,即使你是用lua动态创建的文本框,你也改不了,除非你完全不用ngui,而是用u3d的gui来做。ulua解决了我这个难题,导入一下使用的自定义类(导入类之前先载入命名空间:luanet.load_assembly('Assembly-CSharp')才可以的),比如下面的demo类,或者导入一些ngui的组件类(uilabel或者uisprite等),就能让我能顺利的走下去。所以才用ulua来开发。

(5)kopilua跟ulua都是用的luainterface,所以基本上兼容,可是kopilua没有提供错误堆栈跟踪,导致我们的前端跟我抱怨查错很麻烦,对于一个开发的中大型项目来说很累,也经常混淆弄错的地方,ulua提供了错误堆栈跟踪,所以一出错就能看到在什么地方,出了什么问题,减轻了很多不必要的麻烦。

(6)有朋友问怎么用NGUI实现动态界面,这个属于公司技术细节,我不好说太详细,说个大概的思路吧,看大家自由发挥,我们的也未必就是最好的技术解决方案。我们也就是用的Assetbundle,把每个面板Prefab跟与其相对应的lua脚本都打包成一个Assetbudle(相对应的NGUI的Atlas跟材质、纹理都会被打包进去,记得使用关联素材,否则你的资源会重复,而且很大,浪费玩家流量跟内存),然后使用了《Q灵三国》的动态更新系统代码,把最新的面板资源下载到本地,从Assetbundle里面读取Prefab资源出来,然后上面附加一个公用的C#脚本,并且这个C#脚本会启动lua脚本,这样,每个面板都可以自动更新,附加在上面的lua脚本也能动态更新,即可实现对UI的控制。

(7)其实有个很简单的require的替代方案:把lua代码打包进Assetbundle里面的吧,那好,可以在面板的c#桥里面写个函数,就2行代码即可完成了,比如: 
void RequireLua(string name) { 
  TextAsset luaCode = bundle.Load(name, typeof(TextAsset)) as TextAsset; 
  lua.DoString(luaCode.text); 

每次Lua代码里面需要其他lua,RequireLua('lua2.lua'),然后就可以调用了。这样lua2.lua照样可以动态更新!

(8)感谢Unity Lua群里的“康”同学发现再补充的一个坑:最新发现luainterface还有个bug 
local v1=Vector3(1,1,1) 
local v2=Vector3(1,1,1) 
v1.x = 100 
print(v1.x, v2.x) 
你会发现v2.x也变成100了。原因是luainterface用dictionary存储的vector, 而dict是用的object.hashcode()

所有的c# object都是存储在dict里的,任何对象的hashcode一样,都可能导致obj是同一个,而Vector的hash实现刚好是用x,y,z的值来计算的

9)EntryPointNotFoundException: luaL_newstate是大家遇到最多的错误,这个错误我遇到过,但是有些忘记怎么过它的了,当时没记录下来,后面就没遇到。解决办法:把除了Assets跟ProjectSettings目录之外的都删除掉,重新打开工程。 
感谢isaachu同学找到问题所在:EntryPointNotFoundException: luaL_newstate这个错误是因为在如果在Unity中是设置了iPhone平台,但是uLua的代码没有排除Editor环境,DllImport错误造成的。

(10)一个是DLL没有找到的问题(DllNotFoundException: ulua),目前得到的结论是,真机没有打包libulua.so进包导致,或者模拟器也有些设置不对。打包的时候把libulua.so打包进libs\armeabi-v7a

(11)关于性能评测问题,很多朋友表达出担心,今天唠叨两句,本身lua就是解释型语言,效率不高,如果非要追求那种跟C++那样极致的编译效率是不现实的,只能靠开发者自己通过各种注意、技巧接近最高性能。就算是Flash Air以及cos2dx也不可能做到百分百的性能相等。那这种热更新(内更新)的代价与换来的运营上的价值,大家可以自己衡量一下的,还有如果过多担心效率问题的话,推荐核心算法可以放在C#里面完成,lua只做单纯单次调用,我觉得即使lua再慢,ulua再垃圾,单次调用c#的一个函数也不可能会慢到大家吃顿饭的时间吧,高强度循环的东东(各种Update)就不要放在lua里面了,这种可以避免很多不必要的性能忧虑,比如我们的Socket消息,有单个消息通知才会push给lua,这样不会慢到家的,放心!更详细的请参考chiuan同学帖子http://game.ceeger.com/forum/read.php?tid=16692&fid=2

(12)ulua只能适用于PRO版本,免费版没有办法访问原生码。还有就是尽量使用最新的U3D4.3以上+NGUI3.5+版本,最近在做《Q灵三国》的新版更新,计划把活动部分用ulua实现,我们U3D用4.1.2,NGUI用的是2.7,都是老版本的,好多问题,Sharder丢失、强类型Load素材等,因为项目很大,全部升级新版不太简单。新的游戏框架用的U3D4.3以上+NGUI3.5,所以开发起来非常的方便顺利。这个注意的地方,记录一下。

(13)上午完成了《Q灵三国》里面对ulua的限时活动移植工作,在2011年买的HTC G11(单核)手机上测试到现在,总体来说还行,但是的确没有原始版(C#)的流畅。尽量在游戏初始化的时候把所有的lua脚本都初始化好,然后放入一个公共的对象池,游戏进去以后就不要再产生DoString操作了,需要的时候从lua池里面获取早已初始化好的对象,否则性能比较差,体验很糟糕,这个希望大家注意下哈。【经过一天的优化,限时活动的面板弹出(包含Lua逻辑)已经很接近原始性能了,但是还是有些体验差异,不过真的跟ulua关系不大,主要是原来直接从Resource.Load出Prefab,这一次是从AssetBundle文件里载入,性能会有所不同,如果为了缩小更小的差距,可以提前预加载进游戏,但是要管理好内存占用,这是资源管理器的事情】

(13)我觉得哈,反射没有直接在lua里面声明性能来得好,LuaInterface使用的是反射机制,但是有部分反射机制IOS不认可,这也是有些是可以运行的。反射的性能不是最好的,我对cos2dx不是很懂,但是读过一少部分功能lua代码,他就是有些很常用的方法用lua重写了,如果非要用反射实际上是需要付出性能代价的,不是什么都尽量用反射,尽量lua内部能实现的就别用反射,大家慎用吧。

(14)真的是大家群策群力,坛子上的朋友借助ulua开发了flashx利用uLua转成u3d程序的功能,地址:http://www.flash-x.cn/?p=95 “4.运行unity3d模式可将AS项目轻松转换为u3d项目”从flash转过来的朋友需要学习的话,可以多多参考哈。欢迎更多的网友把自己的框架贴出来,汇总起来。目前很期待chiuan同学的quick-unity框架呢!!!

(15)最近很忙,终于有ulua功能的《Q灵》1.4.0版本提审了,有兴趣的可以试一下,目前有2个地方使用了ulua,一个是“活动”-》“限时活动”里面所有的面板程序都是ulua完成的,包括接收消息等,面板打包资源等。第二个地方没有具体的表现,当进入主场景的时候,ulua会得到一次执行机会,有可能新版活动提示啊,会做相应的提示信息。有问题告诉我一声哈。多谢!! 
苹果版:http://yun.baidu.com/s/1jGFpE8e     安卓版:http://yun.baidu.com/s/1sjz2rpF

示例网盘下载: http://pan.baidu.com/s/1pJAZm0z

uLua,一个Unity+Lua热更新解决方案!相关推荐

  1. uLua最新的Unity+Lua热更新解决方案!!!

    看了坛子上同学用Kopilua,以为真的跨平台没问题,就实验了安卓手机,然后就开始铺游戏框架,干了一星期到昨晚想起来到ipad上跑跑,然后我跟我的小Demo一起崩溃了.今天搜索luajit,终于在u3 ...

  2. 【Unity】uLua热更新解决方案

    jarjin 同学分享的lua热更新解决方案.大家可以试试,在下面回复交流遇到的问题. 原文:http://game.ceeger.com/forum/read.php?tid=16483&f ...

  3. [Unity3D学习]Unity代码热更新 源码下载

    转载自:http://blog.gamerisker.com/archives/608.html 之前的一篇文章<[Unity3D学习]Unity代码热更新解决方案测试结果总结>只是说了一 ...

  4. 【文集】Unity的热更新

    热更新对游戏很重要,但是unity自身是不支持热更新的,因此这方面还是有不少方案和文章 Unity热更新之LuaInterface(上篇) Unity热更新之LuaInterface(下篇) Lua ...

  5. unity python热更新_Unity热更新介绍和测试方法

    最近项目中增加了热更新了功能,程序也完成了相应的开发,接下来就需要对这个模块进行相应的测试工作了,在测试开始之前,了解下其原理总是很有好处的. 1:什么是热更新 简单的理解就是:用户重启客户端就能实现 ...

  6. Unity HybridCLR热更新技术实现

    最近我们在项目中遇到了一个问题:经常需要修改游戏逻辑,如果每次修改都需要重新打包发布,那将会非常耗时,于是我们开始寻找解决方案.最后我们找到了 Unity HybridCLR 热更新技术,实现了游戏逻 ...

  7. cocos2dx lua 热更新

    文章新地址 原理   每次登陆游戏利用cocos的assetManager从服务器拉去当前最新的两个文件. 一个是version.mainifest,一个project.mainifest. 这两个文 ...

  8. 【Unity】热更新插件【ULua】学习教程整理

    前言 IOS不能热更新,不是因为不能用反射,是因为 System.Reflection.Assembly.Load 无法使用 System.Reflection.Emit 无法使用 System.Co ...

  9. 用ECMAScript4 ( ActionScript3) 实现Unity的热更新 -- 使用原型链和EventTrigger

    原型链是JS的必备,作为ECMAScript4,原型链也是支持的. 特别说明,ActionScript3是支持完整的面向对象继承支持的,原型链只在某些非常特殊的情况下使用. 本文旨在介绍如何使用原型链 ...

最新文章

  1. 黄浴:基于深度学习的超分辨率图像技术发展轨迹一览
  2. BeanShell变量的基本范围
  3. [Share]Web Directions Conferences
  4. 解决thinkphp在开发环境下文件模块找不到的问题
  5. difftime(转)
  6. 用神经网络二分类人脑与电脑
  7. YII2操作mongodb笔记(转)
  8. 2 计算机网络性能指标
  9. CSO安全手册中的七条守则
  10. 计算机维修英语情景对话大全,快速英语情景对话大全 日常生活对话 7 排除电脑故障...
  11. 蔡俊锋 web API 开发规范
  12. intouch与PLC之间通讯状态监测和设置
  13. 达梦单机数据库服务器磁盘空间占满问题
  14. 中国高分辨率国家土壤信息格网基本属性数据集
  15. 浅谈互联网寒冬Android进阶之路
  16. webshell检测方式深度剖析---RASP(taint扩展)
  17. 网络攻防技术-Lab5-shellcode编写实验(SEED Labs – Shellcode Development Lab)
  18. 信息收集——Google Hacking
  19. Eclipse中怎样将java项目转化为web项目?
  20. 看过1000份算法简历,才明白人工智能、机器学习、深度学习!!!

热门文章

  1. 【咕泡P5人工智能CV 技术NLP项目实战】
  2. 微信小程序入门开发超详细笔记(一)
  3. Linux 硬盘分区、格式化、挂载
  4. linux pcm接口调试,Linux的alsa接口播放pcm音频数据
  5. Exception in thread “main“ org.apache.ibatis.binding.BindingException: Type interface com.neusoft.Id
  6. 一口气读懂什么是房地产CRM
  7. 盘点2019:中国科技成果惊艳世界
  8. 2022年上半年,大批互联网公司撑不住了
  9. 把arm开发板做成USB网卡(RNDIS /Ethernet Gadget)
  10. simulink微电网一次调频风机储能下垂控制