游戏资源打包

作者:追风剑情 发布于:2019-7-4 13:36 分类:Unity3d

[官方文档] AssetBundles
[官方文档] BuildPipeline
[官方文档] BuildOptions

导资源工具 (Unity 2019)

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

/// <summary>
/// 资源工具
/// 放到Assets/Editor文件夹下
/// </summary>
public class AssetsToolEditor : Editor
{
    [MenuItem("Assets/Build/Build Model")]
    public static void BuildModelItem()
    {
        string export_folder = Application.streamingAssetsPath + "/models";
        Object[] objects = Selection.objects;
        for (int i = 0; i < objects.Length; i++)
            BuildModel(export_folder, objects[i]);
    }

    [MenuItem("Assets/Build/Build Texture")]
    public static void BuildTextureItem()
    {
        string export_folder = Application.streamingAssetsPath + "/textures";
        Object[] objects = Selection.objects;
        for (int i = 0; i < objects.Length; i++)
            BuildTexture(export_folder, objects[i]);
    }

    [MenuItem("Assets/Build/Build Prefab")]
    public static void BuildPrefabItem()
    {
        string export_folder = Application.streamingAssetsPath + "/prefabs";
        Object[] objects = Selection.objects;
        for (int i = 0; i < objects.Length; i++)
            BuildPrefab(export_folder, objects[i]);
    }

    [MenuItem("Assets/Build/Build Scriptable")]
    public static void BuildScriptableItem()
    {
        string export_folder = Application.streamingAssetsPath + "/assets";
        Object[] objects = Selection.objects;
        for (int i = 0; i < objects.Length; i++)
            BuildScriptableObject(export_folder, objects[i]);
    }

    [MenuItem("Assets/Build/Build SpriteAtlas")]
    public static void BuildSpriteAtlasItem()
    {
        string export_folder = Application.streamingAssetsPath + "/atlas";
        Object[] objects = Selection.objects;
        for (int i = 0; i < objects.Length; i++)
            BuildSpriteAtlas(export_folder, objects[i]);
    }

    [MenuItem("Assets/Build/Build TextAsset")]
    public static void BuildTextAssetItem()
    {
        string export_folder = Application.streamingAssetsPath + "/text";
        Object[] objects = Selection.objects;
        for (int i = 0; i < objects.Length; i++)
            BuildTextAsset(export_folder, objects[i]);
    }

    [MenuItem("Assets/Build/Build Lua")]
    public static void BuildLuaTextAssetItem()
    {
        string export_folder = Application.streamingAssetsPath + "/lua";
        Object[] objects = Selection.objects;
        BuildLuaTextAsset(export_folder, objects);
    }

    [MenuItem("Assets/Build/Build Scene")]
    public static void BuildSceneItem()
    {
        string export_folder = Application.streamingAssetsPath + "/scene";
        Object[] objects = Selection.objects;
        BuildSceneAsset(export_folder, objects);
    }

    // Build Model
    public static void BuildModel(string export_folder, Object asset)
    {
        BuildAsset(export_folder, asset, "model");
    }

    // Build Texture
    public static void BuildTexture(string export_folder, Object asset)
    {
        BuildAsset(export_folder, asset, "tex");
    }

    // Build Prefab
    public static void BuildPrefab(string export_folder, Object asset)
    {
        BuildAsset(export_folder, asset, "prefab");
    }

    // Build ScriptableObject
    public static void BuildScriptableObject(string export_folder, Object asset)
    {
        string[] assetNames = AssetDatabase.GetDependencies(AssetDatabase.GetAssetPath(asset));
        string[] assetNames1 = new string[assetNames.Length - 1];
        int j = 0;
        for (int i = 0; i < assetNames.Length; i++)
            //删除依赖资源中的同名脚本,否则打包会报错。
            //报错信息: Script asset "Assets/XXX/XXXX/XXXX.cs" cannot be included into AssetBundle "XXX".
            if (!assetNames[i].EndsWith(asset.name + ".cs"))
                assetNames1[j++] = assetNames[i];

        BuildAsset(export_folder, asset, "asset", assetNames1);
    }

    // Build SpriteAtlas
    public static void BuildSpriteAtlas(string export_folder, Object asset)
    {
        BuildAsset(export_folder, asset, "atlas");
    }

    // Build TextAsset
    public static void BuildTextAsset(string export_folder, Object asset)
    {
        asset.name = TrimPostfix(asset.name);
        BuildAsset(export_folder, asset, "txt");
    }

    // Build Lua File
    public static void BuildLuaTextAsset(string export_folder, Object[] assets)
    {
        BuildAsset(export_folder, assets, "app", "lua");
    }

    // Build Scene
    public static void BuildSceneAsset(string export_folder, Object[] assets)
    {
        string[] scenes = new string[assets.Length];
        for (int i = 0; i < assets.Length; i++)
            scenes[i] = AssetDatabase.GetAssetPath(assets[i]);
        BuildScene(export_folder, scenes);
    }

    // 去掉文件名后缀
    public static string TrimPostfix(string name)
    {
        if (string.IsNullOrEmpty(name))
            return name;
        int index = name.IndexOf('.');
        if (index == -1)
            return name;
        return name.Substring(0, index);
    }

    // 设置资源的AssetBundle信息
    public static void SetAssetBundleNameAndVariant(Object asset, string bundle_name, string bundle_variant)
    {
        AssetImporter importer = AssetImporter.GetAtPath(AssetDatabase.GetAssetPath(asset));
        if (importer == null)
            return;
        importer.SetAssetBundleNameAndVariant(bundle_name, bundle_variant);
    }

    // 将单个资源打成一个包
    public static void BuildAsset(string export_folder, Object asset, string variant, string[] assetNames = null)
    {
        string bundleName = TrimPostfix(asset.name);
        Object[] assets = new Object[] { asset };
        BuildAsset(export_folder, assets, bundleName, variant);
    }

    // 将一组资源打成一个包
    public static void BuildAsset(string export_folder, Object[] assets, string bundleName, string variant)
    {
        if (!Directory.Exists(export_folder))
        {
            Directory.CreateDirectory(export_folder);
            AssetDatabase.Refresh(ImportAssetOptions.ForceUpdate);
        }

        List<string> assetNames = new List<string>();
        List<string> addressableNames = new List<string>();
        for (int i=0; i<assets.Length; i++)
        {
            Object asset = assets[i];
            string assetName = AssetDatabase.GetAssetPath(assets[i]);
            string addressableName = Path.GetFileNameWithoutExtension(assetName);
            assetNames.Add(assetName);
            addressableNames.Add(addressableName);

            SetAssetBundleNameAndVariant(asset, TrimPostfix(asset.name), variant);
        }

        AssetBundleBuild abb = new AssetBundleBuild();
        abb.assetBundleName = bundleName;
        abb.assetBundleVariant = variant;
        //要打包到当前AB包中的资源path
        //加载: bundle.LoadAsset(assetNames[0]);
        abb.assetNames = assetNames.ToArray();
        //为AB中每个资源设置昵称,方便加载
        //加载:bundle.LoadAsset(addressableNames[0]);
        abb.addressableNames = addressableNames.ToArray();

        BuildAssetBundleOptions options = BuildAssetBundleOptions.ChunkBasedCompression | BuildAssetBundleOptions.DeterministicAssetBundle;
        BuildPipeline.BuildAssetBundles(export_folder, new AssetBundleBuild[] { abb }, options, EditorUserBuildSettings.activeBuildTarget);
        AssetDatabase.Refresh(ImportAssetOptions.ForceUpdate);

        Debug.LogFormat("{0}/{1}.{2}", export_folder, abb.assetBundleName, abb.assetBundleVariant);

        DeleteManifest(export_folder, abb.assetBundleName, abb.assetBundleVariant);
    }

    // 删除生成的manifest文件
    public static void DeleteManifest(string export_folder, string assetBundleName, string assetBundleVariant)
    {
        export_folder = export_folder.Substring(export_folder.LastIndexOf("/Assets/") + 1);
        AssetDatabase.DeleteAsset(string.Format("{0}/{1}.{2}.manifest", export_folder, assetBundleName.ToLower(), assetBundleVariant));
        string folder_name = export_folder.Substring(export_folder.LastIndexOf("/") + 1);
        AssetDatabase.DeleteAsset(string.Format("{0}/{1}.manifest", export_folder, folder_name));
        AssetDatabase.DeleteAsset(string.Format("{0}/{1}", export_folder, folder_name));

        AssetDatabase.Refresh(ImportAssetOptions.ForceUpdate);
    }

    // 打包多个场景
    public static void BuildScene(string export_folder, string[] scenes)
    {
        if (!Directory.Exists(export_folder))
        {
            Directory.CreateDirectory(export_folder);
            AssetDatabase.Refresh(ImportAssetOptions.ForceUpdate);
        }

        foreach (string scene in scenes)
            BuildScene(export_folder, scene);
        AssetDatabase.Refresh(ImportAssetOptions.ForceUpdate);
    }

    // 打包单个场景
    private static void BuildScene(string export_folder, string scene)
    {
        string assetName = Path.GetFileNameWithoutExtension(scene);
        string locationPathName = string.Format("{0}/{1}.scene", export_folder, assetName);
        BuildPlayerOptions option = new BuildPlayerOptions();
        //例如 ["Assets/Scenes/Sample.unity",...]
        option.scenes = new string[] { scene };
        option.locationPathName = locationPathName;
        option.target = EditorUserBuildSettings.activeBuildTarget;
        option.options = BuildOptions.BuildAdditionalStreamedScenes;
        BuildPipeline.BuildPlayer(option);

        Debug.Log(locationPathName);
    }
}
11111.png


加载场景AssetBundle

标签: Unity3d

Powered by emlog  蜀ICP备18021003号-1   sitemap

川公网安备 51019002001593号