Zephus 发表于 2023-2-28 17:27

Unity3D使用XLua实现简单热更新

使用XLua热更新

简单的XLua热更Demo 1.首先第一步,是下载xlua插件,可以直接在GitHub下载:xlua插件地址 2.按照热更新设置:在Project Setting 的Player的Scripting Define Symbols添加HOTFIX_ENABLE,这样在编辑器上会看到XLua,然后有Generate Code和HotFix Inject In Editor,在C#脚本有改动的时候就要Generate Code一下(会提示finish) 3.要热更的地方需要标识特性,在类声明的位置标识的时候在打包的时候会热更不成功,解决方案:
public static class HotFixConfig
{
   
    public static List<Type> by_field = new List<Type>()
    {
      typeof(Load),
      typeof(Cube)
    };
}
4.要执行lua,开启一个lua虚拟机
private void Awake()
    {
      luaEnv = new LuaEnv();
      luaEnv.AddLoader(MyLoader);
      luaEnv.DoString("require 'Test'");
    }
    private byte[] MyLoader(ref string filePath)
    {
      string absPath = @"E:\Unity3d\HotFix\XluaTest\" + filePath + ".lua.txt";
      returnSystem.Text.Encoding.UTF8.GetBytes(File.ReadAllText(absPath));
    }
5.lua那边要调用的C#函数要标识为[LuaCallCSharp] 这里只实现了简单的下载单个资源,具体需要再去细写

    public void LoadResource(string resName,string filePath)
    {
      StartCoroutine(Load(resName, filePath));
    }

    IEnumerator Load(string resName,string filePath)
    {
      AssetBundle assetBundle=null;
      if (!bundleDic.ContainsKey(filePath))
      {
            UnityWebRequest request = UnityWebRequestAssetBundle.GetAssetBundle(@"path" + filePath);
            yield return request.SendWebRequest();
            Debug.Log(request);
            bundleDic.Add(filePath, DownloadHandlerAssetBundle.GetContent(request));
      }
      yield return bundleDic;
      assetBundle = bundleDic;
      //.downloadHandler as DownloadHandlerAssetBundle).assetBundle;
      Debug.Log(assetBundle);
      //WWW wWW = new WWW(@"path" + filePath);
      //yield return wWW;
      //AssetBundle assetBundle = wWW.assetBundle;
      //Debug.Log(assetBundle);
      GameObject obj = assetBundle.LoadAsset<GameObject>(resName);

      if (!objDic.ContainsKey(resName))
      {
            objDic.Add(resName, obj);
      }
    }

   
    public GameObject GetPrefab(string resName)
    {
      return objDic;
    }
这里打包AssetBundle用的是官方的插件,也是可以在GitHub下载的:AssetBundle插件地址 附:导入方式:Window-》Package Manager-》右上角的加号-》选择第一个(Add package from disk)->找到下载的这个文件的package.json文件
6.开启了lua虚拟机,当然也要销毁
private void OnDestroy()
    {
      luaEnv.Dispose();
    }
7.
private void OnDisable()
    {
       luaEnv.DoString("require 'LuaDispose'");
    }
    //LuaDispose.lua.txt内容
    xlua.hotfix(CS.Cube,"Update",nil)
    xlua.hotfix(CS.Load,"Start",nil)
    xlua.hotfix(CS.Load,"Update",nil)
8.其他脚本
public class Load : MonoBehaviour
{
    public HotFixScript hotFix;

    private void Awake()
    {
      if (!hotFix)
      {
            hotFix = GetComponent<HotFixScript>();
      }
    }
   
    public void Start()
    {

    }

   
    public void Update()
    {

    }
}

public class Cube : MonoBehaviour
{
    public Rigidbody rigidbody1;
    // Start is called before the first frame update
    void Start()
    {
      rigidbody1 = gameObject.GetComponent<Rigidbody>();
    }

   
    // Update is called once per frame
    public void Update()
    {
      if (Input.GetKeyDown(KeyCode.W))
      {
            rigidbody1.AddForce(Vector3.up*300);
      }
    }
}
9.lua热更内容
local UnityEngine=CS.UnityEngine

xlua.hotfix(CS.Cube,'Update',function (self)
    if(UnityEngine.Input.GetKeyDown(UnityEngine.KeyCode.G))then
      self.rigidbody1:AddForce(UnityEngine.Vector3.up*300)
    end
end)

xlua.hotfix(CS.Load,'Start',function (self)
    self.hotFix:LoadResource('Sphere','gameobject.unity3d')
end)

xlua.hotfix(CS.Load,'Update',function(self)
    if(UnityEngine.Input.GetKeyDown(UnityEngine.KeyCode.T))then
       local obj= UnityEngine.GameObject.Instantiate(self.hotFix:GetPrefab('Sphere'))
       obj.transform.position=UnityEngine.Vector3.right
    end
end)10.在Loading场景加载那两个lua文件
public class LoadScene : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
      StartCoroutine(LoadLuaTxt());
    }

    IEnumerator LoadLuaTxt()
    {
      UnityWebRequest request = UnityWebRequest.Get(@"path/Test.lua.txt");
      yield return request.SendWebRequest();
      string str = request.downloadHandler.text;
      File.WriteAllText(@"E:\Unity3d\HotFix\XluaTest\"+"Test.lua.txt",str);
      UnityWebRequest request1 = UnityWebRequest.Get(@"path/LuaDispose.lua.txt");
      yield return request1.SendWebRequest();
      string str1 = request1.downloadHandler.text;
      File.WriteAllText(@"E:\Unity3d\HotFix\XluaTest\" + "LuaDispose.lua.txt", str1);
      SceneManager.LoadSceneAsync("SampleScene");
    }

}
附:path都是指的服务器地址,之前有需求用了腾讯云的对象存储,所以博主这里都是放在腾讯云里的
11.其他:从服务器下载图片资源方法
IEnumerator LoadImage()
    {
      UnityWebRequest request = UnityWebRequestTexture.GetTexture(@"path/AssetBundles/PC/1.jpg" );
      yield return request.SendWebRequest();
      if (request.error != null)
      {
            Debug.Log(request.error);
      }
      Texture2D texture2D = DownloadHandlerTexture.GetContent(request);
      image.sprite = Sprite.Create(texture2D, new Rect(0,0,texture2D.width,texture2D.height),Vector2.zero);
    }
页: [1]
查看完整版本: Unity3D使用XLua实现简单热更新