Pack AssetBundle by Table

Currently, all assets in a locale is packed together in a single bundle. But my project will keep growing bigger, and my players won’t need all the assets in a locale right away. So I think there should be a Pack by Table option, this ways we don’t need to download all the assets right from the beginning, the assets are downloaded only when needed.

You can change the way assets are packed by configuring the addressables group rules Addressables Integration | Localization | 1.3.2

You can use SmartString in Locale Group Name Field of Addressable Group Rules, so you can assign each String Tables in different asset group by their properties.

Or you may want to create custom class based on GroupResolver, overriding virtual methods like GetExpectedGroupName(). Then replacing serialized instance of group resolvers from Addressable Group Rules with your custom type.

I’m using custom class created from GroupResolver to separate String Tables for local and remote. Something like this:

[Serializable]
public class JeminGroupResolver : GroupResolver
{
    // some codes....

    [MenuItem("Util/Localization/Update Asset Group Resolvers in Group Rules")]
    public static void UpdateLocalizationAddressableGroupSetting()
    {
        AddressableGroupRules.Instance.AssetResolver = new JeminGroupResolver(AddressableGroupRules.Instance.AssetResolver);
        AddressableGroupRules.Instance.LocaleResolver = new JeminGroupResolver(AddressableGroupRules.Instance.LocaleResolver);
        AddressableGroupRules.Instance.AssetTablesResolver = new JeminGroupResolver(AddressableGroupRules.Instance.AssetTablesResolver);
        AddressableGroupRules.Instance.StringTablesResolver = new JeminGroupResolver(AddressableGroupRules.Instance.StringTablesResolver);
        EditorUtility.SetDirty(AddressableGroupRules.Instance);
    }
  
    public override string GetExpectedGroupName(IList<LocaleIdentifier> locales, Object asset, AddressableAssetSettings aaSettings)
    {
        var expectedGroupName = base.GetExpectedGroupName(locales, asset, aaSettings);
      
        if (IsLocalAdrressableAsset(asset))
        {
            return expectedGroupName + "-Local";
        }

        return expectedGroupName + "-Remote";
    }

    protected override string GetExpectedSharedGroupName(IList<LocaleIdentifier> locales, Object asset, AddressableAssetSettings aaSettings)
    {
        var expectedGroupName = base.GetExpectedSharedGroupName(locales, asset, aaSettings);

        if (IsLocalAdrressableAsset(asset))
        {
            return expectedGroupName + "-Local";
        }

        return expectedGroupName + "-Remote";
    }
}
1 Like

Hi, thanks for the code snippet! However, I am still struggling to find a way to obtain the reference of the table where the asset is in. GetExpectedGroupName only has three parameters, but none of these contains the table reference. How do we get the table reference?

The asset parameter will be a table when it’s asking for the expected group name for a string or asset table. Do a type check on it for StringTable or AssetTable.

I printed out the type of the asset parameter, it seems like its type is never a StringTable nor AssetTable.

8250255--1079562--Screen Shot 2022-07-03 at 4.22.27 PM.png

using System;
using System.Collections.Generic;
using UnityEditor.AddressableAssets.Settings;
using UnityEngine;
using UnityEngine.Localization;
using UnityEngine.Localization.Tables;
using Object = UnityEngine.Object;

namespace UnityEditor.Localization.Addressables
{
    [Serializable]
    public class HiCasinoGroupResolver : GroupResolver
    {
        [MenuItem("JiaHo/Localization/Update Asset Group Resolvers in Group Rules")]
        public static void UpdateLocalizationAddressableGroupSetting()
        {
            AddressableGroupRules.Instance.AssetResolver = new HiCasinoGroupResolver();
            EditorUtility.SetDirty(AddressableGroupRules.Instance);
        }

        public override string GetExpectedGroupName(IList<LocaleIdentifier> locales, Object asset,
            AddressableAssetSettings aaSettings)
        {
            string expectedGroupName = base.GetExpectedGroupName(locales, asset, aaSettings);

            var tableCollections = LocalizationEditorSettings.GetAssetTableCollections();
            for (int i = 0; i < tableCollections.Count; i++)
            {
                var assetTables = tableCollections[i].AssetTables;
                for (int j = 0; j < assetTables.Count; j++)
                {
                    var assetTable = assetTables[j];
                    foreach (var keyValuePair in assetTable)
                    {
                        AssetTableEntry entry = keyValuePair.Value;
                        if (entry.Guid == GetAssetGuid(asset))
                        {
                            Debug.LogFormat("asset.name: {0}, table name: {1}", asset.name, assetTable.TableCollectionName);
                            return $"{expectedGroupName}-{assetTable.TableCollectionName}";
                        }
                    }
                }
            }

            Debug.LogErrorFormat("asset.name: {0}, table not found!", asset.name);
            return expectedGroupName;
        }
     
        private string GetAssetGuid(Object asset)
        {
            if (AssetDatabase.TryGetGUIDAndLocalFileIdentifier(asset, out var guid, out long _))
                return guid;

            Debug.LogError("Failed to extract the asset Guid for " + asset.name, asset);
            return null;
        }
    }
}

Hello everyone, I was able to get what I wanted. But it was very convoluted. I was just going through all the tables to find the table that contained that asset. I think there should be a better way.

You don’t need to iterate through all the tables, you can use the locales field to know which tables to check. It also possible for an asset to be referenced by multiple tables. I’ll see if we can improve the information we provide in the future.

1 Like