1. XLua是什么?
Xlua是Lua在C#环境(.net)下的Lua解决方案,包括C#环境下的Lua代码解释器(Lua虚拟机)。
2. 基于XLua的纯Lua开发环境的基本原则?
- Unity场景里不放任务物体,通过代码创建和释放物体。这样避免冲突,方便维护(比如程序和美术都往场景里放了同一物体),可以通过搜索代码查看创建了哪些物体以及结构关系。
- 运行时只有一个场景,没有场景切换。地图、角色、特效、粒子...都被做成资源或预制体给代码使用。(这一步实现美术与程序分离)
- 不手动往节点上面挂脚本,而是通过代码AddComponent挂载。(方便维护,直接搜索组件名称就能找到哪里挂载了脚本)
- 纯AssetsBundle来做资源管理,代替Resources。这样方便更新,方便打空包。
- 制定一个纯Lua的组件化开发框架。方便写业务逻辑,减少Lua与C#相互调用。
- 调试模式加载Lua代码、资源。AssetDataBase来加载资源。发布模式,打AB包,更新。
3. 在Unity中使用XLUA
1)https://github.com/Tencent/xlua 下载xlua
2)复制Assets文件夹下四个文件到工程Assets文件夹
3)打开宏
4)任何代码的修改都要执行以下两个步骤才能运行:
5)下面开始写C#调用Lua的代码
写一个lua文件,命名后缀 .lua.txt
注意lua文件要放在C#脚本的同级Resources目录下。
下面是C#脚本,演示C#脚本里调用lua。
1 using System.Collections;
2 using System.Collections.Generic;
3 using UnityEngine;
4 using XLua;
5
6 public class textCSharp : MonoBehaviour
7 {
8 LuaEnv env = new LuaEnv();
9
10 private void OnGUI()
11 {
12 if (GUILayout.Button("C#调用Lua语句"))
13 env.DoString("print 'testlua'");
14
15 if (GUILayout.Button("C#调用Lua文件"))
16 CSharpCallLuaFile();
17 }
18 void CSharpCallLuaFile()
19 {
20 env.DoString("require 'luatest'");
21 //调用lua全局变量
22 Debug.Log(env.Global.Get<string>("name"));
23 Debug.Log(env.Global.Get<int>("age"));
24 //调用lua表中数据
25 LuaTable table = env.Global.Get<LuaTable>("config");
26 Debug.Log(table.Get<string>("name"));
27 Debug.Log(table.Get<string>("age"));
28 }
29 }
也可以直接映射成类
1 public class textCSharp : MonoBehaviour
2 {
3 LuaEnv env = new LuaEnv();
4
5 private void OnGUI()
6 {
7 if (GUILayout.Button("C#调用Lua文件"))
8 CSharpCallLuaFile();
9 }
10 void CSharpCallLuaFile()
11 {
12 env.DoString("require 'luatest'");
13
14 Config config = env.Global.Get<Config>("config");
15 Debug.Log(config.name);
16 Debug.Log(config.age);
17 }
18 public class Config
19 {
20 public string name;
21 public int age;
22 }
23 }
1 void CSharpCallLuaFile()
2 {
3 env.DoString("require 'luatest'");
4 //调用lua函数并接收返回值
5 LuaFunction fun = env.Global.Get<LuaFunction>("printInfo");
6 object[] objs = fun.Call(); //lua函数可以有1个或多个返回值
7 Debug.Log(objs[0]);
8 }
结果是:第一行输出的是Call()里面的内容
也可以使用委托来调用lua函数
1 public class textCSharp : MonoBehaviour
2 {
3 LuaEnv env = new LuaEnv();
4
5 delegate int Fun(int num);
6 private void OnGUI()
7 {
8 if (GUILayout.Button("C#调用Lua文件"))
9 CSharpCallLuaFile();
10 }
11 void CSharpCallLuaFile()
12 {
13 env.DoString("require 'luatest'");
14 //调用lua函数并接收返回值
15 Fun f = env.Global.Get<Fun>("printInfo");
16 Debug.Log(f(0));
17 }
18 }
输出:
6)下面演示Lua调用C#
先写一个C#类
1 public class Hero
2 {
3 private int Hp;
4 private string Name;
5
6 public Hero(string name, int hp)
7 {
8 this.Name = name;
9 this.Hp = hp;
10 }
11 public void PrintInfo()
12 {
13 Debug.Log(Name + "的血量是:" + Hp);
14 }
15 public int AddHp(int _hp)
16 {
17 Debug.Log("lua传递来的参数:" + _hp);
18 Hp += _hp;
19 return Hp;
20 }
21 }
lua脚本
注意:Lua调用C#类,要加CS
Lua调用 MonoBehaviour 类要加 CS.UnityEngine
别忘了在C#里执行一下
1 public class textCSharp:MonoBehaviour
2 {
3 LuaEnv env = new LuaEnv();
4 void OnGUI()
5 {
6 if (GUILayout.Button("Lua调用C#"))
7 {
8 LuaCallCSharp();
9 }
10 }
11 void LuaCallCSharp()
12 {
13 env.DoString("require 'luatest'");
14 }
15 }
结果如下:
--------------------------------------------------------------------------------------------------------------------------------------------------------------
XLUA配置三步:
1.打标签 :XLUA会自动生成适配代码,注意子类打了标签,父类也要打。
[LuaCallCSharp] Lua里适配的委托、接口也要在C#定义里打标签。
[CSharpCallLua]
[Hotfix]
2.静态列表
3.动态列表
加 static List<Type> 修饰
详细参考:https://github.com/Tencent/xLua/blob/master/Assets/XLua/Doc/configure.md
===================================================================================
下面我们来搭一个XLUA使用框架
1 using System.Collections;
2 using System.Collections.Generic;
3 using UnityEngine;
4 using XLua;
5 using System;
6
7 [LuaCallCSharp]
8 public class LuaEnvMgr
9 {
10 //单例
11 private static LuaEnvMgr instance;
12 public static LuaEnvMgr Instance
13 {
14 get {
15 if (instance == null)
16 instance = new LuaEnvMgr();
17 return instance;
18 }
19 }
20 //封装Lua虚拟机
21 private LuaEnv env;
22 public LuaEnv Env
23 {
24 get { return env; }
25 }
26 //构造函数初始化Lua虚拟机
27 public LuaEnvMgr()
28 {
29 env = new LuaEnv();
30 }
31 //获取Lua table
32 public LuaTable GetGlobalTable()
33 {
34 return env.Global;
35 }
36 //创建Lua table
37 public LuaTable CreateTable()
38 {
39 return env.NewTable();
40 }
41 //释放
42 public void Dispose()
43 {
44 env.Dispose();
45 }
46 }
47
48 [CSharpCallLua]
49 public delegate void OnCollisionDel(Collision2D collision);
50
51 [CSharpCallLua]
52 public delegate void OnTriggerDel(Collider2D collision);
53 /// <summary>
54 /// 方便Lua调用C#生命周期函数
55 /// </summary>
56 [LuaCallCSharp]
57 public class LuaCallBase : MonoBehaviour {
58
59 public TextAsset textAsset;//lua文件
60
61 protected LuaTable table;//存储lua文件数据的表
62
63 //常用更新生命周期
64 protected Action luaAwake;
65 protected Action luaStart;
66 protected Action luaUpdate;
67 protected Action luaDestory;
68 protected Action luaOnGUI;
69
70 //自定义委托生命周期
71 protected OnCollisionDel luaCollisionEnter;
72 protected OnTriggerDel luaTriggerEnter;
73
74
75 protected virtual void Awake()
76 {
77 table = LuaEnvMgr.Instance.CreateTable();
78 LuaTable meta = LuaEnvMgr.Instance.CreateTable();
79 meta.Set("__index", LuaEnvMgr.Instance.GetGlobalTable());
80 table.SetMetaTable(meta);
81 meta.Dispose();
82
83 LuaEnvMgr.Instance.Env.DoString(textAsset.text, this.GetType().Name, table);
84
85
86 SetLuaData();
87 GetLuaData();
88 if (luaAwake != null)
89 luaAwake();
90 }
91
92 public object GetLuaData(string dataName)
93 {
94 object obj;
95 table.Get(dataName,out obj);
96 return obj;
97 }
98
99 protected virtual void SetLuaData()
100 {
101 table.Set("self", this);
102 }
103
104 protected virtual void GetLuaData()
105 {
106 table.Get("awake", out luaAwake);
107 table.Get("start", out luaStart);
108 table.Get("update", out luaUpdate);
109 table.Get("destroy", out luaDestory);
110 table.Get("ongui", out luaOnGUI);
111
112 table.Get("onCollisionEnter", out luaCollisionEnter);
113 table.Get("onTriggerEnter", out luaTriggerEnter);
114 }
115
116 private void Start()
117 {
118 if (luaStart != null)
119 luaStart();
120 }
121 private void Update()
122 {
123 if (luaUpdate != null)
124 luaUpdate();
125 }
126 private void OnGUI()
127 {
128 if (luaOnGUI != null)
129 luaOnGUI();
130 }
131 private void OnDestroy()
132 {
133 if (luaDestory != null)
134 luaDestory();
135 }
136
137 private void OnCollisionEnter2D(Collision2D collision)
138 {
139 if (luaCollisionEnter != null)
140 luaCollisionEnter(collision);
141 }
142 private void OnTriggerEnter2D(Collider2D collision)
143 {
144 if (luaTriggerEnter != null)
145 luaTriggerEnter(collision);
146 }
147 }
View Code
只需要继承这个框架类,把lua脚本拖上去,就会执行啦!跟C#在Unity里的操作一样,只是挂载的C#脚本里的功能都由Lua脚本来实现了。
如果嫌Lua每次调用C#方法都要加前缀麻烦。可以写一个Lua公共脚本,把这些前缀重新赋值,其他脚本只要 require "公共脚本名",就可以像写C#一样调用Unity方法啦!
System=CS.System
Int=System.Int32
String=System.String
Unity=CS.UnityEngine
Debug=Unity.Debug
GameObject=Unity.GameObject
Transform=Unity.Transform
Renderer=Unity.Renderer
Color=Unity.Color
Vector3=Unity.Vector3
Vector2=Unity.Vector2
Input=Unity.Input
Resources=Unity.Resources
Camera=Unity.Camera
LineRenderer=Unity.LineRenderer
EdgeCollider2D=Unity.EdgeCollider2D
Time=Unity.Time
Vector3List=CS.System.Collections.Generic.List(Vector3)
Vector2List=CS.System.Collections.Generic.List(Vector2)
function getLuaData(obj,script,data)
local instance=obj:GetComponent(script)
return instance:GetLuaData(data)
end
参考:Unity3D架构师进阶系列: 基于xLua的热更框架