XLua热更新入门教程

什么是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案例删掉
  • 详细教程请看官方文档,水平有限,多多指教
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章