使用Unity Editor打包 AssetBundle

Unity Editor扩展

最近在看热更新和编辑器扩展,于是想着就把打包AssetBundle的过程在Editor里面进行实现。

背景描述:

AssetBundle的打包,之前是需要进行自己输入代码进行打包的。虽然可以放到Editor里进行一件执行,但是涉及到较多的文件时,还是需要将路径一个一个敲进代码里。

要实现的功能:

当涉及较多的Asset需要打包时,就只需要通过打开文件夹的方式选中就可以了。将代码部分取消掉。

实现思路:

根据Unity给的API可以知道大概的思路

  1. 我们需要的数据:AssetBundle名、AssetBundle要存储的路径、还有每个Asset名(相对路径)
  2. 数据怎么存储:AssetBundle名和AssetBundle要存储的路径比较简单,可以作为一个全局变量进行调用。每个Asset的存储就稍微麻烦一点了,主要涉及到每个Asset的存储和删除。开始时使用的是字符串数组,但是做了很多无用功之后,发现,只是使用字符串数据是存在几个比较大的缺陷:(1)怎么将每个Asset的信息和浏览的功能绑定在一起(2)删除的功能,如果使用数组,那么需要将额外的实现。
  3. 最终方案:最后觉得还是觉得使用泛型List比较好(还想过使用链表,不过还没实现)。对于每个Asset信息的存取和删除,想着还是将它们集成到一个类里面会比较方便,所以声明一个Element类进行信息的存取和删除
    下面是源码:
public class Element
{
    public int ID;
    public string path = "";
    string root = "Assets";
    public bool isActive = true;

    public Element()
    { }


    public void TextFieldElement()
    {
        GUILayout.BeginHorizontal();
        GUILayout.Space(30);
        path = EditorGUILayout.TextField("资源:", path, GUILayout.Width(324));
        path = ReferenceButton();
        DestoryButton();
        GUILayout.EndHorizontal();
    }

    /// 
    /// 单击按钮获取相对路径
    /// 
    /// 
    public string ReferenceButton()
    {
        if (GUILayout.Button("浏览", GUILayout.Width(65)))
        {
            path = EditorUtility.OpenFilePanel("选取资源", "", "*");
        }
        if (path != "" && path != null)
        {
            int index = path.LastIndexOf(root);
            path = path.Substring(index);
        }
        return path;
    }

    public void DestoryButton()
    {
        if (GUILayout.Button("删除", GUILayout.Width(65)))
        {
            isActive = false;
            Debug.Log(isActive);
        }
    }

}

下面是编辑器部分的代码:

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

public class BuildAssetBundles : EditorWindow
{

    Vector2 scrollPos;
    static int _abElementsCount;
    string root = "Assets";
    static string _sourcePath;
    static string _AssetBundleName;
    static string[] _abElementsPath;
    List textCom = new List();


    #region InitialEditor
    [MenuItem("Tools/BuildAssetBundle")]
    private static void InitializeEditor()
    {
        GetWindow();
        _abElementsCount = 0;
        _sourcePath = "";
    }
    #endregion



    private void Update()
    {
        if (textCom.Count != 0)
        {
            for (int i = 0; i < textCom.Count; i++)
            {
                if (textCom[i].isActive == false)
                {
                    textCom.Remove(textCom[i]);
                    _abElementsCount--;
                }
            }
        }
    }

    private void OnGUI()
    {

        scrollPos = EditorGUILayout.BeginScrollView(scrollPos);
        //资源包名称
        _AssetBundleName = AssetBundleName(_AssetBundleName);
        //资源包路径
        _sourcePath = AssetBundlePath(_sourcePath);
        //资源包容量
        _abElementsCount = UpdateElementsCount(_abElementsCount);

        if (textCom.Count != 0)
        {
            foreach (var item in textCom)
            {
                item.TextFieldElement();
            }
        }


        #region 使用List
        if (GUILayout.Button("添加", GUILayout.Width(200)))
        {
            Element temp = new Element();
            textCom.Add(temp);
            _abElementsCount++;
        }
        #endregion





        //打包资源
        if (GUILayout.Button("打包", GUILayout.Width(200)))
        {
            _abElementsPath = new string[textCom.Count];
            for (int i = 0; i < textCom.Count; i++)
            {
                _abElementsPath[i] = textCom[i].path;
            }
            PackAssetBundles();
            ShowNotification(new GUIContent("打包完成"));
        }

        //显示信息
        if (GUILayout.Button("显示信息", GUILayout.Width(200)))
        {
            for (int i = 0; i < _abElementsPath.Length; i++)
            {
                Debug.Log(i + ":" + _abElementsPath[i]);
            }
        }
        EditorGUILayout.EndScrollView();
    }





    //资源包命名
    private string AssetBundleName(string assetBundleName)
    {
        GUILayout.BeginHorizontal();
        assetBundleName = EditorGUILayout.TextField("资源包名称:", assetBundleName, GUILayout.Width(350));
        if (GUILayout.Button("清空", GUILayout.Width(65)))
        {

            assetBundleName = "";
            //EditorUtility.FocusProjectWindow();
        }
        GUILayout.EndHorizontal();
        return assetBundleName;
    }

    private string AssetBundlePath(string assetBundlePath)
    {
        GUILayout.BeginHorizontal();
        assetBundlePath = EditorGUILayout.TextField("资源包路径:", assetBundlePath, GUILayout.Width(350));
        if (GUILayout.Button("浏览", GUILayout.Width(65)))
        {
            assetBundlePath = EditorUtility.OpenFolderPanel("选择文件夹", "Assets/", "");
        }
        if (assetBundlePath != "" && assetBundlePath != null)
        {
            int index = assetBundlePath.LastIndexOf(root);
            assetBundlePath = assetBundlePath.Substring(index);
        }
        GUILayout.EndHorizontal();
        return assetBundlePath;
    }

    private int UpdateElementsCount(int assetElementCount)
    {
        GUILayout.BeginHorizontal();
        EditorGUILayout.LabelField(new GUIContent("资源包容量:"), GUILayout.Width(145));
        GUILayout.Label(_abElementsCount.ToString(), GUILayout.Width(100));
        GUILayout.EndHorizontal();
        return assetElementCount;
    }





    public void PackAssetBundles()
    {
        AssetBundleBuild[] build = new AssetBundleBuild[1];
        build[0].assetBundleName = _AssetBundleName;
        build[0].assetNames = _abElementsPath;
        BuildPipeline.BuildAssetBundles(_sourcePath, build, BuildAssetBundleOptions.None, BuildTarget.StandaloneWindows64);
    }

}





效果图:

使用Unity Editor打包 AssetBundle_第1张图片

注意:这个脚本必须放在Editor文件夹下面,否则会报错无法进行BuildAssetBundles;

你可能感兴趣的:(学习)