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. bash 替换特殊字符

    bash 替换特殊字符 PID=`netstat -tpln|grep `;PID=${PID#*LISTEN};PID=`echo $PID | sed -s "s/\/java//g&q ...

  2. python mmap对象

    ----使用内存映射的原因 为了随机访问文件的内容,使用mmap将文件映射到内存中是一个高效和优雅的方法.例如,无需打开一个文件并执行大量的seek(),read(),write()调用,只需要简单的 ...

  3. vue-cli项目npm run build后,index.html无法在浏览器打开

  4. c# 控件的基类——Control

    控件的基类用于Windows窗体应用的控件都派生自Control类,并继承了许多通用成员,这些成员都是平时使用控件的过程中最常用的. Name:控件实例的名字,通常通过“属性”窗口设置,控件实例名称变 ...

  5. Linux上查看大文件的开头几行内容以及结尾几行的内容

    head -n 50 filePath 查看开头50行的内容 tail -n 50 filePath 查看文件结尾50行的内容

  6. Token:共识的下一个100年,区块链技术是无可阻挡的文明进程

    Token:共识的下一个100年,区块链技术是无可阻挡的文明进程.很少有人意识到,区块链的应用——Token可能是近100年来最伟大的制度创新,超越股份制,并将是『债券』之后最重要最主流的交易品种,没 ...

  7. JustOj 2039: 成绩排名 (结构体排序)

    题目描述 每次期末考试成绩出来之前的一段时间大豪哥心里都是痛苦的,总感觉自己会在班上排名特别差.所以当成绩出来以后大豪哥想快点知道班上的总排名,以便知道自己的排名.(PS:大豪哥班上有个学霸名叫日天, ...

  8. Linux CPU使用率含义及原理

    相关概念 在Linux/Unix下,CPU利用率分为用户态.系统态和空闲态,分别表示CPU处于用户态执的时间,系统内核执行的时间,和空闲系统进程执行的时间. 下面是几个与CPU占用率相关的概念. CP ...

  9. MyEclipse配置Struts2的本地工作空间中的DTD约束文件

    1.拷贝URI http://struts.apache.org/dtds/struts-2.3.dtd 2.配置XML Catalog 3.struts-2.3.dtd文件来源 解压jar包\Web ...

  10. uwsgi 的巨坑

    网上各种找,最后自己猜,猜到了. 必须安装python插件, 网上找的都是不带数字的版本号, 要么找不到要么不行. 我是 3.6.1,尝试加36, 成了. yum install -y uwsgi-p ...