
安裝xLua
插件在GITHUB上進行下載下傳。
下載下傳後的檔案目錄結構
- 打開
檔案夾将Assets
和Plugins
這兩個檔案夾Copy到Unity人更新項目中的Assets檔案夾中。XLua
2020最後一篇 Unity熱更新執行個體一鏡到底,看這篇就夠了 在Unity的IDE出現XLua選項
2020最後一篇 Unity熱更新執行個體一鏡到底,看這篇就夠了 -
開啟宏 HOTFIX_ENABLE
File—>Bulid Setting—>Player Settings—>Player—>Scripting Define Symbols
2020最後一篇 Unity熱更新執行個體一鏡到底,看這篇就夠了 設定完成後會在出現
2020最後一篇 Unity熱更新執行個體一鏡到底,看這篇就夠了 - XLua 中的Tools 工具檔案夾 複制到熱更新工程中Assets同級目錄
2020最後一篇 Unity熱更新執行個體一鏡到底,看這篇就夠了 - xLua在Unity中使用步驟
- 每次修改需要更新的腳本,需要運作
。Generate Code
- 執行
,進行Lua注入。Hotfix Inject In Editor
- 檢查Unity 中XLua熱更新環境
- 引入命名空間 using XLua。
- 在需要更新的類上方加入标簽 [Hotfix] 。
- 在需要更新的方法上方加入 [LuaCallCSharp] 。
- 建立LuaEnv
- 将測試腳本HotfixTest 挂載到場景Manager總控中。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using XLua;
using System.IO;
namespace XLuaProject
{
[Hotfix]
public class HotfixTest : MonoBehaviour
{
public LuaEnv luaEnv;
// Start is called before the first frame update
void Start()
{
luaEnv = new LuaEnv();
luaEnv.DoString("CS.UnityEngine.Debug.Log('hello world')");
luaEnv.Dispose();
}
}
}
6. 運作
Generate Code
。
7. 執行
Hotfix Inject In Editor
,進行Lua注入。
8. 運作結果,lua虛拟環境搭建完畢。
安裝AssetBundles-Browser
插件在GITHUB上進行下載下傳。
1. 将插件下載下傳下來後一定注意放入Unity的目錄結構。在Unity的項目目錄中裝件Editor檔案夾。
2.将AssetBundles-Browser解壓後的Editor檔案夾Copy到Unity的項目中。目錄結構如下圖所示。
3.在Unity的IDE導覽列中的Window就會出現AssetBundles-Browser。
場景建構及描述
未更新前運作後值2s後建立一個sun物體并自轉,更新後先建立earth物體并自轉2s後建立sun并自轉,sun出現後earth圍繞sun進行公轉。
- 建立預制體:分别建立兩個預制體earth,sun并分别設定材質。每個球體放個cube是為了看清自轉。
2020最後一篇 Unity熱更新執行個體一鏡到底,看這篇就夠了 - 建立預制體腳本:自轉腳本
,公轉腳本Rotation
。并将自轉腳本挂載到上述兩個預制體上。Revolution
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using XLua;
namespace XLuaProject
{
public class Rotation : MonoBehaviour
{
public static int speed = -50;
// Start is called before the first frame update
[LuaCallCSharp]
void Start()
{
}
// Update is called once per frame
void Update()
{
transform.Rotate(0, speed * Time.deltaTime, 0, Space.Self);
}
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace XLuaProject
{
public class Revolution : MonoBehaviour
{
public GameObject Axis;//軸,用于選擇圍繞中心
public float RotateSpeed = 10;//旋轉速度// Use this for initialization
void Start()
{
}
void Update()
{
this.transform.RotateAround(Axis.transform.position, Vector3.up, RotateSpeed);
}
}
}
- AssetBundle設定打包與加載。
- 預制體設定AssetBundle為
,同樣的操作将earth預制體打包命名為sun
字尾命名為earth
ab
2020最後一篇 Unity熱更新執行個體一鏡到底,看這篇就夠了 - AssetBundles-Browser進行 AssetBundle資源打包。 點選
2020最後一篇 Unity熱更新執行個體一鏡到底,看這篇就夠了
,設定Build Target 及Output Path(輸出目錄)。Build
檢視生成的ab包。2020最後一篇 Unity熱更新執行個體一鏡到底,看這篇就夠了 2020最後一篇 Unity熱更新執行個體一鏡到底,看這篇就夠了 - 加載生成AssetBundle資源包。使用LoadAB腳本進行資源加載。挂載到場景中的總控Manager中。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace XLuaProject
{
public class LoadAB : MonoBehaviour
{
public static Dictionary<string, GameObject> prefabDict = new Dictionary<string, GameObject>();
// Start is called before the first frame update
void Start()
{
}
/// <summary>
/// 加載AB資源
/// </summary>
/// <param name="resName">字典對象名</param>
/// <param name="filePath">資源名</param>
public void LoadResource(string resName, string filePath)
{
string path = Application.dataPath + "/AssetBundles/StandaloneWindows/" + filePath;
AssetBundle ab = AssetBundle.LoadFromFile(path);
GameObject gameObject = ab.LoadAsset<GameObject>(resName);
prefabDict.Add(resName, gameObject);
}
public GameObject GetGameObject(string objName)
{
return prefabDict[objName];
}
}
}
- 加載生成AssetBundle資源包腳本的使用。建立CreateObj腳本通過LoadAB腳本進行資源加載。CreateObj腳本也挂載到總控Manager中。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using XLua;
namespace XLuaProject
{
public class CreateObj : MonoBehaviour
{
LoadAB loadAB;
private void Awake()
{
loadAB = GetComponent<LoadAB>();
}
// Start is called before the first frame update
void Start()
{
Invoke("CreateSun", 2);
}
void CreateSun()
{
loadAB.LoadResource("sun", "sun.ab");
GameObject gameObject = loadAB.GetGameObject("sun");
var tempObj = Instantiate(gameObject);
tempObj.name = "sun";
tempObj.transform.position = new Vector3(0f, 0, 0);
}
}
}
- 運作結果
2020最後一篇 Unity熱更新執行個體一鏡到底,看這篇就夠了
由于引入xLua的關系,每次我們修改加上熱更新辨別的腳本代碼都需要執行一遍 ,運作在執行
Generate Code
,進行Lua注入。否則運作報錯。
Hotfix Inject In Editor
編寫熱更新腳本
官方建議方式二。
和其它配置一樣,有兩種方式
方式一:直接在類裡頭打Hotfix标簽(不建議,示例隻是為了友善示範采取這種方式);
!!注意,方式一在高版本unity不支援
方式二:在一個static類的static字段或者屬性裡頭配置一個清單。屬性可以用于實作的比較複雜的配置,比如根據Namespace做白名單。
!!注意,高版本Unity需要把配置檔案放Editor目錄下
- 在Assets–>Editor檔案夾中建立
靜态類
靜态類靜态類
*因為之前忽略靜态類的這個注意事項我蹲了好久坑。 *,這個腳本使用的Namespace作為白名單進行篩選的,是以需要熱更新的腳本我都會加上命名空間HotficCfg
。XLuaProject
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Text;
using UnityEngine;
using XLua;
public static class HotficCfg
{
[Hotfix]
public static List<Type> by_property
{
get
{
//從程式集中擷取全部類資訊
var allTypes = Assembly.Load("Assembly-CSharp").GetTypes();
var nameSpace = new List<string>();
//周遊所有類篩選符合規則的命名空間
foreach (var t in allTypes)
{
if (t.Namespace != null && (t.Namespace.StartsWith("XLuaProject", StringComparison.CurrentCulture)))
{
if (!nameSpace.Contains(t.Namespace))
{
nameSpace.Add(t.Namespace);
}
}
}
var retList = new List<Type>();
var sb = new StringBuilder();
//周遊所有類篩選所有包含該命名空間的Type對象
foreach (var t in allTypes)
{
if (nameSpace.Contains(t.Namespace))
{
retList.Add(t);
sb.AppendLine(t.FullName);
}
}
//輸出所有Type資訊到項目根目錄HotTypes.txt文本中
File.WriteAllText(Path.Combine(Application.dataPath, "../HotTypes.txt"), sb.ToString());
return retList;
}
}
}
- 每次我們在執行
都會在項目根目錄也就是和Assets平級目錄下生成一個可以熱更新的類的白名單。Generate Code
2020最後一篇 Unity熱更新執行個體一鏡到底,看這篇就夠了 - 在Resources建立lua檔案夾儲存lua腳本,unity中加載lua檔案要以
結尾。.lua.txt
2020最後一篇 Unity熱更新執行個體一鏡到底,看這篇就夠了 - 建立LuaEnv 腳本管理
,自定義加載器MyLoader,lua檔案命名以LuaManager
結尾。.lua.txt
using System.IO;
using UnityEngine;
using XLua;
public class LuaManager : MonoBehaviour
{
public static LuaManager _instance;
public static LuaManager Instance
{
get
{
return _instance;
}
}
[CSharpCallLua]
public delegate void LuaDelegate(string paras);
/// <summary>
/// 定義一個Delegate,Lua結果将傳參回調給該Delegate
/// </summary>
public static LuaDelegate LuaFunc;
/// <summary>
/// 定義一個Lua虛拟機,建議全局唯一
/// </summary>
public static LuaEnv luaEnv;
void Awake()
{
_instance = this;
LuaEnvInit();
}
public void LuaEnvInit()
{
luaEnv = new LuaEnv();
luaEnv.AddLoader(MyLoader);
///lua腳本的主入口
luaEnv.DoString(@"require 'updateInfo'");
//擷取Lua中全局function,然後映射到delegate
luaEnv.Global.Get("LuaFunc", out LuaFunc);
}
private byte[] MyLoader(ref string filepath)
{
string abspath = Application.dataPath + "/Resources/lua/" + filepath + ".lua.txt";
return System.Text.Encoding.UTF8.GetBytes(File.ReadAllText(abspath));
}
}
- 在Unity編寫xLua腳本的注意事項。 運作
2020最後一篇 Unity熱更新執行個體一鏡到底,看這篇就夠了
在執行Generate Code
就OK了。Hotfix Inject In Editor
- 先來個Hello Word!在lua檔案夾中建立名為
hello.lua.txt
xlua.hotfix(CS.XLuaProject.CreateObj,'Start',function(self)
CS.UnityEngine.Debug.Log("Hello word!")
end)
lua腳本更新CreateObj腳本中的
Start
方法輸出"Hello word!"
運作之後不再建立sun的腳本而是輸出Hello Word!
- 熱更新變量
xlua.hotfix(CS.XLuaProject.Rotation,'Start',function(self)
ChangeCode()
end)
function ChangeCode()
CS.XLuaProject.Rotation.speed=100
CS.UnityEngine.Debug.Log(CS.XLuaProject.Rotation.speed)
end
- 增量熱更新加載earth的AB包,建立earth。
- 在xLua源碼中找到util.lua.txt 并copy到Assets\Resources\lua中。
- 建立updateInfo.lua.txt編寫腳本引入util,
local util=require 'util'
local util=require 'util'
util.hotfix_ex(CS.XLuaProject.CreateObj,'Start',function(self)
self.Start(self)
-- lua 函數更新建立地球預制體
CreateEarth(self)
end)
function CreateEarth(self)
self.loadAB:LoadResource("earth", "earth.ab")
local gameObject=self.loadAB:GetGameObject("earth")
local tempObj=CS.UnityEngine.GameObject.Instantiate(gameObject)
tempObj.name="earth"
tempObj.transform.position = CS.UnityEngine.Vector3(-1.7, 0, 0)
end
- 設定腳本中私有通路
xlua.private_accessible(CS.XLuaProject.CreateObj)
- 更新updateInfo.lua.txt完整腳本
local util=require 'util'
util.hotfix_ex(CS.XLuaProject.CreateObj,'Start',function(self)
self.Start(self)
CreateEarth(self)
end)
util.hotfix_ex(CS.XLuaProject.CreateObj,'CreateSun',function(self)
self.CreateSun(self)
local earth=CS.UnityEngine.GameObject.Find("earth")
local sun=CS.UnityEngine.GameObject.Find("sun")
local dd=earth:AddComponent(typeof(CS.XLuaProject.Revolution))
dd.Axis =sun
dd.RotateSpeed = 3
end)
function CreateEarth(self)
self.loadAB:LoadResource("earth", "earth.ab")
local gameObject=self.loadAB:GetGameObject("earth")
local tempObj=CS.UnityEngine.GameObject.Instantiate(gameObject)
tempObj.name="earth"
tempObj.transform.position = CS.UnityEngine.Vector3(-1.7, 0, 0)
end
xlua.hotfix(CS.XLuaProject.Rotation,'Start',function(self)
ChangeCode()
end)
function ChangeCode()
CS.XLuaProject.Rotation.speed=100
CS.UnityEngine.Debug.Log(CS.XLuaProject.Rotation.speed)
end
1.xLua所有的配置都支援三種方式:打标簽;靜态清單;動态清單。此項目使用的是動态清單方式,
是以方法無需在打[LuaCallCSharp]的标簽。
2.關于AssetBundle打包本篇側重點在熱更新,是以忽略了AssetBundle打包的原則。
3.由于項目開發時間較長開發過程中解決一些坑未及時記錄,如果您按照本篇文章做下來出現問題歡迎留言讨論。
4.最後以此文終結2020,終結疫情。