什么是XLua
XLua是腾讯开源的一款Unity热更新插件
XLua与其他热更新方案比优势
- GitHub上星数最多
- 可以更多地使用C#代码
- Lua兼容多
- 掌握Lua在游戏行业更有竞争优势
XLua热更新流程
- 把L和AB文件放在服务器上(这里Lua脚本文件咱就叫L)
- Unity应用从服务器下载L,L写入在本地,编译本地L,L内容是修改C#脚本内容,编译修改后的C#脚本,哇,热更了脚本
- 再次热更脚本,使C#脚本可以从服务器下载AB文件,把AB文件转换成新游戏对象(C#来写Lua来调简单些),有了对象,再次热更脚本让它在场景中显示,哇,热更了资源
教程环境
- Unity2018.4.14f1
- XLua最新版本
- Win10家庭版64位1909
安装过程
- 打开自己某个Unity项目工程,该工程这里咱取名叫B
- 打开从GitHub下载的XLua,在B与之相对应目录下拷入Xlua相关文件(如下图)
- Unity编辑打开PlayerSettings中的相关设置,其中键入”HOTFIX_ENABLE“(如下图)
- 在B与之相对应目录下,拷入3个Unity编辑器安装目录中的dll文件(如下图)
- 之后可运行XLua自带案例试试,每次修改脚本后都要先点1再点3,只有代码冲突才点2(如下图)
- 在服务器上放3个Lua文件,1是补丁脚本,2是释放脚本,3是XLua中的库(如下图)
开始写代码
- 写一个xlua热更管理器脚本,把它挂载在某个游戏对象上
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Text;
using UnityEngine;
using UnityEngine.Networking;
using XLua;
[Hotfix] //所有要热更的类都要打上这个标签
public class HotFixScript : MonoBehaviour
{
public static Dictionary<string, GameObject> prefabDict = new Dictionary<string, GameObject>(); //字典保存从AB文件加载的游戏对象
private LuaEnv luaEnv;
private void Start()
{
luaEnv = new LuaEnv();
luaEnv.AddLoader(MyLoader); //加载器方便加载而生,可以加载到该路径下的一些lua文件
luaEnv.DoString("require'fish2'"); //加载fish2
}
private byte[] MyLoader(ref string filepath)
{
var temp1 = Application.persistentDataPath; //本地可读写的目录
var temp2 = ".lua.txt";
var temp3 = temp1 + "/" + filepath + temp2;
return Encoding.UTF8.GetBytes(File.ReadAllText(temp3));
}
private void OnDisable()
{
luaEnv.DoString("require'fishDispose2'"); //加载fishDispose2,里面有释放的lua代码
}
private void OnDestroy()
{
luaEnv.Dispose(); //释放环境
}
[LuaCallCSharp] //既然这个方法是要被Lua调用的,所以要加上这个标签,性能更好,否则将会使用反射来搞性能更差
public void LoadResource(string resName, string filePath) //从远程加载ab转换对象放入缓存,这里是提前用C#写好方法,然后用Lua去调用
{
StartCoroutine(LoadResourceCorotine(resName, filePath));
}
private IEnumerator LoadResourceCorotine(string resName, string filePath)
{
var request = UnityWebRequestAssetBundle.GetAssetBundle(@"http://122.51.186.74/Book/AssetBundles/" + filePath);
yield return request.SendWebRequest();
var ab = (request.downloadHandler as DownloadHandlerAssetBundle).assetBundle;
var gameObject = ab.LoadAsset<GameObject>(resName);
prefabDict.Add(resName, gameObject);
}
[LuaCallCSharp]
public static GameObject GetGameObject(string goName) //获取缓存的ab变成的对象
{
return prefabDict[goName];
}
}
- 上线版前放一个或多个脚本(如下),万一上线版有新需求,就可以热更新此脚本实现新类。
using UnityEngine;
using XLua;
[Hotfix]
public class HotClass2 : MonoBehaviour
{
[LuaCallCSharp]
public void Function1()
{
}
[LuaCallCSharp]
public void Function2()
{
}
}
- 打AB资源包(略)
- Lua释放脚本(供参考)
xlua.hotfix(CS.Treasour,'CreatePrize',nil)--CS.Treasour表示类,'CreatePrize'表示类中方法,这里要释放掉
xlua.hotfix(CS.Bullect,'OnTriggerEnter',nil)
xlua.hotfix(CS.Bullect,'Start',nil)
xlua.hotfix(CS.CreateFish,'Update',nil)
xlua.hotfix(CS.CreateFish,'Start',nil)
- Lua补丁脚本(供参考)
local UnityEngine=CS.UnityEngine
local printTrue =true;
local util = require('util');
xlua.private_accessible(CS.Bullect)--开启可以访问私有成员
util.hotfix_ex(CS.Bullect,'OnTriggerEnter',function(self,other)--热更方法,这个可以复写原来方法,性能较差
self.OnTriggerEnter(self,other)--原来的方法
if printTrue then
local go =UnityEngine.GameObject.Find("Ainiyou").GetComponent("Text");--没有泛型用这种形式
go.text = "ainiyou";
end
end)
xlua.hotfix(CS.Bullect,'Start',function(self)--热更方法,这个是完全改写
local b = self:GetComponent('BoxCollider');
print(b.isTrigger);
local brandom =UnityEngine.Mathf.FloorToInt(UnityEngine.Random.Range(0,8));--Lua没有int的解决方案
print(brandom);
end)
util.hotfix_ex(CS.Treasour,'CreatePrize',function(self)
self: CreatePrize();
for i=0,4,1 do
local go=UnityEngine.GameObject.Instantiate(self.gold,self.transform.position+UnityEngine.Vector3(-10+i*10,0,0),self.transform.rotation)--Vector3在Lua没有New
go.transform.SetParent(go.transform,self.cavas)
local go1=UnityEngine.GameObject.Instantiate(self.diamands,self.transform.position+UnityEngine.Vector3(0,10,0)+UnityEngine.Vector3(-10+i*10,0,0),self.transform.rotation)
go1.transform.SetParent(go1.transform,self.cavas)
end
end)
xlua.private_accessible(CS.CreateFish)
xlua.hotfix(CS.CreateFish,'Start',function(self)
self.hotFixScript:LoadResource('level3fish3','level3fish3.ab')--修改让脚本可以加载ab
--self.hotFixScript:LoadResource('SeaWave','gameobject\\wave.ab')
end)
补充说明
- 个人一些配置,实现了给所有类打
[HotFix]
(如下图)
- 打安装包要把XLua案例删掉
- 详细教程请看官方文档,水平有限,多多指教