Unity 中资源包的使用

Unity 有许多有用的功能,其中之一是对资源包的支持。

什么是资产包?

资源包是包含游戏资源的文件,从 3D 模型、纹理和音频剪辑等简单资源到场景和预制件等更复杂的资源

但是,脚本不能包含在资源包中,只能包含它们的引用,因此重命名或移动它们时要小心,因为这会中断连接,并且您需要重建资源包才能使它们再次工作。

何时使用资源包?

当您的游戏拥有大量资源并且将它们包含在构建中会影响初始下载时间时,请使用资源包。

导出资源包

导出资源包分两步完成:分配资源包名称并使用编辑器脚本构建它们。

分配资源包名称

要指定资源包名称,请在项目视图中选择资源(可以是预制件、纹理,甚至场景),然后在最底部的检查器视图中单击下拉菜单,然后单击 'New...' (或单击现有资源包名称)。

为多个资源分配相同的包名称会将它们打包在同一个资源包中。建议将场景与其他资源分开打包。

此外,您不必为每个资源分配资源包名称。通常,您只需将捆绑包名称分配给主预制件或资产,其余依赖项将自动包含在内。

构建资产包

要构建资源包,请按照以下步骤操作:

  • 创建一个名为 Editor 的新文件夹(如果没有)
  • 在 Editor 文件夹中创建一个新脚本,将其命名为 BuildAssetBundles,然后将以下代码粘贴到其中:

BuildAssetBundles.cs

using UnityEngine;
using UnityEditor;

public class BuildAssetBundles
{
    [MenuItem("Build/Build AssetBundles")]
    static void BuildAllAssetBundles()
    {
        string outputFolder = "Assets/__Bundles";

        //Check if __Bundles folder exist
        if (!AssetDatabase.IsValidFolder(outputFolder))
        {
            Debug.Log("Folder '__Bundles' does not exist, creating new folder");

            AssetDatabase.CreateFolder("Assets", "__Bundles");
        }

        BuildPipeline.BuildAssetBundles(outputFolder, BuildAssetBundleOptions.ChunkBasedCompression, EditorUserBuildSettings.activeBuildTarget);
    }
}

保存后,您会注意到它将添加一个菜单按钮(Build -> Build AssetBundles)。单击它将构建资源包并将它们放置在 "__Bundles" 文件夹中。

加载资源包

要加载资源包,首先需要使用 UnityWebRequest 下载,然后使用特殊函数解压。一般来说,资源包有两种类型:包含资源的资源包和包含场景的资源包。

从资源包加载资源

下面的代码下载名为 "fpsplayer" 的资源包,然后提取名为 "FPSPlayer" 的预制件并在场景中实例化它:

        int assetBundleVersion = 1; // Changing this number will force Asset Bundle reload
        string assetBundlePath = "file://" + Application.dataPath + "/__Bundles/" + "fpsplayer"; // Path to Asset Bundle file
        using (UnityEngine.Networking.UnityWebRequest www = UnityEngine.Networking.UnityWebRequestAssetBundle.GetAssetBundle(assetBundlePath, (uint)assetBundleVersion, 0))
        {
            yield return www.SendWebRequest();

            if (www.isNetworkError || www.isHttpError)
            {
                Debug.LogError("AssetBundle Error: " + www.error);
                yield return null;
            }
            else
            {
                // Get downloaded Asset Bundle
                AssetBundle assetBundle = UnityEngine.Networking.DownloadHandlerAssetBundle.GetContent(www);
                // Extract Prefab named "FPSPlayer" from the Asset Bundle
                GameObject playerPrefab = assetBundle.LoadAsset("FPSPlayer") as GameObject;
                // Instantiate Player Prefab
                Instantiate(playerPrefab, Vector3.zero, Quaternion.identity);
                // Unload Asset Bundle from memory (but do not destroy the existing instance(s))
                assetBundle.Unload(false);
            }
        }

从资源包加载场景

从资源包加载场景的方式略有不同。

下面的代码将下载带有场景的资源包并使其可供加载:

        int assetBundleVersion = 1; // Changing this number will force Asset Bundle reload
        string assetBundlePath = "file://" + Application.dataPath + "/__Bundles/" + "testscene"; // Path to Asset Bundle file
        using (UnityEngine.Networking.UnityWebRequest www = UnityEngine.Networking.UnityWebRequestAssetBundle.GetAssetBundle(assetBundlePath, (uint)assetBundleVersion, 0))
        {
            yield return www.SendWebRequest();

            if (www.isNetworkError || www.isHttpError)
            {
                Debug.LogError("AssetBundle Error: " + www.error);
                yield return null;
            }
            else
            {
                // Get downloaded Asset Bundle (This will make the Scene available for load)
                AssetBundle assetBundle = UnityEngine.Networking.DownloadHandlerAssetBundle.GetContent(www);
                // Load the Scene extracted from the Asset Bundle
                UnityEngine.SceneManagement.SceneManager.LoadScene("TestScene");
            }
        }