Unity3d 中使用Lua之UniLua
来源:互联网 发布:美国eia原油库存数据 编辑:程序博客网 时间:2024/05/16 02:55
Unity3d 中使用Lua之UniLua
方便动态更新游戏用。
开源项目地址:https://github.com/xebecnan/UniLua
最新支持到Lua5.2,C#版的Lua
基础用法:
大部分的使用是可以参考标准的 Lua 官方文档和 Lua 教程的。 Lua 本身的语法是一样的。C API 和 C# API 之间有个对应关系。例如 lua_pushnumber() 这个 C API 对应到 UniLua 里就是 lua.PushNumber()
所有标准 lua 中 lua.h 和 lauxlib.h 里定义的接口,都对应 LuaAPI.cs 里定义的 ILuaAPI 和 LuaAuxLib.cs 里定义的 ILuaAuxLib 接口。
从 C# 调用 Lua
最朴素的从 C# 调用 lua 的一个全局函数的写法:
Lua.GetGlobal( "foo" ); // 加载 lua 中定义的一个名叫 foo 的全局函数到堆栈Debug.Assert( Lua.IsFunction(-1) ); // 确保加载成功了, 此时栈顶是函数 fooLua.PushString( "test" ); // 将第一个参数(字符串 "test")入栈Lua.PushInteger( 42 ); //将第二个参数(整数 42)入栈Lua.Call(2, 0); // 调用函数 foo, 指明有2个参数,没有返回值// 上面的代码相当于 lua 里一个这样的调用 foo("test", 42)
稍微复杂一点的例子可以参考实例程序里的一些简单写法:参考这个文件 Assets/Behaviour/LuaScriptController.cs:
- Assets/Behaviour/LuaScriptController.cs
- framework/main.lua
// 创建 Lua 虚拟机var Lua = LuaAPI.NewState();// 加载基本库Lua.L_OpenLibs();// 加载 Lua 脚本文件var LuaScriptFile = "framework/main.lua";var status = Lua.L_DoFile( LuaScriptFile );// 捕获错误if( status != ThreadStatus.LUA_OK ){ throw new Exception( Lua.ToString(-1) );}// 确保 framework/main.lua 执行结果是一个 Lua Tableif( ! Lua.IsTable(-1) ){ throw new Exception( "framework main's return value is not a table" );}// 从 framework/main.lua 返回的 table 中读取 awake 字段指向的函数// 并保存到 AwakeRef 中 (可以将 AwakeRef 视为这个函数的句柄)var AwakeRef = StoreMethod( "awake" );// 不再需要 framework/main.lua 返回的 table 了,将其从栈上弹出Lua.Pop(1);//----------------------------------------------------// 在需要的时候可以这样调用 AwakeRef 指向的 lua 函数CallMethod( AwakeRef );//----------------------------------------------------// StoreMethod 和 CallMethod 的实现private int StoreMethod( string name ){ Lua.GetField( -1, name ); if( !Lua.IsFunction( -1 ) ) { throw new Exception( string.Format( "method {0} not found!", name ) ); } return Lua.L_Ref( LuaDef.LUA_REGISTRYINDEX );}private void CallMethod( int funcRef ){ Lua.RawGetI( LuaDef.LUA_REGISTRYINDEX, funcRef ); var status = Lua.PCall( 0, 0, 0 ); if( status != ThreadStatus.LUA_OK ) { Debug.LogError( Lua.ToString(-1) ); }}
从 Lua 调用 C# 函数 ( 使用 C# 来扩展 Lua 功能 )
目前的示例程序是使用 FFI 库来实现的 从 Lua 调用 C# 函数。 FFI 因为用到了反射机制来调用 C# 函数,性能会比较低。应该尽量避免使用,如果没有找到更好的办法,准备之后把这个FFI实现废弃掉。其实直接用 C# 实现一个库的形式,来让 lua 调用这种传统的做法效率会比较高,也是推荐采用的方式。而且也并不会麻烦太多。
比如我现在要实现一个叫 libfoo 的库, 里面提供两个方法: add(a, b) 和 sub(a, b)
库的实现
using UniLua;public static class LibFoo{ public const string LIB_NAME = "libfoo.cs"; // 库的名称, 可以是任意字符串 public static int OpenLib(ILuaState lua) // 库的初始化函数 { var define = new NameFuncPair[] { new NameFuncPair("add", Add), new NameFuncPair("sub", Sub), }; lua.L_NewLib(define); return 1; } public static int Add(ILuaState lua) { var a = lua.L_CheckNumber( 1 ); // 第一个参数 var b = lua.L_CheckNumber( 2 ); // 第二个参数 var c = a + b; // 执行加法操作 lua.PushNumber( c ); // 将返回值入栈 return 1; // 有一个返回值 } public static int Sub(ILuaState lua) { var a = lua.L_CheckNumber( 1 ); // 第一个参数 var b = lua.L_CheckNumber( 2 ); // 第二个参数 var c = a - b; // 执行减法操作 lua.PushNumber( c ); // 将返回值入栈 return 1; // 有一个返回值 }}
库的初始化
// 创建 Lua 虚拟机var Lua = LuaAPI.NewState();// 加载基本库Lua.L_OpenLibs();Lua.L_RequireF( LibFoo.LIB_NAME // 库的名字 , LibFoo.OpenLib // 库的初始化函数 , false // 不默认放到全局命名空间 (在需要的地方用require获取) );
库的使用 (在 lua 代码中)
// 获取库local libfoo = require "libfoo.cs"// 调用库的方法print(libfoo.add(42, 1))print(libfoo.sub(42, 22))
UTF-8 support
C# 采用 UTF-16 作为字符串的内部编码,而 Lua 本身没有实现比较完善的编码支持。为了处理这个问题,我实现了一个简单的编码库 enc lib。使用方法如下:
-- Assuming your source code is in utf-8.-- convert from utf-8:local utf8_str = '测试字符串'local print_safe_str = enc.decode(utf8_str, 'utf8')print(print_safe_str)-- convert to utf-8:local original_str = enc.encode(print_safe_str, 'utf8')assert(utf8_str == original_str)更多资料:http://dong2008hong.blog.163.com
- Unity3d 中使用Lua之UniLua
- [Unity3D]Unity3D游戏开发之Lua与游戏的不解之缘终结篇:UniLua热更新完全解读
- Unity3d中使用Lua
- Unity3D UniLua的示例
- Unity3D C#调用UniLua
- Unity3D UniLua调用C#
- [Unity3D]Lua中使用协程coroutine和计时器timer
- [Unity3D]Lua中使用协程coroutine和计时器timer
- 在Unity3D里面使用Lua
- [Unity3D]Unity3D游戏开发之Lua与游戏的不解之缘(中)
- [Unity3D]Unity3D游戏开发之Lua与游戏的不解之缘(中)
- unity3d 之 在Unity3D中使用静态变量
- lua语言(四)之Unity3D实践
- Unity3D游戏开发之Lua与游戏的不解之缘(转载中)
- Lua之Sprite使用
- Lua中使用List
- Unity3D之FingerGestures使用
- Lua中使用C函数之简化版
- 【C#】重写和重载的区别
- 云智慧CEO殷晋:APM市场发展空间广阔
- PostgreSQL 对简单树的遍历
- Java内存分析
- CodeForces - 148D Bag of mice(概率dp)
- Unity3d 中使用Lua之UniLua
- C# 实现文件关联
- Java内存分配
- 紫光软件推云平台档案管理 逐鹿大数据时代
- vmware10上三台虚拟机的Hadoop2.2.0集群搭建
- HighChart操作
- 服务器证书安装配置指南(IIS7.5)
- 小镇故事:以云计算之名
- 【ZZ】神与学霸的区别