博客 / 詳情

返回

Tuanjie InstantAsset

InstantAsset

InstantAsset 是一套全新的資產解決方案,旨在提升開發者的開發和運行時效率,簡化資產管理流程,特點是支持資產免構建、導入即用、具有更細粒度的內存週期管理和更方便快捷的管理方式。當前僅支持在 Tuanjie 1.7.0及以上版本使用InstantAsset功能。

本文檔可能更新不及時(當前Tuanjie1.7.6),如果版本差距過大,請關注官方文檔:https://docs.unity.cn/cn/tuanjiemanual/Manual/InstantAssetIntro.html.

解決的問題

使用Instant Asset可以解決:

  • 資產構建時間過長
  • 不合理的分包導致運行時冗餘問題
  • 資產生命週期管理問題

未來展望

  • 提供多線程資產加載接口
  • 持續改進InstantAsset中資產的內存管理和加載效率
  • 免構建模式下,擴展資源類型範圍包含腳本類型資產的新增和改動等

Instant Asset 準備工作

資產管理方式

InstantAsset 默認是以文件夾為單位對資產進行管理。每個文件夾對應一個 InstantAssetTable,用於存儲和管理該文件夾內的資產信息, 為了方便開發者使用我們同時也支持用户自定義資產列表分組到同一個InstantAssetTable中。

分組策略

Instant Assets的分組策略參考了 AssetBundle 的設計理念,主要包括以下幾種方式:

  • 邏輯實體分組:根據資產的邏輯關係或功能進行分組,確保相關資產被組織在一起。
  • 類型分組:按照資產的類型(如圖片、音頻、視頻等)進行分類,便於管理和檢索。
  • 併發內容分組:針對需要同時加載或處理的內容進行分組,以優化性能和資源利用率。

處理要求

在實際處理過程中,Instant Asset 要求將屬於同一分組的資產放置在同一個文件夾內,以保證資產按文件夾進行構建並管理


Instant Asset工作流程

要開始使用Instant Asset,要按照以下步驟操作。

切換到支持平台

目前支持Windows、Android、iOS、WebGL和WeixinMiniGame平台。

具體架構和後端參考官方文檔:https://docs.unity.cn/cn/tuanjiemanual/Manual/InstantAsset-Workflow.html

開啓Instant Asset功能

在ProjectSetting/Editor/Instant Player 勾選Instant Asset按鈕。(會提示Restart Editor)

構建Instant Asset

在 Assets 文件夾下創建名為 Editor 的文件夾,在 Editor 文件夾下創建腳本CreateInstantAsset:

using UnityEditor;
using System.IO;

public class CreateInstantAsset
{
    [MenuItem("Assets/Build InstantAsset")]
    static void BuildAllAssetPacker()
    {

        // 設置構建輸出路徑
        string outputPath = Application.streamingAssetsPath;
    
        if (!System.IO.Directory.Exists(outputPath))
        {
            System.IO.Directory.CreateDirectory(outputPath);
        }
        
        // 定義資源別名表
        InstantAssetAliasTable[] aliasTables = new InstantAssetAliasTable[]
        {
            // 資源列表方式指定 示範代碼
            new InstantAssetAliasTable
            {
                aliasTableName = "Prefabs_table",
                assetNames = new string[] 
                { 
                    "Assets/Prefabs/Player.prefab",
                    "Assets/Prefabs/Enemy.prefab",
                    "Assets/Prefabs/TestScene.scene"
                }
            },

            // 目錄方式指定資源 示範代碼
            new InstantAssetAliasTable
            {
                aliasTableName = "Materials_table",
                buildDirectoryPath = "Assets/Materials", // 包含目錄下所有資源
                assetNames = null 
            }
        };
        
        // 設置構建選項
        InstantAssetOptions options = InstantAssetOptions.CompressionLz4HC | 
                                     InstantAssetOptions.ForceRebuild;
        
        // 調用構建方法
        bool success = InstantAssetEditorUtility.BuildAssetPacker(
            outputPath,           // 輸出文件路徑
            aliasTables,          // 資源表
            options,              // 構建選項
            1024,                 // 大小限制
            EditorUserBuildSettings.activeBuildTarget  // 目標平台
        );
        
        if (success)
        {
            Debug.Log("資源包構建成功!文件已保存到: " + outputPath);
        }
        else
        {
            Debug.LogError("資源包構建失敗!");
        }
    }
}

此腳本在團結編輯器的 Assets 菜單底部添加一個名為 Build InstantAsset 的菜單項。點擊該菜單項將觸發關聯函數中的代碼。執行時,腳本會根據 InstantAssetAliasTable 收集所有指定資源,並將它們打包到由 outputPath 定義的文件夾中。每個資源包的大小由 size 參數指定,目標平台由 targetPlatform 參數確定。此外,腳本會在 outputPath 中生成與 aliasTables 數量一致的 InstantAssetTable 文件。如果包含場景文件,還會額外生成一份以所在分組的 InstantAssetTable 名稱後綴加 ‘-scene’ 命名的 InstantAssetTable 文件。

加載 InstantAssetTable 和資源

InstantAssetTable 中包含了特定文件夾下資產及其依賴的信息。用户首先需要通過指定 InstantAssetTable 文件路徑來加載 InstantAssetTable 對象,再利用 InstantAssetTable 加載資產, 如果指定資產中包含了場景文件,會額外生成場景文件的表,命名規則是在指定表名的基礎上加“-scene”, 如果需要加載場景文件則也需要提前加載其場景文件的 InstantAssetTable。
同步的方式加載資源,具體代碼如下所示:

public class LoadInstantAsset : MonoBehaviour
{
    void Start() 
    {
        // 設置資源的根路徑文件夾, 這裏我們假定資源存放在 streamingAssets 目錄下,所以直接設置為Application.streamingAssetsPath
        InstantAsset.SetInstantAssetRootPath(Application.streamingAssetsPath);

        // 加載包含目標資源對應的 InstantAssetTable, 假定我們需要加載名為Prefabs_table的表
        var tablePath = System.IO.Path.Combine(Application.streamingAssetsPath, "Prefabs_table");
        var myLoadedInstantAssetTable = InstantAsset.ReadAssetTable(tablePath) as InstantAssetTable;
        if (myLoadedInstantAssetTable == null) 
        {
            Debug.Log("Failed to load InstantAssetTable");
            return;
        }

        // 同時如果我們需要加載Player.prefab,則需要填入相對路徑,參考如下
        var prefab = myLoadedInstantAssetTable.LoadAsset<GameObject>("Assets/Prefabs/Player.prefab") as GameObject;
        Instantiate(prefab);

        // 卸載資源接口 參考如下
        myLoadedInstantAssetTable.UnloadAsset(prefab);
    }

    void OnDestroy()
    {
       // 卸載資源表 參考如下
       var tablePath = System.IO.Path.Combine(Application.streamingAssetsPath, "Prefabs_table");
       InstantAsset.UnloadAssetTable(tablePath)
    }
}

異步的方式加載資源,代碼如下所示:

public class LoadInstantAsset : MonoBehaviour
{
    IEnumerator Start()
    {
        // 設置資源的根路徑文件夾, 這裏我們假定資源存放在 streamingAssets 目錄下,所以直接設置為Application.streamingAssetsPath
        InstantAsset.SetInstantAssetRootPath(Application.streamingAssetsPath);

        // 加載包含目標資源對應的 InstantAssetTable, 假定我們需要加載名為Prefabs_table的表
        var tablePath = System.IO.Path.Combine(Application.streamingAssetsPath, "Prefabs_table");
        var myLoadedInstantAssetTable = InstantAsset.ReadAssetTable(tablePath) as InstantAssetTable;

        InstantAssetRequest request = myLoadedInstantAssetTable.LoadAssetAsync<GameObject>("Assets/Prefabs/Player.prefab");

        while (!request.isDone)
        {
            Debug.Log("Loading progress: " + request.progress);
            yield return null;
        }

        if (request.asset != null)
        {
            var prefab = request.asset as GameObject;
            if (prefab != null)
            {
                Instantiate(prefab);
            }
        }
    }
}

當前InstantAsset還不支持同步方式加載場景,只能通過異步的方式加載場景資源。此外,場景加載還不支持編輯器模擬,編輯器可以先通過添加場景到Build Setting 的方式臨時測試加載邏輯,具體代碼如下所示:

public class LoadInstantAsset : MonoBehaviour
{
    IEnumerator Start() 
    {
        // 設置資源的根路徑文件夾, 這裏我們假定資源存放在 streamingAssets 目錄下,所以直接設置為Application.streamingAssetsPath
        InstantAsset.SetInstantAssetRootPath(Application.streamingAssetsPath);

        //如果指定目錄或者指定的資源中包含場景資產,會額外生成一個場景表來記錄,命名是用户設置的表名加上"-scene"來區分普通資源表和場景表
        //這裏普通資源表名為 Prefabs_table,則場景表名是:Prefabs_table-scene
        var tablePath = Application.streamingAssetsPath + "/Prefabs_table" + "-scene";
        var myLoadedInstantAssetTable = InstantAsset.ReadAssetTable(tablePath) as InstantAssetTable;

        // 同時如果我們需要加載 Assets/Prefabs/TestScene.scene,則需要填入相對路徑,參考如下
        AsyncOperation sceneOperation = SceneManager.LoadSceneAsync( "Assets/Prefabs/TestScene.scene");

        yield return sceneOperation;
    }
}
user avatar
0 位用戶收藏了這個故事!

發佈 評論

Some HTML is okay.