1、打AB包
ab包插件:assetbundles-browser-master.zip
1)编辑器修改
将此代码放到Editor文件夹下,不然会报错
using System.Net; using UnityEditor; using System.IO; using System; //-----------------------------【构建AssetBundles资源包】----------------------------- public class BuildAssetBundles { // 菜单选项目录 [MenuItem("Assets/Build AssetBundles")] static public void BuildAllAssetBundles() { // 创建文件目录 string dir = "AssetBundles"; if (!Directory.Exists(dir)) { Directory.CreateDirectory(dir); } // 构建 // 参数1:路径 // 参数2:压缩算法,none 默认 // 参数3:设备参数,ios,Android,windows等等 BuildPipeline.BuildAssetBundles(dir, BuildAssetBundleOptions.None, BuildTarget.StandaloneWindows64); UnityEngine.Debug.Log("AssetBundle资源打包完成!"); } }
然后在Assets菜单下会出现Build AssetBundles,如下:
2)设置
在场景中创建一个sphere,然后制作prefab。在预制体的Inspector面板中修改AssetBundle。
tips:new->输入名称(尽量英文,两个都要改,前一个是名称,后一个是后缀)
3)打包
这时候就完成了ab包打包设置,Assets->Build AssetsBundle即可完成打包,打包后输入文件在Assets文件同级下(先等下吼,因为还有一个文件哈)
ab包里有四个文件
2、服务器配置
使用的netbox服务器
1)下载和安装
nbsetup.rar
按照安装步骤一步步来即可,很快就安好了!!!
2)配置
第一步:在安装好的位置,新建一个文件夹,用做服务器,后续这个文件中的文件可以访问
第二步:在同级文件夹中新建一个txt,并且改名为main.box,然后用记事本打开,复制如下信息进去
Dim httpd Shell.Service.RunService "NBWeb", "NetBox Web Server", "NetBox Http Server Sample" '---------------------- Service Event --------------------- Sub OnServiceStart() Set httpd = NetBox.CreateObject("NetBox.HttpServer") --要加上nexbox,不然报错,找不到对象 If httpd.Create("", 8088) = 0 Then --端口号,注意不能被占用 Set host = httpd.AddHost("", "\root") --这个根据自己的来 host.EnableScript = true host.AddDefault "default.asp" host.AddDefault "default.htm" host.AddDefault "index.asp" host.AddDefault "index.htm" httpd.Start else Shell.Quit 0 end if End Sub Sub OnServiceStop() httpd.Close End Sub Sub OnServicePause() httpd.Stop End Sub Sub OnServiceResume() httpd.Start End Sub
第三步:在统计文件夹中新建一个txt,改成default.asp,内容随意,可以按如下
<html><body>Hello! WEB.<br><%=Now%></body></html>
前三步完成后的文件夹层级
第四步:双击main.box,即可开启服务,通过网址“http://localhost:8088/文件名”的格式,即可访问
开启服务后可以在电脑右下角看到:
开启成功:
3、更新
准备:
下载xlua资源,并且把Tools文件放到unity工程的Assets同级,把Plugins和XLua放到Assets文件夹下,成功后会出现Xlua菜单
unity修改scripting define symbols为HOTFIX_ENBLE,然后回车
1)C#测试脚本
将以下两个脚本都挂载到场景中的空物体上,对应的slider和text绑定到DownLoad上,button添加事件
此脚本,后续会被lua脚本更新,正常写,唯一特殊的要添加using XLua;和在类前边添加[Hotfix],不然会报错
using UnityEngine; using UnityEngine.EventSystems; using XLua; //-----------------------------【游戏脚本】----------------------------- [Hotfix] public class GameScript : MonoBehaviour { public int num1 = 100; private int num2 = 200; void Update() { // 鼠标左键点击 if (Input.GetMouseButtonDown(0)) { if (EventSystem.current.IsPointerOverGameObject()) { Debug.Log("点击到UGUI的UI界面"); } else { //创建 cube (后面会通过热更 lua脚本替换掉这里,使之生成Sphere) GameObject cubeGo = Resources.Load("Cube") as GameObject; // 在鼠标点击的地方实例cube Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition); RaycastHit hit; if (Physics.Raycast(ray, out hit)) { Debug.Log(hit.point); GameObject cube = GameObject.Instantiate(cubeGo, hit.point + new Vector3(0, 1, 0), transform.rotation) as GameObject; } Debug.Log("创建cube实例"); } } } //射线 - 用于xlua调用 避免重载问题 public static bool RayFunction(Ray ray, out RaycastHit hit) { return Physics.Raycast(ray, out hit); } }
下载资源脚本
using System; using System.Collections; using System.Collections.Generic; using UnityEngine; using System.IO; using UnityEngine.Networking; using XLua; using UnityEngine.UI; //-----------------------------【下载资源】----------------------------- public class DownLoad : MonoBehaviour { // private string path = @"file://E:\WorkSpaces\Unity\XLuaFix\AssetBundles\newobj.u3d"; // private string verPath = @"http://localhost/AssetBundles/version.txt"; private string path = @"http://localhost:8088/soyuanicon.unity3d"; public AssetBundle assetBundle; // 开始下载更新 public void StartDownLoad() { Debug.Log("开始下载更新!"); // 启动协程 StartCoroutine(GetAssetBundle(ExcuteHotFix)); } //-----------------------------【从服务器下载热更资源】----------------------------- public Slider slider; public Text progressText;//进度显示 IEnumerator GetAssetBundle(Action callBack) { UnityWebRequest www = UnityWebRequestAssetBundle.GetAssetBundle(path); Debug.Log("path:"+path); www.SendWebRequest(); while (!www.isDone) { Debug.Log(www.downloadProgress); slider.value = www.downloadProgress;//下载进度 progressText.text = Math.Floor(www.downloadProgress * 100) + "%"; yield return 1; } // 下载完成 if (www.isDone) { progressText.text = 100 + "%"; slider.value = 1; // 隐藏UI(等待1s) yield return new WaitForSeconds(1); GameObject.Find("Canvas").SetActive(false); } if (www.isNetworkError || www.isHttpError) { Debug.Log("DownLoad Err: " + www.error); } else { assetBundle = DownloadHandlerAssetBundle.GetContent(www); TextAsset hot = assetBundle.LoadAsset<TextAsset>("luaScript.lua.txt"); Debug.Log("hot.text=" + hot.text); string newPath = Application.persistentDataPath + @"/luaScript.lua.txt"; Debug.Log("new path:"+newPath); if (!File.Exists(newPath)) { // Create后如果不主动释放资源就会被占用,下次打开会报错,所以一定要加上 .Dispose() File.Create(newPath).Dispose(); } // 写入文件 File.WriteAllText(newPath, hot.text); Debug.Log("下载资源成功!new Path : " + newPath); // 下载成功后 读取执行lua脚本 callBack(); } } //-----------------------------【执行热更脚本】----------------------------- public void ExcuteHotFix() { Debug.Log("开始执行热更脚本 luaScript"); LuaEnv luaenv = new LuaEnv(); luaenv.AddLoader(MyLoader); luaenv.DoString("require 'luaScript'"); } // 自定义Loader public byte[] MyLoader(ref string filePath) { // 读取下载的脚本资源 string newPath = Application.persistentDataPath + @"/" + filePath + ".lua.txt"; Debug.Log("执行脚本路径:" + newPath); string txtString = File.ReadAllText(newPath); return System.Text.Encoding.UTF8.GetBytes(txtString); } }
2)Lua测试脚本
注意:这个脚本必须是txt结尾,要和上边的文件名一致(我的上边叫luaScript.lua.txt)
print("Version: 1.5") xlua.private_accessible(CS.GameScript) local unity = CS.UnityEngine --[[ xlua.hotfix(class, [method_name], fix) 描述 : 注入lua补丁 class : C#类,两种表示方法,CS.Namespace.TypeName或者字符串方式"Namespace.TypeName",字符串格式和C#的Type.GetType要求一致,如果是内嵌类型(Nested Type)是非Public类型的话,只能用字符串方式表示"Namespace.TypeName+NestedTypeName"; method_name : 方法名,可选; fix : 如果传了method_name,fix将会是一个function,否则通过table提供一组函数。table的组织按key是method_name,value是function的方式。 --]] -- 替换掉 GameScript 的 Update 方法 xlua.hotfix(CS.GameScript,"Update", function(self) print("lua 开始执行") if unity.Input.GetMouseButtonDown(0) then local go = unity.GameObject.Find("ScriptsManager") --挂载脚本的空物体的名称 --print("获取场景中的物体:"..go) -- 获取assetBundle资源 local ab = go:GetComponent("DownLoad").assetBundle --下载资源的脚本名称 -- 读取创建 Sphere local SphereGo = ab:LoadAsset("Sphere") --打ab包的物体名称 --print("通过ab获取的soyuan:"..SphereGo) --这句有时会报错,注释掉哦 -- 在鼠标点击的位置实例Sphere local ray = unity.Camera.main:ScreenPointToRay (unity.Input.mousePosition) local flag,hit = CS.GameScript.RayFunction(ray) if flag then print(hit.transform.name) local sphere = unity.GameObject.Instantiate(SphereGo) sphere.transform.localPosition = hit.point + unity.Vector3(0,1,0) end end end )
场景中的关系:
3)打ab包
第一步:把lua脚本也和sphere设置同样的AssetBundle名称和后缀,然后一起打包(忘了的话,看第一部分哦)
第二步:把打包的ab包上传到netbox服务器
第三步:回到unity,然后在XLua菜单
按图示顺序执行:
执行完之后即可运行
执行更新前:
执行更新后