Xlua:腾讯研发,开源免费
 
配置:文件解压,拷贝到Unity项目里
注意:Xlua文件夹不许移动,不许重命名
 
运行Xlua:
1、引用命名空间
2、创建虚拟机
3、运行lua语句
4、不需要时,释放虚拟机(LuaEnv:Lua的虚拟机)
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using XLua;//1、引用Xlua的命名空间
public class HelloWorld : MonoBehaviour
{
//lua的语句
private string lua = @"print('Hello World') return 1, 'nihao', true";
//2、创建一个运行lua语句的lua虚拟机
private LuaEnv luaEnv = new LuaEnv(); void Start()
{
//4、运行lua的语句
//这个方法的参数就是lua的语句,返回值就是运行lua,lua里的最终的返回内容
object[] obj_arr = luaEnv.DoString(lua);
foreach (var item in obj_arr)
{
Debug.Log(item);
}
} private void OnDestroy()
{
//3、不需要虚拟机的时候,需要把虚拟机释放掉
luaEnv.Dispose();
}
}
 
C#调用Lua的文件:
1、Lua文件的后缀必须是.lua.txt的,file.lua.txt
2、Lua文件必须放在Resources文件夹下,不可以是子文件夹,默认加载器的原因
3、Lua文件的默认编码格式必须是UTF-8的。
4、使用Lua的关键字require调用,不需要写文件后缀,只需要写文件名
----例如:file.lua.txt; require 'file'
5、对于文件的返回值,需要写成 return require 'file'才能获得

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using XLua;
public class LuaByFile : MonoBehaviour
{
private string lua = @"require 'LuaByFile'";
//private string lua = @"a = require 'LuaByFile' retrun a"; //private string lua = @"retrun require 'LuaByFile'";
private LuaEnv luaEnv = new LuaEnv(); void Start()
{
object[] obj_arr = luaEnv.DoString(lua);
} private void OnDestroy()
{
luaEnv.Dispose();
}
}
 
自定义的加载器:能执行我们想要执行的指定文件夹下的Lua文件
自定义的加载器的参数:require传入的文件名
自定义的加载器的返回值:要执行的Luad的语句转换成的字节数组(UTF-8转换),如果返回null。证明未找到文件。
一个lua虚拟机能添加无数个自定义加载器,从第一个加载器中开始找,如果找到了(未返回null),那么就不执行之后的其他的加载器,如果所有的自定义的加载器都未找到,执行默认的加载器,从Resources文件夹中寻找文件,如果默认的也未找到,直接报错。
 
.lua.txt文件打成AB包

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using XLua;
using System.IO;
using System.Text;
public class CustomeLoader : MonoBehaviour { private LuaEnv luaEnv = new LuaEnv();
//该文件不在Resources下,默认加载器加载不到
private string lua = @"require 'CustomeLoader2'"; void Start () {
//添加一个自定义的加载器
luaEnv.AddLoader(CustomeLoader1);
luaEnv.AddLoader(CustomeLoader2);
luaEnv.DoString(lua);
} private void OnDestroy()
{
luaEnv.Dispose();
} /// <summary>
/// 自定义的加载器
/// </summary>
/// <param name="filePath">参数是require后的那个文件名字</param>
/// <returns></returns>
/// 返回值就是要执行的lua的转换之后的字节数组,如果返回值是null证明我们未找到该lua文件
byte[] CustomeLoader1(ref string filePath)
{
//filePath:参数是require后的那个文件名字
//byte[] bytes = System.Text.Encoding.UTF8.GetBytes("print('hello world')");
//文件所在的绝对路径
string path = Application.streamingAssetsPath + "/Lua/" + filePath + ".lua.txt";
if (!File.Exists(path))
{
return null;//如果不存在该文件,直接返回null
}
StreamReader sr = new StreamReader(path, System.Text.Encoding.UTF8);
string lua = "";
try
{
lua = sr.ReadToEnd();
}
catch (System.Exception)
{
throw;
}
sr.Close();
if (lua == "")//如果读取内容为空串,那么返回null,证明未找到该文件
{
return null;
}
else
{
byte[] bytes = System.Text.Encoding.UTF8.GetBytes(lua);
return bytes;
}
} /// <summary>
/// 从ab包中加载lua文件
/// </summary>
/// <param name="filePath"></param>
/// <returns></returns>
byte[] CustomeLoader2(ref string filePath)
{
//加载AB包
AssetBundle ab = AssetBundle.LoadFromFile(Application.streamingAssetsPath + "/AB/lua");
//从ab包中加载所需要的lua文件
TextAsset lua = ab.LoadAsset<TextAsset>(filePath + ".lua");
if (lua != null)
{
return lua.bytes;
}
return null;
}
}
 
C#访问Lua文件里的变量和方法:
 
C#访问Lua的全局变量
虚拟机执行一个lua语句之后,lua里的全局的变量或方法,
都存放在luaEnv.Global中,从Global中获取这些全的变量或方法。
 
CSharpCallLuaVariate.lua.txt
print('开始执行Variate.lua')
a =
b = 1.2
c = true
d = '小明'
print('开始执行Variate.lua')
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using XLua;
public class CSharpCallLuaVariate : MonoBehaviour { private LuaEnv luaEnv = new LuaEnv(); void Start () {
luaEnv.DoString("require 'CSharpCallLuaVariate'");
//虚拟机执行一个lua语句之后,lua里的全局的变量或方法
//都存放在luaEnv.Global中,从Global中获取这些全的变量或方法
//泛型是要接收的变量类型,参数是lua里的变量名字
//返回值就是变量的值
//int
int a = luaEnv.Global.Get<int>("a");
Debug.Log("a: " + a);
//float
float b = luaEnv.Global.Get<float>("b");
Debug.Log("b: " + b);
//bool
bool c = luaEnv.Global.Get<bool>("c");
Debug.Log("c: " + c);
//string
string d = luaEnv.Global.Get<string>("d");
Debug.Log("d: " + d);
} private void OnDestroy()
{
luaEnv.Dispose();
}
}
 
C#访问全局的table
1、映射到类或结构体中(值拷贝过程)
只能把table中的键值对映射到类中的公共变量,并且变量名与键名一致。
对于类中如果变量多于table的键值对,table键值对多余类中变量,都没有任何的影响
 
2、使用接口映射
不光能映射基本类型,还能映射table中的方法。
Table中的键与接口中的属性名或方法名对应上。
 
3、使用字典或list映射
List映射:只能映射索引的数字且连续的,并且只能映射值与list指定了类型一致的元素。
字典映射:当指定了字典的键类型和值类型之后,table中键与字典的键的类型一致,且键对应的值的类型与字典中值类型一致的也会映射过来。
 
4、使用XLua提供的LuaTable来映射
 
CSharpCallLuaTable.lua.txt
print('开始执行CSharpCallLuaTable.lua')
t1 = {, , , "小明", "nihao"}
t1.f1 = "name"
t1.f2 = true
t1.id =
t1[] =
t1[] =
t1.func1 = function()
print("func1")
end
print('开始执行CSharpCallLuaTable.lua')
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using XLua;
public class CSharpCallLuaTable : MonoBehaviour { private LuaEnv luaEnv = new LuaEnv(); void Start()
{
luaEnv.DoString("require 'CSharpCallLuaTable'"); //1、使用class或struct去映射table(值拷贝过程)
T1 t1 = luaEnv.Global.Get<T1>("t1");
t1.Print(); //2、可以使用接口去映射(引用拷贝过程)
IT1 it1 = luaEnv.Global.Get<IT1>("t1");
Debug.Log("it1:f1: " + it1.f1 + ",f2: " + it1.f2 + ",id: " + it1.id);
it1.func1(); //3、映射到字典或List中(值拷贝过程)
List<object> list = luaEnv.Global.Get<List<object>>("t1");
foreach (var item in list)
{
Debug.Log("list: " + item);
}
Dictionary<string, object> dic = luaEnv.Global.Get<Dictionary<string, object>>("t1");
foreach (KeyValuePair<string, object> item in dic)
{
Debug.Log("键: " + item.Key + "值: " + item.Value);
} //4、使用XLua提供的LuaTable来映射
LuaTable lt = luaEnv.Global.Get<LuaTable>("t1");
//对于table中字符串作为键的键值对
string f1 = lt.Get<string>("f1");
Debug.Log("f1: " + f1);
//对于table中的数字类型的索引的键值对,在取的时候需要指定键的类型和值的类型
string a = lt.Get<int, string>();
Debug.Log("第四个索引: " + a);
}
private void OnDestroy()
{
luaEnv.Dispose();
}
public class T1
{
public string f1;
public bool f2;
public int id;
public void Print()
{
Debug.Log("f1: " + f1 + ",f2: " + f2 + ",id: " + id);
}
}
[CSharpCallLua]//需要添加此特性
public interface IT1//接口里不能有变量,可以用变量
{
string f1 { get; set; }
bool f2 { get; set; }
int id { get; set; }
void func1();
}
}
 
C#映射全局的方法
1、使用委托映射
Lua中多返回值的情况:如果C#的委托有返回值,那么lua的函数的第一个返回值就是委托的返回值,第二个返回值之后依次对应委托里的out或ref参数传出。
如果C#的委托是无返回值的,那么lua函数从第一个返回值开始,依次对应委托的out或ref参数传出。
2、使用LuaFunction映射
 
CSharpCallLuaFunction.lua.txt
print('开始执行CSharpCallLuaFunction.lua')

--无参无返回值
func1 = function()
print("无参无返回值:func1")
end --有参无返回值
func2 = function(a, b)
print("有参无返回值:func2:", a, b)
end --无参有返回值
func3 = function()
print("无参有返回值:func3")
return
end --有参有返回值
func4 = function(a, b)
print("有参有返回值:func4:", a, b)
return true
end --无参多返回值
func5 = function()
print("无参多返回值:func5:")
return true, false, , "小明"
end --有参多返回值
func6 = function(a, b)
print("有参多返回值:func6:", a, b)
return true, false, , "小明"
end print('开始执行CSharpCallLuaFunction.lua')
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using XLua;
public class CSharpCallLuaFunction : MonoBehaviour {
private LuaEnv luaEnv = new LuaEnv();
//映射无参无返回值
[CSharpCallLua]//加特性自动适配,不用再去做映射,效率高
private delegate void Func1();
//映射有参无返回值 参数可以是任意类型
[CSharpCallLua]
private delegate void Func2(string a, int b);
//无参有返回值 最好委托返回值类型与lua中方法的返回值相对应
[CSharpCallLua]
private delegate int Func3();
[CSharpCallLua]
private delegate void Func4();
//无参多返回值
[CSharpCallLua]
private delegate bool Func5(out bool outOne, ref int outTwo, out string outThree);
//有参多返回值
[CSharpCallLua]
private delegate bool Func6(int a, out bool outOne, int b);
// Use this for initialization
void Start () {
luaEnv.DoString("require'CSharpCallLuaFunction'");
//全局的方法依旧存储在 Global中
//1. 全局方法映射到委托
Func1 func1 = luaEnv.Global.Get<Func1>("func1");
func1();
// 对于Lua中任意的方法,C#任意的一个委托类型都能映射过来,
// 只是对于返回值和参数的情况会忽略处理
// 最好使用相对应的委托去映射
//Del func2 = luaenv.Global.Get<Del>("func6");
// func2();
Func2 func2 = luaEnv.Global.Get<Func2>("func2");
func2("小明", );
Func3 func3 = luaEnv.Global.Get<Func3>("func3");
Debug.Log("func3的返回值" + func3());
Func5 func5 = luaEnv.Global.Get<Func5>("func5");
bool outOne = false;
int outTwo = ;
string outThree ="";
bool rt = func5(out outOne, ref outTwo, out outThree);
Debug.Log("func5:第1个返回值:" + rt + "第2个返回值:" + outOne + "第3个返回值:" + outTwo + "第4个返回值:" + outThree);
Func6 func6 = luaEnv.Global.Get<Func6>("func6");
bool out1;
bool rt1 = func6(, out out1, );
Debug.Log(rt1 + "------" + out1); //2. LuaFunction映射,效率低
LuaFunction luaFunc6 = luaEnv.Global.Get<LuaFunction>("func6");
//调用方法 参数就是方法的参数,返回值就是lua方法的返回值,多返回值存入数组中
object[] obj_Arr = luaFunc6.Call(, );
foreach (var item in obj_Arr)
{
Debug.Log(item);
}
} // Update is called once per frame
void Update () { }
private void OnDestroy()
{
luaEnv.Dispose();
}
}
 
Lua调用C#的变量或方法
调用静态的变量:CS.命名空间.类名.变量或属性名 或  CS.类名.变量或属性名
调用成员的变量:
1、类实例化:变量名 = CS.命名空间.类名() 或 CS.类名()
2、调用成员变量或属性:对象名.变量名或属性名
 
Lua调用C#的方法
静态:调用C#的静态方法: CS.命名空间.类名.方法名() 或 CS.类名.方法名()
非静态的: 调用C#的成员方法: 对象名:方法名()
 
NewGameObject.lua.txt
print('开始执行NewGameObject.lua')
--C#:GameObject obj = new UnityEngine.GameObject();
--实例化一个对象
obj = CS.UnityEngine.GameObject();
print('结束执行NewGameObject.lua')
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using XLua;
public class NewGameObject : MonoBehaviour { private LuaEnv luaEnv = new LuaEnv(); void Start () {
luaEnv.DoString("require 'NewGameObject' ");
//GameObject obj = new UnityEngine.GameObject();
} private void OnDestroy()
{
luaEnv.Dispose();
}
}

LuaCallCSharpVariate.lua.txt

print('开始执行LuaCallCSharpVariate.lua')
--静态变量:CS.命名空间.类名.变量或属性名 或 CS.类名.变量或属性名
print("A静态变量", CS.Lesson.A.name)
--调用成员变量,首先需要new出来对象
a = CS.Lesson.A()
--调用成员变量:对象名.变量名或属性名
print("A成员变量", a.id, a.Sex)
print('结束执行LuaCallCSharpVariate.lua')
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using XLua;
public class LuaCallCSharpVariate : MonoBehaviour { private LuaEnv luaEnv = new LuaEnv(); void Start()
{
luaEnv.DoString("require 'LuaCallCSharpVariate' ");
} private void OnDestroy()
{
luaEnv.Dispose();
}
} namespace Lesson
{
public class A
{
public static string name = "A";
public int id;
private bool sex;
public bool Sex
{
get { return sex; }
set { sex = value; }
}
public A() { id = ; sex = true; }
}
}

LuaCallCSharpFunction.lua.txt

print('开始执行LuaCallCSharpFunction.lua')

--C# B.StaticFunc()

--调用C#的静态方法:CS.命名空间.类名.方法名() 或 CS.类名.方法名()
CS.Lesson.B.StaticFunc() --调用C#的成员方法
--实例化一个类对象
b = CS.Lesson.B() --调用C#的成员方法:对象名:方法名()
b:UnStaticFunc() --Xlua支持通过子类的对象去访问父类的方法、属性、变量
b:Func() print('结束执行LuaCallCSharpFunction.lua')
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using XLua;
public class LuaCallCSharpFunction : MonoBehaviour { private LuaEnv luaEnv = new LuaEnv(); void Start()
{
luaEnv.DoString("require 'LuaCallCSharpFunction' ");
} void Update()
{
}
private void OnDestroy()
{
luaEnv.Dispose();
}
} namespace Lesson
{
public class B : C
{
public static void StaticFunc()
{
Debug.Log("这是一个静态方法");
}
public void UnStaticFunc()
{
Debug.Log("这是一个非静态方法");
}
}
public class C
{
public void Func()
{
Debug.Log("Func");
}
}
}
案例 - 用Lua实现游戏物体旋转移动
Move.lua.txt
print("开始执行Move")

--参数就是Move的类对象
Set = function(self)
move = self
end Update = function()
--C# transform.Rotate(Vector3.up*30 * Time.deltaTime);
print("Update") move.transform:Rotate(CS.UnityEngine.Vector3.up * * CS.UnityEngine.Time.deltaTime); v = CS.UnityEngine.Input.GetAxis("Vertical");
h = CS.UnityEngine.Input.GetAxis("Horizontal"); move.transform:Translate(CS.UnityEngine.Vector3(h,,v) * CS.UnityEngine.Time.deltaTime); end
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using XLua;
public class Move : MonoBehaviour
{
private LuaEnv luaenv = new LuaEnv(); [CSharpCallLua]
private delegate void Del();
[CSharpCallLua]
private delegate void Set(Move move);
private Del update; void Start()
{
luaenv.DoString("require 'Move'");
Set set = luaenv.Global.Get<Set>("Set");
set(this);//把自己传递到lua中去
update = luaenv.Global.Get<Del>("Update");
} void Update()
{
//transform.Rotate(Vector3.up*30 * Time.deltaTime);
//transform
/*
float v = Input.GetAxis("Vertical");
float h = Input.GetAxis("Horizontal");
transform.Translate(new Vector3(h,0,v) * Time.deltaTime);
*/
if (null != update)
{
update();
}
} private void OnDestroy()
{
update = null;
luaenv.Dispose();
}
}

Unity3D学习笔记(三十一):Xlua(1)的更多相关文章

  1. angular学习笔记(三十一)-$location(2)

    之前已经介绍了$location服务的基本用法:angular学习笔记(三十一)-$location(1). 这篇是上一篇的进阶,介绍$location的配置,兼容各版本浏览器,等. *注意,这里介绍 ...

  2. angular学习笔记(三十一)-$location(1)

    本篇介绍angular中的$location服务的基本用法,下一篇介绍它的复杂的用法. $location服务的主要作用是用于获取当前url以及改变当前的url,并且存入历史记录. 一. 获取url的 ...

  3. Java学习笔记三十一:Java 包(package)

    Java 包(package) 一:包的作用: 如果我们在使用eclipse等工具创建Java工程的时候,经常会创建包,那么,这个包是什么呢. 为了更好地组织类,Java 提供了包机制,用于区别类名的 ...

  4. PHP学习笔记三十一【const】

    <?php //常量都是public类型 // const 常量名=赋值 .变量名不需要加$符号,也不需要要访问修饰符,默认就是public class A{ const TAX_RATE=0. ...

  5. Unity3D学习笔记(十一):布料和协程

    延迟函数:动态资源加载:T:Resources.Load<T>(string path);Assets - Resources,Resources是一个资源管理的工具类,预制体放在Reso ...

  6. VSTO 学习笔记(十一)开发Excel 2010 64位自定义公式

    原文:VSTO 学习笔记(十一)开发Excel 2010 64位自定义公式 Excel包含很多公式,如数学.日期.文本.逻辑等公式,非常方便,可以灵活快捷的对数据进行处理,达到我们想要的效果.Exce ...

  7. python3.4学习笔记(二十一) python实现指定字符串补全空格、前面填充0的方法

    python3.4学习笔记(二十一) python实现指定字符串补全空格.前面填充0的方法 Python zfill()方法返回指定长度的字符串,原字符串右对齐,前面填充0.zfill()方法语法:s ...

  8. kvm虚拟化学习笔记(三)之windows kvm虚拟机安装

    KVM虚拟化学习笔记系列文章列表----------------------------------------kvm虚拟化学习笔记(一)之kvm虚拟化环境安装http://koumm.blog.51 ...

  9. Unity3D学习笔记2——绘制一个带纹理的面

    目录 1. 概述 2. 详论 2.1. 网格(Mesh) 2.1.1. 顶点 2.1.2. 顶点索引 2.2. 材质(Material) 2.2.1. 创建材质 2.2.2. 使用材质 2.3. 光照 ...

  10. Unity3D学习笔记3——Unity Shader的初步使用

    目录 1. 概述 2. 详论 2.1. 创建材质 2.2. 着色器 2.2.1. 名称 2.2.2. 属性 2.2.3. SubShader 2.2.3.1. 标签(Tags) 2.2.3.2. 渲染 ...

随机推荐

  1. sitecore系列教程之目标功能有什么新意?

    由于SItecore 8中有很多令人兴奋的东西,我选择专注于体验平台的特定领域,这篇文章的主题是目标. 1.客户智能选项  目标项目(/ sitecore / system / Marketing C ...

  2. orb slam2 双目摄像头

    主要参考了http://blog.csdn.net/awww797877/article/details/51171099这篇文章,其中需要添加的是:export ROS_PACKAGE_PATH=$ ...

  3. Java8的CompletionService使用与原理

    为了防止无良网站的爬虫抓取文章,特此标识,转载请注明文章出处.LaplaceDemon/ShiJiaqi. https://www.cnblogs.com/shijiaqi1066/p/1045423 ...

  4. Linux服务器---邮件服务器dovecot

    安装dovecot Dovecot是CentOS系统中著名的POP3/IMAP服务器实现.POP3/IMAP是从邮件服务器中读取邮件时使用的协议,POP3将邮件全部从服务器中拖取下来:IMAP则每次从 ...

  5. linux dns

    linux 用户相关的 root   相当于QQ群主 sudo  QQ群管理员 普通用户  QQ群水军 root  UID 是 0   组UID也是0  普通用户UID从1000开始 查看用户id 信 ...

  6. thinkphp 开启事物

    $Member->startTrans();//启动事务 // 提交事务$ Member->commit(); // 事务回滚$Member ->rollback();

  7. Cookie&Session与自定义session

    cookie与session的区别? cookie是保存在浏览器端的键值对 session是保存在服务器端的键值对 session依赖于cookie 摘自: http://bubkoo.com/201 ...

  8. oracle 12.2 linux/solaris正式发布

    oracle 12.2 linux/solaris正式发布,可以从http://www.oracle.com/technetwork/database/enterprise-edition/downl ...

  9. 【题解】Luogu P4344 [SHOI2015]脑洞治疗仪

    原题传送门:P4344 [SHOI2015]脑洞治疗仪 前置芝士:珂朵莉树 窝博客里对珂朵莉树的介绍 没什么好说的自己看看吧 珂朵莉树好题啊 我一开始一直Re65 后来重构代码就ac了,或许是rp问题 ...

  10. linux homebrew skill 技巧

    $ cat /usr/bin/gitdiffH0#!/bin/bashgit diff HEAD $(git ls-files| grep '\.py$\|\.py\.in$') | osflake8 ...