打包AssetBundle上传服务器,并用lua进行更新

只记录学习,这些类和操作比较繁琐,一定要仔细,一定要仔细,一定要仔细!!!

既然是要打包,那这里写一个类打包,这个类比较特殊,熟练运用后,可以写插件。

这个脚本需要放在Assets下建一个Editor文件里面

引入命名空间:using UnityEditor;

和文件留的命名空间:using System.IO;

这里会创建一个文件夹streamingAssets,将打包后的文件都放在这个文件夹下面

using UnityEditor;
using System.IO;

public class TextEditor : Editor
{
    //写插件
    [MenuItem("NewItem/Cube")]
    public static void Create()
    {
        
        //资源打包
        string path=Application.streamingAssetsPath;
        if (!Directory.Exists(path)) 
        {
            Directory.CreateDirectory(path);//创建streamingAssets文件夹
        }
        //打包
        BuildPipeline.BuildAssetBundles(path, 
        BuildAssetBundleOptions.ChunkBasedCompression, BuildTarget.StandaloneWindows64);
    }
}

这个脚本不需要挂载   会出现在工具栏中每次打包  都需要重新执行

这里创建了一个文件  并给上了包名,你所有要打包的东西这里都要给上包名,这里我只截下一个,在原脚本那种还有一个球的预制体也打包了

加载文件有3中方法

public class TestAB : MonoBehaviour
{
    string path=Application.streamingAssetsPath+"/qiu";//qiu:打包后的预设文件
    void Start()
    {
        StartCoroutine(LoadFromMemory(path));//1
        LoadFile();//2
        StartCoroutine(LoadFromServer());//3
    }
    //1.重内存中异步加载
    IEnumerator LoadFromMemory(string name)
    {
        AssetBundleCreateRequest request = AssetBundle.LoadFromMemoryAsync(File.ReadAllBytes(name));//打包后的预设
        yield return request;
        AssetBundle ab=request.assetBundle;
        GameObject go = ab.LoadAsset<GameObject>("qiu");//qiu 原文件
        Instantiate(go);
        ab.Unload(false);//卸载资源和资源包

    }
    //2.从本地加载
    void LoadFile()
    {
        AssetBundle ab = AssetBundle.LoadFromFile(Path.Combine(Application.streamingAssetsPath, "qiu"));//打包后的预设
        GameObject qiu= ab.LoadAsset<GameObject>("qiu");//qiu 原文件
        Instantiate(qiu);
        ab.Unload(false);//卸载资源和资源包
    }
    //3.重服务器上加载
    IEnumerator LoadFromServer()
    {
        string path = "file:///" + Application.streamingAssetsPath + "/qiu";//打包后的预设
        UnityWebRequest request=UnityWebRequestAssetBundle.GetAssetBundle(path);
        yield return request.SendWebRequest();
        AssetBundle ab = DownloadHandlerAssetBundle.GetContent(request);
        GameObject qiu = ab.LoadAsset<GameObject>("qiu");//qiu 原文件
        Instantiate(qiu);
        ab.Unload(false);//卸载资源和资源包
    }
    void Update()
    {
        
    }
}

这里还有一个方法可以找出对应的文件 他的所有一栏关系文件

public class TestAB : MonoBehaviour
{
    string path=Application.streamingAssetsPath+"/qiu";//qiu:打包后的预设文件
    //加载配置文件
    void LoadManifest()
    {
        AssetBundle ab = AssetBundle.LoadFromFile(Application.streamingAssetsPath + "/StreamingAssets");
        AssetBundleManifest abm = ab.LoadAsset<AssetBundleManifest>("AssetBundleManifest");
        string[] s = abm.GetAllDependencies("qiu");//qiu 材质包的名字  找出他所有的依赖关系
        foreach (var item in s)
        {
            print(item);
        }
        ab.Unload(false);//卸载资源和资源包
    }
}

 下面就是把打包后的文件上传服务器,因为这里我是记录学习我在这里建立一个Server作为服务器,Client作为客户端

我们需要把打包后的文件手动复制一份到Server文件下面

下面我们将用代码将文件上传到客户端,并用热更新实现更新

using UnityEngine.Networking;
using System.IO;

public class DownLoad : MonoBehaviour
{
   public AssetBundle ab;
    void Start()
    {
        StartCoroutine(Load());
    }
    //从服务器上加载文件到客户端
    IEnumerator Load()
    {
        string path = "file:///" + Application.dataPath + "/Server/qiu";//Server 服务器端
        UnityWebRequest request= UnityWebRequestAssetBundle.GetAssetBundle(path);
        yield return request.SendWebRequest();
        ab = DownloadHandlerAssetBundle.GetContent(request);
        TextAsset ta = ab.LoadAsset<TextAsset>("qiu.lua.txt");//配置文件
        string newPath = Application.dataPath + "/Client/qiu.lua.txt";//Client 客户端
        File.WriteAllText(newPath, ta.text);
    }
   

}

接下来是热更新,需要注意的是这里不是Lua文件而是txt文件

首先写一个允许热更新的类  挂载在摄像机上

using XLua;

[Hotfix]
public class Test : MonoBehaviour
{
    private GameObject cube;
    void Start()
    {
        cube = Resources.Load<GameObject>("Cube");
    }

    void Update()
    {
        if(Input.GetMouseButtonDown(0))
        {
            Instantiate(cube);
        }
    }
}

写一个热更新文件

这里通过代码去获取摄像机上的脚本  

通过脚本去获取客户端上的ab包,去对类进行热更新

engine=CS.UnityEngine
xlua.hotfix(CS.Test,'Update',
         function(self)
                   if engine.Input.GetMouseButtonDown(0) then
                             camera=engine.GameObject.Find('Main Camera')
                             download=camera:GetComponent('DownLoad')
                             ab=download.ab
                             qiu=ab:LoadAsset('qiu')
                             engine.GameObject.Instantiate(qiu)
                    end
           end
)

下面是一个打开和关闭文件的类,单独写成一个类,方便后面调用(当然,如果你只是实验打包操作,只要调用一次,就可以不用)这个类写成单例,以后需要打开文件可以直接调用这个类的方法,就不用每次去写打开和关闭文件操作了(这也算一个简单的框架,方便调用)

需要注意的是,你的文件后缀名,有多个不同的后缀名时,协程多个方法即可

using System.IO;
using XLua;

public class XLuaManager
{
    //调用lua文件的简单框架
    //单例
    private XLuaManager() { }
    private static XLuaManager instance=null;
    public static XLuaManager Instance
    {
        get
        {
            if(instance == null)
            {
                instance = new XLuaManager();
                Init();
            }
            return instance;
        }
    }
    public static LuaEnv lua;
    static void Init()//初始化lua文件
    {
        lua=new LuaEnv();
        lua.AddLoader(FileLoader);
    }
    static byte[] FileLoader(ref string fileName)
    {
        string path = Application.dataPath + "/Lua/" + fileName + ".lua.txt";
        return File.ReadAllBytes(path);
    }
    public void Dostring(string str)
    {
        lua.DoString(str);
    }
    public void Dispose()//释放资源
    {
        lua.Dispose();
    }
}

现在是实现热更新的最后一步,调用文件

public class TestLua : MonoBehaviour
{
    
    void Start()
    {
        XLuaManager.Instance.Dostring("require('qiu')");
    }
}

这里就实现了框架的好处,当你需要打开文件时,只需要调用方法,将你需要打开的文件名作为参数传进去即可。

猜你喜欢

转载自blog.csdn.net/Optimistic_lx/article/details/129956675
今日推荐