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 CMS中更改项目的模板

    如何在Sitecore CMS中创建项目后更改项目的模板. 在创建项目时选择了错误的模板,或者创建了新模板并将现有项目更新为新模板时,这非常有用.   警告! 更改模板时要小心.如果原始模板具有不在新 ...

  2. [openjudge-搜索]深度优先搜索之马走日

    题目描述 描述 马在中国象棋以日字形规则移动.请编写一段程序,给定n*m大小的棋盘,以及马的初始位置(x,y),要求不能重复经过棋盘上的同一个点,计算马可以有多少途径遍历棋盘上的所有点. 输入 第一行 ...

  3. 【Hadoop学习之十二】MapReduce案例分析四-TF-IDF

    环境 虚拟机:VMware 10 Linux版本:CentOS-6.5-x86_64 客户端:Xshell4 FTP:Xftp4 jdk8 hadoop-3.1.1 概念TF-IDF(term fre ...

  4. python 使用json.dumps() 的indent 参数,获得漂亮的格式化字符串后输出

    想获得漂亮的格式化字符串后输出,可以使用json.dumps() 的indent 参数.它会使得输出和pprint() 函数效果类似 >>> data {'age': 4, 'nam ...

  5. Java技术整理1---反射机制及动态代理详解

    1.反射是指在程序运行过程中动态获取类的相关信息,包括类是通过哪个加载器进行加载,类的方法和成员变量.构造方法等. 如下示例可以通过三种方法根据类的实例来获取该类的相关信息 public static ...

  6. Linux基础命令---设置程序优先级nice

    nice nice指令可以设置程序运行的优先级,优先级会影响到程序的调度时间.nice的范围是-20~19,其中-20级别最高,19级别最低. 此命令的适用范围:RedHat.RHEL.Ubuntu. ...

  7. Javascript创建类的七种方法

    /* 第一种定义类的方法 */var cls = new Object();cls.name = "wyf";cls.showName = function(){console.l ...

  8. P5015 标题统计

    P5015 标题统计 ‘   ’ 不等于空格,空格是个字符 代码: #include<iostream> #include<cstdio> #include<cmath& ...

  9. spark与kafka集成进行实时 nginx代理 这种sdk埋点 原生日志实时解析 处理

    日志格式202.108.16.254^A1546795482.600^A/cntv.gif?appId=3&areaId=8213&srcContId=2535575&area ...

  10. 合并两个JsonArray

    //合并两个JSONArray public static String joinJSONArray(JSONArray mData, JSONArray array) { StringBuffer ...