需求:實作熱更新全流程。(代碼熱更、物體熱更)
本篇文章使用的是xlua來開發的。學習的是這位老哥的
步驟:
1:導入xlua
(1)首先xlua直接去hub上下過來(XLua)。

(2)解壓壓縮包。打開檔案夾,把Assets裡面的東西全部複制到自己工程的Assets檔案夾下。
這裡面的其他檔案夾是我自己建立的。
然後再把tools也拖到工程目錄裡面跟Assets同級。
到這裡,xlua環境就算弄好了(不學習、運作案例的話)。
下面就是官方案例運作了:
案例都在XLua下的Examples檔案夾裡面。
運作案例之前需要打開場景之後;
在菜單面闆找到并點選XLua——Generate Code(生成);
然後點選Hotfix Inject In Editor(注入unity編輯器,這樣才能在unity編輯器裡面運作成功);
最後就是點選運作就可以了。
2:搭建自己的遊戲場景并寫入邏輯
(1)建立一個場景取名Game并放到Scenes檔案夾下。
(2)在Game場景裡面建立一個Plane作為地闆,建立一個Cube作為遊戲物體。
(3)給Cube添加剛體元件(Rigidbody)和腳本控制(Cube.cs)
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using XLua;
[Hotfix]//辨別
public class Cube : MonoBehaviour
{
private Rigidbody _rigidbody;//定義元件
void Start()
{
_rigidbody = GetComponent<Rigidbody>();//擷取元件
}
[LuaCallCSharp]//辨別
void Update()
{
if (Input.GetKeyDown(KeyCode.W))//控制
{
_rigidbody.AddForce(Vector3.up * 500);
}
}
}
(4)在工程檔案的同一層級建立一個Lua檔案夾,并在Lua檔案夾下建立兩個文本檔案(取名Test.lua.txt和LuaDispose.lua.txt)
輸入内容
Test.lua.txt 的内容
local UnityEngine=CS.UnityEngine
xlua.hotfix(CS.Cube,'Update',function(self)
if(UnityEngine.Input.GetKeyDown(UnityEngine.KeyCode.S))then
self._rigidbody:AddForce(UnityEngine.Vector3.up*500)
end
end)
LuaDispose.lua.txt 的内容
(5)建立一個熱更腳本(HotfixScript.cs)并在場景中建立一個空物體取名HotfixScript,把腳本拖到空物體上。
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Text;
using UnityEngine;
using UnityEngine.Networking;
using XLua;
public class HotFixScript : MonoBehaviour
{
private LuaEnv _luaEnv;//建立lua運作環境
private void Awake()
{
_luaEnv = new LuaEnv(); //執行個體lua運作環境
_luaEnv.AddLoader(MyLoader); //必須要有的
_luaEnv.DoString("require'Test'"); //loader進行加載Test.lua.txt 從"E:\Test\Lua\" + filePath + ".lua.txt"檔案中進行加載 (注:require是固定不變的,調用完才能取得裡面的變量)
}
private byte[] MyLoader(ref string filePath)
{
string absPath = @"F:\XLua\Lua\" + filePath + ".lua.txt";
return Encoding.UTF8.GetBytes(File.ReadAllText(absPath));
}
void Start()
{
}
void Update()
{
}
private void OnDisable()
{
_luaEnv.DoString("require'LuaDispose'"); //執行LuaDispose裡面的關閉方法
}
private void OnDestroy()
{
_luaEnv.Dispose(); //釋放lua環境
}
}
然後就可以生成——注入——運作了。(到這裡第一個更新檔就完成了)
3:建立熱更資源并打出AB包
打ab包我之前的一篇部落格裡面有三種方法,随便選一種即可。
這裡我用的是AssetBundle Browser打包的。
打出ab包之後全選複制到伺服器檔案夾下的AssetBundles檔案夾裡面(我打的有兩個物體)
4:搭建一個簡單的本地伺服器
本地伺服器我有一篇部落格也寫到過。
這裡我用的是NetBox2的方法。
5:從伺服器上下載下傳AssetBundles,并加載出來
HotFixScript.cs腳本内容更新一下從伺服器上下載下傳AssetBundles,并加載出來的内容。
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Text;
using UnityEngine;
using UnityEngine.Networking;
using XLua;
public class HotFixScript : MonoBehaviour
{
private LuaEnv _luaEnv;//建立lua運作環境
private void Awake()
{
_luaEnv = new LuaEnv(); //執行個體lua運作環境
_luaEnv.AddLoader(MyLoader); //必須要有的
_luaEnv.DoString("require'Test'"); //loader進行加載Test.lua.txt 從"E:\Test\Lua\" + filePath + ".lua.txt"檔案中進行加載 (注:require是固定不變的,調用完才能取得裡面的變量)
}
private byte[] MyLoader(ref string filePath)
{
string absPath = @"F:\XLua\Lua\" + filePath + ".lua.txt";
return Encoding.UTF8.GetBytes(File.ReadAllText(absPath));
}
void Start()
{
}
void Update()
{
}
private void OnDisable()
{
_luaEnv.DoString("require'LuaDispose'"); //執行LuaDispose裡面的關閉方法
}
private void OnDestroy()
{
_luaEnv.Dispose(); //釋放lua環境
}
[LuaCallCSharp]//需要熱更腳本裡面調用的方法必須加上這個标簽
public void LoadResource(string resName, string filePath) //開啟加載assetbundle裡面的資源的協程
{
StartCoroutine(Load(resName, filePath));
}
private Dictionary<string, GameObject> _objectsAssetBundleDic = new Dictionary<string, GameObject>();//把加載出來的AssetBundle物體存起來,友善使用的時候調用
private string serverPath = @"http://localhost/AssetBundles"; //伺服器AssetBundles存放位址
IEnumerator Load(string resName, string filePath)//加載assetbundle裡面的資源
{
UnityWebRequest request = UnityWebRequestAssetBundle.GetAssetBundle(serverPath + filePath);
yield return request.SendWebRequest();
AssetBundle ab = (request.downloadHandler as DownloadHandlerAssetBundle).assetBundle;
GameObject go = ab.LoadAsset<GameObject>(resName);
Debug.Log(go.name);
_objectsAssetBundleDic.Add(resName, go);
}
[LuaCallCSharp]//需要熱更腳本裡面調用的方法必須加上這個标簽
public GameObject GetAssetBundlePrefab(string resName)//擷取到AssetBundle物體
{
return _objectsAssetBundleDic[resName];
}
}
建立一個熱更加載代碼(Load.cs),以便通過lua調用C#裡面的方法。
using System;
using UnityEngine;
using XLua;
[Hotfix]
public class Load : MonoBehaviour
{
public HotFixScript hot;//定義HotFixScript腳本
private void Start()
{
}
private void Update()
{
}
}
然後更新一下Test.lua.txt 和 LuaDispose.lua.txt 的内容
Test.lua.txt
local UnityEngine=CS.UnityEngine
xlua.hotfix(CS.Cube,'Update',function(self)
if(UnityEngine.Input.GetKeyDown(UnityEngine.KeyCode.S))then
self._rigidbody:AddForce(UnityEngine.Vector3.up*500)--(Lua裡面調用靜态方法直接”.“就可以了,非靜态方法得用”:“)
end
end)
xlua.hotfix(CS.Load,'Start',function(self)--重寫Load代碼裡面的Start方法
self.hot:LoadResource('capsule','\\capsule')--加載ab包裡面的capsule
self.hot:LoadResource('sphere','\\sphere')--加載ab包裡面的sphere
end)
xlua.hotfix(CS.Load,'Update',function(self)--重寫Load代碼裡面的Update方法
if(UnityEngine.Input.GetKeyDown(UnityEngine.KeyCode.G))then
UnityEngine.Object.Instantiate( self.hot:GetAssetBundlePrefab('capsule'))--生成capsule
UnityEngine.Object.Instantiate( self.hot:GetAssetBundlePrefab('sphere'))--生成sphere
end
end)
LuaDispose.lua.txt
xlua.hotfix(CS.Cube,'Update',nil)
xlua.hotfix(CS.Load,'Update',nil)
xlua.hotfix(CS.Load,'Start',nil)
然後開啟伺服器,運作就可以了。
6:下載下傳Lua并加載
(1)建立一個Init場景作為加下載下傳Lua檔案、配置檔案的過渡場景。
(2)建立一個腳本實作Lua檔案下載下傳(LoadLua.cs)
using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.SceneManagement;
public class LoadLua : MonoBehaviour
{
void Start()
{
StartCoroutine(Load());
}
public List<string> luaName = new List<string>(); //所有需要熱更的lua的名字
private string severPath = @"http://localhost/"; //伺服器位址
private string clientPath = @"F:\XLua\Lua\"; //用戶端lua儲存位址
IEnumerator Load()//從伺服器上下載下傳熱更腳本(如果有變則下載下傳新的,沒變則不下載下傳)
{
for (int i = 0; i < luaName.Count; i++)
{
UnityWebRequest requset = UnityWebRequest.Get(severPath + luaName[i] + ".lua.txt");
yield return requset.SendWebRequest();
string str = requset.downloadHandler.text;//擷取lua的内容
Debug.Log(str);
File.WriteAllText(clientPath + luaName[i] + ".lua.txt", str);//寫入并存入本地
}
SceneManager.LoadScene(1);//下載下傳完跳轉到遊戲場景(Game)
}
}
以上就是熱更新的整個流程了。
本文僅作為個人紀錄,如有問題請自行去bilibili上看教程。