Unity组件开发--AB包打包工具

发布时间:2024年01月10日

1.项目工程路径下创建文件夹:ABundles

2.AB包打包脚本:

using System.Collections.Generic;
using System.IO;
using UnityEditor;
using UnityEditor.SceneManagement;
using UnityEngine;
using UnityEngine.SceneManagement;

public class AssetBundlePackage {


    static string[] GetBuildScenes() {
        List<string> sceneArray = new List<string>();
        foreach (EditorBuildSettingsScene e in EditorBuildSettings.scenes) {
            if (e == null) continue;
            if (e.enabled) sceneArray.Add(e.path);
        }
        return sceneArray.ToArray();
    }


    [MenuItem("BuildScene/Build")]
    public static void BuildScene() {
        //BundleAssetsBundle_Webgl();

        string folderPath = EditorUtility.OpenFolderPanel("Select Folder", "", "");
        Debug.Log("Selected Folder: " + folderPath);

        BuildPipeline.BuildPlayer(new string[] { "Assets/GameStart.unity" }, folderPath, BuildTarget.WebGL, BuildOptions.AutoRunPlayer);
    }

    [MenuItem("BuildScene/BuildForMobile")]
    public static void BuildSceneForMobile()
    {
        //BundleAssetsBundle_Webgl();

        string folderPath = EditorUtility.OpenFolderPanel("Select Folder", "", "");
        Debug.Log("Selected Folder: " + folderPath);

        BuildPipeline.BuildPlayer(new string[] { "Assets/GameStartMoibile.unity" }, folderPath, BuildTarget.WebGL, BuildOptions.AutoRunPlayer);
    }

    [MenuItem("SceneAsset/BuildCurrent")]
    public static void BuildCurrentScene() {
        string rootPath = Application.dataPath.ToLower().Replace("assets", "") + "ABundles/webgl/scenes";
        string scenePath = EditorSceneManager.GetActiveScene().path;
        string sceneName = System.IO.Path.GetFileNameWithoutExtension(scenePath).ToLower();

        AssetBundleBuild assetBundleBuild = new AssetBundleBuild();
        assetBundleBuild.assetNames = new []{ scenePath };
        assetBundleBuild.assetBundleName = sceneName + ".bundle";
        BuildPipeline.BuildAssetBundles(rootPath, new AssetBundleBuild[] { assetBundleBuild}, BuildAssetBundleOptions.None, BuildTarget.WebGL);
    }

    [MenuItem("SceneAsset/BuildAllScene")]
    public static void BuildAllScene() {
        bool isOk = EditorUtility.DisplayDialog("确认框", "是否将所有场景打成AB包", "确认", "取消");
        if (!isOk) {
            return;
        }

        //AB包路径是ABundles
        string rootPath = Application.dataPath.ToLower().Replace("assets","") + "ABundles/webgl/scenes";
        var allScenesPath = GetBuildScenes();
        foreach (var scenePath in allScenesPath) {
            string sceneName = System.IO.Path.GetFileNameWithoutExtension(scenePath).ToLower();
            AssetBundleBuild assetBundleBuild = new AssetBundleBuild();
            assetBundleBuild.assetNames = new[] { scenePath };
            assetBundleBuild.assetBundleName = sceneName + ".bundle";
            Debug.Log(sceneName + scenePath);
            BuildPipeline.BuildAssetBundles(rootPath, new AssetBundleBuild[] { assetBundleBuild }, BuildAssetBundleOptions.None, BuildTarget.WebGL);
        }
    }


    [MenuItem("AssetBundle/BuildWebGL")]
    public static void BundleAssetsBundle_Webgl() {
        Debug.Log("BundleAssetsBundle WebGL");
        BuildAllAssetBundles();
    }
    private static void BuildAssetsBundle(BuildTarget target) {
        //string packagePath = Application.streamingAssetsPath;
        //if (packagePath.Length <= 0 && !Directory.Exists(packagePath))
        //{
        //    return;
        //}
        //BuildPipeline.BuildAssetBundles(packagePath, BuildAssetBundleOptions.UncompressedAssetBundle, target);
    }
    //Asset/BundleAsset/Prefab/Com/a.bundle  Prefab/Com/a
    public static string RemovePrefix(string inputString) {
        inputString = inputString.Replace("\\", "/");
        string prefix = "Assets/BundleAsset/";
        string result = inputString.Replace(prefix, "");
        return result.Replace(".bundle", "");
    }
    static void BuildAllAssetBundles() {
        string prefabsFolderPath = "Assets/BundleAsset/Prefab";

        if (!Directory.Exists(prefabsFolderPath)) {
            Debug.LogError($"Folder {prefabsFolderPath} does not exist!");
            return;
        }

        //AB包路径是ABundles
        string rootPath = Application.dataPath.ToLower().Replace("assets", "") + "ABundles/webgl";
        if (!Directory.Exists(rootPath)) {
            Debug.LogError($"Folder {rootPath} does not exist!");
            return;
        }

        string[] prefabGUIDs = AssetDatabase.FindAssets("t:Prefab", new[] { prefabsFolderPath });
        foreach (var prefabGUID in prefabGUIDs) {
            string prefabPath = AssetDatabase.GUIDToAssetPath(prefabGUID);
            GameObject prefab = AssetDatabase.LoadAssetAtPath<GameObject>(prefabPath);
            if (prefab == null) {
                continue;
            }
            var assetPath = AssetDatabase.GetAssetPath(prefab);
            var dependencies = GetAllDependencies(assetPath).ToArray();

            var withoutEx = Path.GetFileNameWithoutExtension(prefabPath);

            AssetBundleBuild assetBundleBuild = new AssetBundleBuild();
            assetBundleBuild.assetBundleName = RemovePrefix(withoutEx).ToLower() + ".bundle";
            assetBundleBuild.assetNames = dependencies;
            var directName = Path.GetDirectoryName(assetPath);
            var outPackagePath = $"{rootPath}/{RemovePrefix(directName).ToLower()}";

            Debug.Log($"prefabPath {prefabPath}");
            if (!Directory.Exists(outPackagePath)) {
                Directory.CreateDirectory(outPackagePath);
            }

            BuildPipeline.BuildAssetBundles(outPackagePath, new AssetBundleBuild[] { assetBundleBuild }, BuildAssetBundleOptions.None, BuildTarget.WebGL);
        }

        Debug.Log("BuildAssetBundles ok");
    }

    public static List<string> GetAllDependencies(string assetPath) {
        var list = new List<string>();
        var dependencies = AssetDatabase.GetDependencies(assetPath, false);
        foreach (var dependency in dependencies) {
            if (Path.GetExtension(dependency) == ".cs" || Path.GetExtension(dependency) == ".meta" || Path.GetExtension(dependency) == ".DS_Store") {
                continue;
            }
            list.Add(dependency);
        }
        list.Add(assetPath);
        return list;
    }


}

3.需要打包的场景添加到打包配置:

4.unity编辑器生成菜单:

5.场景加载AB包管理器:

using Cysharp.Threading.Tasks;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using UnityEngine;
using UnityEngine.SceneManagement;
using System.IO;
using UnityEngine.Networking;
using GLTFast;
using LitJson;
using System.Web;

public class SceneLoader : MonoBehaviour {
    
    public int TemplateId;

    public bool useBundle;

    public bool isDeBug;

    public bool isShowCase;

    public bool isMobileTest;

    [Header("天空盒材质球")]
    public UnityEngine.Material skyboxMaterial;

    bool sceneIsLoaded = false;
    [DllImport("__Internal")]
    private static extern string GetUA();

    public virtual void Awake() {

#if !UNITY_EDITOR && UNITY_WEBGL
          string a = GetUA();
          if (a == "1")
            {
                //PC端
                Debug.Log("当前运行环境在PC端");
                PlayerData.Instance.isRunningPC = true;
            }
            if (a == "2")
            {
                //移动端
                Debug.Log("当前运行环境在移动端");
                PlayerData.Instance.isRunningPC = false;
            }
#endif



#if UNITY_EDITOR

        AppConst.UseAssetBundle = useBundle;

#endif

        AppConst.useShowBundlePath = isShowCase;

        DontDestroyOnLoad(gameObject);
        EventManager.Instance.AddListener(EventName.LoadSceneAction, OnSceneLoad);
        EventManager.Instance.AddListener(EventName.OnSceneCfgLoadEnd, RemoveUnuse);



    }

    public virtual void Start() {

        var fps = transform.Find("FPS");
        if (fps) {
            fps.gameObject.SetActive(isDeBug);
        }

        if (isMobileTest) LoadNetCofig();



    }


    void LoadNetCofig() {
        var configPath = Application.dataPath;

#if UNITY_EDITOR
        var filepath = Path.Combine(Application.dataPath.Replace("Assets", ""), "config.txt");
#else
        var filepath = Path.Combine(Application.dataPath, "config.txt");
#endif
        Debug.Log("configPath" + filepath);
        filepath = filepath.Replace("\\", "/");
        StartCoroutine(LoadFileSetNetwork(filepath));
    }

    IEnumerator LoadFileSetNetwork(string filepath) {
        UnityWebRequest www = UnityWebRequest.Get(filepath);


        yield return www.SendWebRequest();


        if (www.result == UnityWebRequest.Result.ConnectionError || www.result == UnityWebRequest.Result.ProtocolError) {
            Debug.LogError(www.error);
        }
        else {
            string json = www.downloadHandler.text;
            var data = LitJson.JsonMapper.ToObject(json);

            if ((string)data["AssetBundleIP"] != string.Empty) {
                Host.AssetBundleIP = (string)data["AssetBundleIP"];
            }
            Host.gameServer = (string)data["local"];
            Host.ApiHost = (string)data["ApiHost"];
            Host.remote = (string)data["remote"];

            Debug.Log("url config:" + json);
            StartCoroutine(tempLoad());

        }
    }

    public IEnumerator tempLoad() {
        Debug.Log("OnBaelogin" + TemplateId);
        var SceneName = TemplateId.ToString();
#if UNITY_EDITOR
        if (AppConst.UseAssetBundle) {
            yield return AssetBundleManager.Instance.LoadSceneSync(SceneName);
        }
        else {
            yield return SceneManager.LoadSceneAsync(SceneName);
        }
#else
        yield return AssetBundleManager.Instance.LoadSceneSync(SceneName);
#endif

        EventManager.Instance.TriggerEvent(EventName.OnSceneLoaded);
        UIManager.Instance.PushPanel(UIPanelType.MAIN_PANEL); //这里有个坑, 如果把界面放在场景加载之前添加,会出现各种错误乱象
        UIManager.Instance.PushPanel(UIPanelType.HUD_PANEL);
        Debug.Log("DownLoadScenConfig");
        if (HttpHelper.Instance != null) {
            HttpHelper.Instance.GetDefaultSpaceImg();
            HttpHelper.Instance.DownLoadScenConfig();
        }
    }


    private void RemoveUnuse(object sender, EventArgs e) {
        RemoveSceneUnUseDefault();

        ResetSkyBox();
    }


    public void ResetSkyBox() {
        JsonData sceneJson = JsonMapper.ToObject(SceneModel.Instance.sceneJsonInitData);
        if (sceneJson["skyBox"] != null) {

            string imgdata = sceneJson["skyBox"]["body"].ToString();
            string decodedString = HttpUtility.UrlDecode(JsonMapper.ToObject(imgdata)["imgDatas"].ToString());
            StartCoroutine(LoadTexturesAndGenerateCubemap(JsonMapper.ToObject<List<skyImgData>>(decodedString)));
        }

    }

    private IEnumerator LoadTexturesAndGenerateCubemap(List<skyImgData> skyImgDataList) {
        Texture2D[] textures = new Texture2D[skyImgDataList.Count];
        Cubemap cubemap;

        for (int i = 0; i < skyImgDataList.Count; i++) {
            using (UnityWebRequest www = UnityWebRequestTexture.GetTexture(skyImgDataList[i].url)) {
                yield return www.SendWebRequest();

                if (www.result == UnityWebRequest.Result.Success) {
                    Texture2D texture = DownloadHandlerTexture.GetContent(www);
                    textures[i] = texture;
                }
                else {
                    Debug.LogError("Failed to load image: " + www.error);
                    yield break;
                }
            }
        }

        Material material = new Material(skyboxMaterial);

        material.SetTexture("_FrontTex", textures[0]);
        material.SetTexture("_BackTex", textures[1]);
        material.SetTexture("_LeftTex", textures[2]);
        material.SetTexture("_RightTex", textures[3]);
        material.SetTexture("_UpTex", textures[4]);
        material.SetTexture("_DownTex", textures[5]);

        RenderSettings.skybox = material;

    }



    /// <summary>
    /// 移除场景默认设置的那些被删除的板
    /// </summary>
    public void RemoveSceneUnUseDefault() {
        var comVOs = SceneModel.Instance.rootCfg.comCfg.comVOs;
        var scene = SceneManager.GetActiveScene();
        GameObject[] roots = scene.GetRootGameObjects();
        foreach (GameObject root in roots) {
            var loaders = root.GetComponentsInChildren<ComLoader>();
            foreach (var loader in loaders) {
                if (comVOs.TryGetValue(loader.instanceName, out _) == false) {
                    StartCoroutine(waitSeconds(loader.gameObject));
                }
            }
        }
    }

    IEnumerator waitSeconds(GameObject go) {
        yield return new WaitForEndOfFrame();
        GameObject.Destroy(go);
    }






    IEnumerator coLoadSceneAsync() {

        if (PlayerData.Instance.isRunningPC == false) {
            yield return new WaitForSeconds(1f);
        }

#if UNITY_EDITOR
        if (SceneModel.Instance.useGlb == false) {
            PlayerData.Instance.TemplateId = TemplateId;
        }
#endif
        var SceneName = "";

        if (SceneModel.Instance.useGlb == true) {
            SceneName = "1000";
        }
        else {
            if (PlayerData.Instance.isRunningPC) {
                SceneName = PlayerData.Instance.TemplateId.ToString();
            }
            else {
                SceneName = PlayerData.Instance.TemplateId.ToString() + "_mobile";
            }
        }

        Debug.Log("SceneName TemplateId:" + SceneName);
#if UNITY_EDITOR
        if (AppConst.UseAssetBundle) {
            yield return AssetBundleManager.Instance.LoadSceneSync(SceneName);
        }
        else {
            yield return SceneManager.LoadSceneAsync(SceneName);
        }

#else
        yield return AssetBundleManager.Instance.LoadSceneSync(SceneName);
#endif

    }

    /// <summary>
    /// 发布态场景加载完成
    /// </summary>
    /// <param name="arg0"></param>
    /// <param name="arg1"></param>
    private void OnPublishModeSceneLoadSuccess(Scene arg0, LoadSceneMode arg1) {
        UIManager.Instance.PushPanel(UIPanelType.EDITOR_MODE_PANEL);
        UIManager.Instance.PushPanel(UIPanelType.HUD_PANEL);
        EventManager.Instance.TriggerEvent(EventName.OnSceneLoaded);
        HttpHelper.Instance.GetDefaultSpaceImg();
        SceneModel.Instance.setDefaultSceneConfig();

        if (PlayerController.Instance.gameObject.GetComponent<RoleInfoUICtr>()) {
            PlayerController.Instance.gameObject.GetComponent<RoleInfoUICtr>().publicModeForName();
            PlayerController.Instance.gameObject.GetComponent<RoleInfoUICtr>().isShowOwnerObj(true);
        }

        if (SceneModel.Instance.useGlb) {
            EventManager.Instance.TriggerEvent(EventName.onGlbSceneLoad, new GlbLoadEvenArg { url = SceneModel.Instance.glbPath });
        }
    }

    public void OnSceneLoad(object sender, EventArgs e) {

        if (sceneIsLoaded == true) {
            return;
        }
        sceneIsLoaded = true;
        var arg = e as SceneLoadActionArgs;
        Debug.Log("OnSceneLoad:" + arg.state);
        if (arg.state == AppConst.PublicMode) //创建态
        {
            SceneManager.sceneLoaded += OnPublishModeSceneLoadSuccess;
        }
        else { //浏览态

            SceneManager.sceneLoaded += OnViewSceneLoadOk;
        }
        StartCoroutine(coLoadSceneAsync());
    }



    /// <summary>
    /// 浏览态场景加载完成
    /// </summary>
    /// <param name="arg0"></param>
    /// <param name="arg1"></param>
    private void OnViewSceneLoadOk(Scene arg0, LoadSceneMode arg1) {
        EventManager.Instance.TriggerEvent(EventName.OnSceneLoaded);
        if (PlayerData.Instance.isRunningPC == true) {
            UIManager.Instance.PushPanel(UIPanelType.HUD_PANEL);
        }
        //ToastPanel.Show("OnViewSceneLoadOk");
        //AlertPanel.Show("OnViewSceneLoadOk", null);
        //Debug.Log("DownLoadScenConfig");
        //if (HttpHelper.Instance != null)
        //{
        //    HttpHelper.Instance.GetDefaultSpaceImg();
        //    //HttpHelper.Instance.DownLoadScenConfig(); //挪到登陆的时候请求场景数据
        //}


        if (SceneModel.Instance.useGlb) {
            EventManager.Instance.TriggerEvent(EventName.onGlbSceneLoad, new GlbLoadEvenArg { url = SceneModel.Instance.glbPath });
        }


        if (PlayerData.Instance.isRunningPC) {
            SceneModel.Instance.ImplementComLoder();
            UIManager.Instance.PushPanel(UIPanelType.MAIN_PANEL);

        }
        else {
            if (SceneModel.Instance.useGlb) {

                EventManager.Instance.AddListener(EventName.onGlbSceneLoadOK, (s, e) => {

                    StartCoroutine(waitSeconds(1, () => {
                        UIManager.Instance.PushPanel(UIPanelType.MAIN_PANEL);
                    }));

                });

                StartCoroutine(waitSeconds(1, () => {

                    if (SceneModel.Instance.useGlb) {
                        EventManager.Instance.TriggerEvent(EventName.onGlbSceneLoad, new GlbLoadEvenArg { url = SceneModel.Instance.glbPath });
                    }
                }));
            }
            else {

                StartCoroutine(waitSeconds(1, () => {
                    UIManager.Instance.PushPanel(UIPanelType.MAIN_PANEL);
                }));

            }


        }
    }

    private IEnumerator waitSeconds(float scecond, Action call) {
        yield return new WaitForSeconds(scecond);
        call();


    }

    public virtual void Onlogin() {



    }

}

文章来源:https://blog.csdn.net/woshiyuyanjia/article/details/135505098
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。