注意,我使用的是2018版,如果是2019及以上的, lua的更新还需要多一步
可以看这个视频里的最后的部分
https://www.bilibili.com/video/BV1DK4y1Q7gR?p=9&spm_id_from=pageDriver
资源热更新
流程
首先需要打包ab(assetsbundles,后面都简称),打包的内容上一篇有写
然后放到服务器上
这里用的是教学中的本地服务器。netbox2进行的模拟,网上直接下就好了
这个服务器的用法是,在服务器程序的同级文件夹中放入你的ab包和lua代码就可以了,然后在unity 中访问下载资源和代码即可
如图
创建好之后打开exe文件这个服务器就算打开成功了
然后资源的内容就完成了
lua代码热更新
流程
在项目发布之前需要一些准备工作
首先是在项目打开的第一个场景中从服务器上下载最新的lua代码,这里可以做一个简单的判断,如果内容不变的话就不下载,教程里是没有这一步的,不过我估计项目大的话是需要这一步的
下载完成之后就跳转到下一个场景,在下一个场景中的c#代码里写入读取lua的方法,让场景在进入的时候就能加载最新的资源和代码
逻辑相对简单,但实现的时候会有很多问题
首先是需要学一点lua语法,lua和c#不同, 有的内容需要不同的语法和格式才能识别到,还有bug,信息太少不知道从何下手等等
实现
在你的の第一个场景前创建一个新场景,用于从云端下载最新的lua文件
using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.UI;
using UnityEngine.SceneManagement;
public class LoadLua : MonoBehaviour
{
// Start is called before the first frame update
void Start()
{
StartCoroutine(Load());
}
IEnumerator Load()
{
UnityWebRequest request = UnityWebRequest.Get(@"http://localhost/HotFix.lua.txt");
yield return request.SendWebRequest();
string s = request.downloadHandler.text;
File.WriteAllText(Application.streamingAssetsPath+ "/LuaScripts/HotFix.lua.txt", s);
SceneManager.LoadScene("HotFixTest");
}
// Update is called once per frame
void Update()
{
}
}
代码如上
请求里的地址需要使用你自己的链接,我没有真的服务器,这里就模拟本地了
然后这个场景的任务就完成了~如果需要大佬们还可以加点进度条啥的,这个我还没看所以就没做了,以后有时间康康
然后就是在真正的第一个场景里添加代码
首先是创建一个中间类,用于lua里调用热更新的类(这里的原因视频里是说我们的代码因为有协程的参与,而使用携程的话是无法将方法设置为静态的,因此只能通过在别的类里实例化热更新的类,从而才能调用到我们需要的热更新(public)的方法)
这个代码简单
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using XLua;
[Hotfix]
public class Load : MonoBehaviour
{
public HotFixScripts hot;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
}
}
不过有一些需要注意的地方,首先是添加xlua的引用
其次是新建一个public 热更新类的命名
我这里叫做hotfixscripts,名字随意~
还有下面的start和update,我的建议是不要删掉,视频里也没有删,不过没有特意说明,我是因为后面再视频里看到up主的lua代码里将调用热更新类方法的代码写在了这个类的start和update里,想着如果删掉了可能会有问题,不过话说这些类本身就自带了这两个方法,不知道删掉会不会真的有问题,没测试过,后面有时间再整,反正也就多了这几行(又扯远了)
然后才是正式的编写调用lua的方法
c#调用lua的方法上上篇里面有讲~这里就不多赘述
只有一个不同, 就是我们的资源是在服务器上的,所以需要访问服务器上的数据才行,用到的方法是unitywebrequestassetsbundle
具体代码如下
using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.UI;
using XLua;
[Hotfix]
public class HotFixScripts : MonoBehaviour
{
// Start is called before the first frame update
private LuaEnv le;
private Dictionary<string, GameObject> asDics = new Dictionary<string, GameObject>();
void Start()
{
le = new LuaEnv();
le.AddLoader(myLoader);
le.DoString("require 'HotFix'");
}
// Update is called once per frame
void Update()
{
}
public byte[] myLoader(ref string filePath)
{
Debug.Log(filePath);
string path = Application.streamingAssetsPath+"/LuaScripts/" + filePath + ".lua.txt";
return System.Text.Encoding.UTF8.GetBytes(File.ReadAllText(path));
}
[LuaCallCSharp]
public void LoadRes(string resName, string fileName)
{
StartCoroutine(Load(resName, fileName));
}
IEnumerator Load(string resName, string fileName)
{
//AssetBundle test = AssetBundle.LoadFromFile(Application.streamingAssetsPath+"/test");
UnityWebRequest request = UnityWebRequestAssetBundle.GetAssetBundle(@"http://localhost/AssetBundles/PC/"+fileName);
yield return request.SendWebRequest();
AssetBundle ab = (request.downloadHandler as DownloadHandlerAssetBundle).assetBundle;
GameObject obj = ab.LoadAsset<GameObject>(resName);
asDics.Add(resName, obj);
print(resName);
}
[LuaCallCSharp]
public GameObject GetPrefabs(string resName)
{
return asDics[resName];
}
}
和前面一样,需要lua就要添加引用,需要让lua调用和修改代码就要在方法前添加[LuaCallCSharp]
然后把load类和热更新类都挂载到场景中的相机上即可
这里需要注意,从这两天研究xlua来看,xlua只能帮助我们在项目不是大更新的情况下实现热更新,比如修改贴图,添加一些新素材等,如果要添加一些新的内容,如新的系统啥的,我觉得是不太科学的,最好还是让用户下客户端比较实际
最后就是lua代码的编写
lua语法网上有很多,我也是萌新就不写了,看了视频和网上其他大佬的帖子,用了一些比较常用的方法
local UnityEngine = CS.UnityEngine
xlua.hotfix(CS.Load,'Start',function(self)
self.hot:LoadRes('Sphere','test')
end)
xlua.hotfix(CS.Load,'Update',function(self)
if(UnityEngine.Input.GetKeyDown(UnityEngine.KeyCode.U)) then
UnityEngine.GameObject.Instantiate(self.hot:GetPrefabs('Sphere'));
end
end)
local就是声明一个变量,供后面的代码使用
xlua.方法名()就是使用xlua自己的方法
后面记得加上end作为结尾
里面的hot就是Load这个类里声明的热更新的类
通过load实例化热更新的类,然后调用和修改热更新自己的方法
这里需要注意的几点
第一个就是在xlua里使用c#的方法和属性的话,需要写完成他们是在哪里来的,比如input这个类的话就是在CS.UnityEngine下的,都是需要写完成的,否则识别不了
到这里热更新的功能基本就实现了~可能思路还是会不太清晰,因为只学了两天,还没有很熟练的掌握,后面有机会的话再写详细一点或者录个频啥的吧
加油~
进度条
方法
AsyncOperation里的allowSceneActivation,以及协程里的WaitForEndOfFrame
AsyncOperation async = SceneManager.LoadSceneAsync("HotFixTest");//这里填写你下一个场景的名称
async.allowSceneActivation = false;
while (i<=100)
{
i++;
progress.GetComponent<Slider>().value = i/100;
yield return new WaitForEndOfFrame();
}
yield return new WaitForSeconds(1f);
async.allowSceneActivation = true;
注意,这个方法不能直接获得访问链接的进度,是我们自己写的进度~
转载:https://blog.csdn.net/pure81/article/details/116202081