小言_互联网的博客

unity学习笔记-资源热更新以及代码热更新以及进度条

342人阅读  评论(0)

资源热更新以及代码热更新


注意,我使用的是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
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场