前言:为什么要用Lua

首先要说,所有编程语言里面,我最喜欢的还是C#,VisualStudio+C#,只能说太舒服了。所以说,为什么非要在unity里面用Lua呢?可能主要是闲的蛋疼。。。。。另外还有一些次要原因:

方便做功能的热更新;

Lua语言的深度和广度都不大,易学易用,可以降低项目成本。

C#与Lua互相调用的方案

坦白来将,我并没有对现在C#与Lua互相调用的所有库进行一个仔细的调研,大概搜了一下,找到这样几个:

slua:https://github.com/pangweiwei/slua

Nlua:http://nlua.org/

UniLua:https://github.com/xebecnan/UniLua

uLua插件

以上这些方案的具体内容,不是本文的重点,这里就不说了,感兴趣的同学,点开自己去看就行了。

最后我选用了uLua,主要原因是:uLua方案比较成熟,它并没有太多自己的代码,主要是把LuaInterface和Lua解释器整合了一下,都是比较成熟的代码,相对会稳定一些。另外,个人很欣赏LuaInterface这个库。接下来我们就看一下uLua。:)

uLua插件的使用非常简单,基本上看一下他自带的几个例子就明白了。

游戏逻辑粘合层设计

uLua插件解决了语言层面的问题:C#与LUA两种语言代码互相调用,以及参数传递等相关的一系列底层问题。而我们游戏逻辑开发中,到底如何使用LUA是上层的一个问题。下面给出我摸索的一个方案,个人认为:够简单,够清晰,是很薄很薄的一层,不可能更薄了。

使用几个LuaState?

曾经看过一个网友的方案,每次运行脚本就new一个LuaState,个人认为这种方案十分不妥。整个游戏的Lua代码应该运行在一个LuaState之上,原因有二:

运行在同一LuaState的Lua代码才能互相调用啊。相信一个游戏总会有一定的代码量的,如果不同的lua文件之中的代码,完全独立运行,不能互相调用或者互相调用很麻烦,则游戏逻辑组织平添很多障碍;

混合语言编程中原则之一就是:尽量减少代码执行的语言环境切换,因为这个的代价往往比代码字面上看上去要高很多。我的目标是:既然用了Lua,就尽量把UI事件响应等游戏上层逻辑放到Lua代码中编写。

基于以上原因,我觉得游戏的Lua代码全都跑在一个LuaState之上。这也是本文方案的基础。

实现LuaComponent

首先说一下我的目标:

既然C#对于Unity来说是脚本层了,那么Lua应该和C#脚本代码具有相同的逻辑地位;

Lua整合的代码应该很少,应尽量保持简单;

基于以上的目标,我实现了LuaComponet类,它的实现类似MonoBehavior,只不过我们没有C++源代码,只能由C#层的MonoBehavior来转发一下调用。这样,我们的Lua代码的实现方式就是写和写一个C#脚本组件完全一致了,可以说达到了和引擎天衣无缝的整合。:)OK,先上代码!

usingUnityEngine;usingSystem.Collections;usingLuaInterface;///

///Lua组件 - 它调用的Lua脚本可以实现类似MonoBehaviour派生类的功能///

[AddComponentMenu("Lua/LuaComponent")]public classLuaComponent : MonoBehaviour

{private static LuaState s_luaState; //全局的Lua虚拟机

[Tooltip("绑定的LUA脚本路径")]publicTextAsset m_luaScript;publicLuaTable LuaModule

{get;private set;

}

LuaFunction m_luaUpdate;//Lua实现的Update函数,可能为null

///

///找到游戏对象上绑定的LUA组件(Module对象)///

public staticLuaTable GetLuaComponent(GameObject go)

{

LuaComponent luaComp= go.GetComponent();if (luaComp == null)return null;returnluaComp.LuaModule;

}///

///向一个GameObject添加一个LUA组件///

public staticLuaTable AddLuaComponent(GameObject go, TextAsset luaFile)

{

LuaComponent luaComp= go.AddComponent();

luaComp.Initilize(luaFile);//手动调用脚本运行,以取得LuaTable返回值

returnluaComp.LuaModule;

}///

///提供给外部手动执行LUA脚本的接口///

public voidInitilize(TextAsset luaFile)

{

m_luaScript=luaFile;

RunLuaFile(luaFile);//-- 取得常用的函数回调

if (this.LuaModule != null)

{

m_luaUpdate= this.LuaModule["Update"] asLuaFunction;

}

}///

///调用Lua虚拟机,执行一个脚本文件///

voidRunLuaFile(TextAsset luaFile)

{if (luaFile == null || string.IsNullOrEmpty(luaFile.text))return;if (s_luaState == null)

s_luaState= newLuaState();object[] luaRet = s_luaState.DoString(luaFile.text, luaFile.name, null);if (luaRet != null && luaRet.Length >= 1)

{//约定:第一个返回的Table对象作为Lua模块

this.LuaModule = luaRet[0] asLuaTable;

}else{

Debug.LogError("Lua脚本没有返回Table对象:" +luaFile.name);

}

}//MonoBehaviour callback

voidAwake()

{

RunLuaFile(m_luaScript);

CallLuaFunction("Awake", this.LuaModule, this.gameObject);

}//MonoBehaviour callback

voidStart()

{

CallLuaFunction("Start", this.LuaModule, this.gameObject);

}//MonoBehaviour callback

voidUpdate()

{if (m_luaUpdate != null)

m_luaUpdate.Call(this.LuaModule, this.gameObject);

}///

///调用一个Lua组件中的函数///

void CallLuaFunction(string funcName, params object[] args)

{if (this.LuaModule == null)return;

LuaFunction func= this.LuaModule[funcName] asLuaFunction;if (func != null)

func.Call(args);

}

}

这段代码非常简单,实现以下几个功能点:

管理一个全局的LuaState;

负责将MonoBehavior的调用转发到相应的LUA函数;

提供了GetComponent()、AddComponent()对应的LUA脚本版本接口;这点非常重要。

LUA代码约定

为了很好的和LuaComponent协作,Lua脚本需要遵循一些约定:

LUA脚本应该返回一个Table,可以是LUA的Module,也可以是任何的Table对象;

返回的Table对象应该含有MonoBehaviour相应的回调函数;

例如:

[AppleScript] 纯文本查看 复制代码

LuaComponent回调函数中,主动将GameObject对象作为参数传递给Lua层,以方便其进行相应的处理。

Lua组件之间的互相调用(在Lua代码中)

基于以上结构,就很容易实现Lua组件之间的互相调用。在Demo工程中,有一个“Sphere”对象,绑定了如下脚本:

[AppleScript] 纯文本查看 复制代码

还有另外一个“Cube”对象,绑定了如下脚本,用来演示调用上面这个Lua组件的成员:

[AppleScript] 纯文本查看 复制代码

最后,顺带总结一下:在设计上次游戏逻辑框架时,比较好的思路是:在透彻的理解Unity自身架构的前提下,在其架构下进行下一层设计,而不是想一种新的框架。因为Unity本身就是一个框架。更多内容请参见作者博客:http://blog.csdn.net/neil3d/article/details/44200821

lua按钮unity_在Unity中使用Lua脚本相关推荐

  1. Unity中的MonoBehaviour脚本-基础知识和继承关系

    本文分享Unity中的MonoBehaviour脚本-基础知识和继承关系 作为一个程序员, 在Unity中开发, 我们接触最多的对象之里一定有MonoBehaviour, 所以作为Unity基础知识学 ...

  2. linux系统无root权限lua库安装,liunx系统中安装lua以及torch

    一直在用pytorch,最近在做项目的时候,遇到了torch的开源代码,所以又开始不得不接触torch以及他所依赖的环境lua. liunx下lua环境的配置代码如下: ''' curl -R -O ...

  3. 蒙皮骨骼动画 unity_在Unity中沿航路点设置蒙皮网格动画

    蒙皮骨骼动画 unity This post is a guide to importing a skinned mesh with a looping animation and then anim ...

  4. 【Unity】6.1 Unity中的C#脚本基础知识

    分类:Unity.C#.VS2015 创建日期:2016-04-16 一.简介 1.常用的C#数据类型 这里简单介绍用Unity开发游戏时,最常用的一些数据类型. (1)基本类型 int.float. ...

  5. image加载图片 ui unity_关于Unity中UI中的Image节点以及它的Image组件

    一.图片的Inspector面板属性 Texture Type:一般是选择sprite(2D and UI) Sprite Mode:一般是选择Single Packing Tag:打包的标志值,最后 ...

  6. ui动效 unity_基于Unity中的NGUI插件,通用的UI如何设计?

    整理自知乎,文/王致远 以我的项目经历来说,要保证通用性必须分清需求是框架需要还是项目需要.举一个例子,所有的项目都需要一个弹窗提示的接口,但是不同项目弹窗都不一样,当时做的时候我没有想好怎么分离,那 ...

  7. 批量清理Unity中missing的脚本.

    工具git地址 这个小工具是我为了帮助开源项目金庸群侠传3D重制版 写得, 主要用处是批量查找丢失引用关系的脚本, 并且删除, 支持多选文件以及处理整个工程.

  8. Unity中如何用脚本调用动画(Animation)

    public class Cube : MonoBehaviour {private Animation animation;// Use this for initializationvoid St ...

  9. Unity协程实现分析以及Lua协程与Unity协程的混合使用

    1,节选翻译一篇stackoverflow关于Unity协程实现的讨论 - The big clues are in the C# version. Firstly, note that the re ...

最新文章

  1. 前端新手学习记录2 -使用vscode编写个人网站首页
  2. linux lua ide,mac os上开发lua用什么ide
  3. DNS域名服务器双master+ntp时间服务器双主+keepalived企业高可用方案 附脚本
  4. window7环境下安装neo4j server版本踩坑记录
  5. 九、“行胜于言车胜马,负重致远向前途”
  6. python中messagebox用法实例_pyqt4教程之messagebox使用示例分享
  7. 最长回文子串—leetcode5
  8. 使用miniSIPServer搭建pjsip服务器
  9. 在Completablefuture和Observable之间转换
  10. matlab中的方波信号图片_基于Matlab的雷达信号处理仿真
  11. LB负载均衡集群--LVS
  12. 大班科学计算机的发明应用教案,大班科学教案:机器人探密
  13. hssfcell判断文本类型_ICML 2020 | 显式引入对分类标签的描述,如何提高文本分类的效果?...
  14. linux下Makefile学习--注释很好
  15. 生意倒闭的老板基本死于这两个思维
  16. mysql间隙锁触发条件,详解系列文章
  17. percona 5.7.11root初始密码设置
  18. respond是空的_httpClient 获取response 中的 content 为空的原因(急求)
  19. python3 collections模块_python的Collections 模块
  20. eBay SOA开源平台

热门文章

  1. sp_getapplock_sp_getapplock和sp_releaseapplock存储过程概述
  2. centos /bin /sbin /usr/bin /usr/sbin 目录的说明
  3. BZOJ2654 Tree
  4. CAD制图系列之中心线画法
  5. 在使用静态构造函数的时候应该注意几点
  6. 关于tomcat和jetty的乱码问题
  7. Knockout获取数组元素索引的2种方法,在MVC中实现
  8. Cannot subclass final class class com.sun.proxy.$Proxy16
  9. 第13届景驰-埃森哲杯广东工业大学ACM程序设计大赛--K-密码
  10. JS事件冒泡和事件捕获