ビルドスクリプトの作成
Addressables API を使用してプロジェクトビルドをカスタマイズする方法は、いくつかあります。
- スクリプトからビルドを開始する
- 既存のスクリプトをオーバーライドする
- BuildScriptBase を拡張するか、IDataBuilder を実装する
ビルドスクリプトをカスタマイズして、さまざまなアセットタイプを処理したり、別の方法でアセットを処理したりするときは、[再生モードスクリプト] のカスタマイズが必要になる場合もあります。これをおこなうと、再生モード中にエディターがそれらのアセットを同じ方法で処理できるようになります。
スクリプトからの Addressables ビルドの開始
別のスクリプトから Addressables ビルドを開始するには、AddressableAssetSettings.BuildPlayerContent メソッドを呼び出します。
ビルドを開始する前に、アクティブな [プロファイル] と、アクティブなビルドスクリプトを設定する必要があります。デフォルト以外のオブジェクトを使用する場合は、別の AddressableAssetSettings オブジェクトを設定することもできます。
BuildPlayerContent では、ビルドの実行時にいくつかの情報が考慮されます。これには、AddressableAssetSettingsDefaultObject、ActivePlayerDataBuilder、addressables_content_state.bin
ファイルがあります。
AddressableAssetSettings の設定
AddressableAssetSettings によって定義される設定には、グループのリストや使用するプロファイルがあります。
エディターに表示される設定 (メニュー: Window > Asset Management > Addressables > Settings) にアクセスするには、静的 AddressableAssetSettingsDefaultObject.Settings プロパティを使用します。ただし、必要に応じて別の設定オブジェクトをビルドに使用することもできます。
カスタム設定オブジェクトをビルドにロードするには、以下を実行します。
static void getSettingsObject(string settingsAsset)
{
// This step is optional, you can also use the default settings:
//settings = AddressableAssetSettingsDefaultObject.Settings;
settings
= AssetDatabase.LoadAssetAtPath<ScriptableObject>(settingsAsset)
as AddressableAssetSettings;
if (settings == null)
Debug.LogError($"{settingsAsset} couldn't be found or isn't " +
$"a settings object.");
}
アクティブなプロファイルの設定
BuildContent で開始されるビルドでは、アクティブなプロファイルの変数設定が使用されます。カスタマイズしたビルドスクリプトの一部としてアクティブなプロファイルを設定するには、AddressableAssetSettingsDefaultObject.Settings オブジェクトの activeProfileId フィールドで、使用するプロファイルの ID を指定します。
AddressableAssetSettings オブジェクトには、プロファイルのリストが含まれています。目的のプロファイルの名前を使用して ID 値を検索し、その ID を activeProfileId 変数に割り当てます。
static void setProfile(string profile)
{
string profileId = settings.profileSettings.GetProfileId(profile);
if (String.IsNullOrEmpty(profileId))
Debug.LogWarning($"Couldn't find a profile named, {profile}, " +
$"using current profile instead.");
else
settings.activeProfileId = profileId;
}
アクティブなビルドスクリプトの設定
BuildContent メソッドは、現在の ActivePlayerDataBuilder 設定に基づいてビルドを開始します。特定のビルドスクリプトを使用するには、[ActivePlayerDataBuilderIndex] プロパティに AddressableAssetSetting.DataBuilders リスト内の IDataBuilder オブジェクトのインデックスを指定します。
ビルドスクリプトは、IDataBuilder を実装した ScriptableObject でなければならず、AddressableAssetSettings インスタンスの DataBuilders リストに追加する必要があります。リストに追加したら、標準の List.IndexOf メソッドを使用して、このオブジェクトのインデックスを取得します。
static void setBuilder(IDataBuilder builder)
{
int index = settings.DataBuilders.IndexOf((ScriptableObject)builder);
if (index > 0)
settings.ActivePlayerDataBuilderIndex = index;
else
Debug.LogWarning($"{builder} must be added to the " +
$"DataBuilders list before it can be made " +
$"active. Using last run builder instead.");
}
ビルドの開始
使用するプロファイルとビルダー (必要な場合) を設定したら、ビルドを開始できます。
static bool buildAddressableContent()
{
AddressableAssetSettings
.BuildPlayerContent(out AddressablesPlayerBuildResult result);
bool success = string.IsNullOrEmpty(result.Error);
if (!success)
{
Debug.LogError("Addressables build error encountered: " + result.Error);
}
return success;
}
ビルドの成功を確認するには、BuildPlayerContent(out AddressablesPlayerBuildResult result) を使用します。result.Error には、Addressables ビルドが失敗した場合に返されたエラーメッセージが含まれます。string.IsNullOrEmpty(result.Error) が true の場合は、ビルドが成功しています。
ビルドを開始するスクリプトの例
以下の例では、エディターの Asset Management > Addressables メニューに 2 つのメニューコマンドを追加します。最初のコマンドは、設定済みのプロファイルとビルドスクリプトを使用して Addressable コンテンツをビルドします。2 番目のコマンドは、Addressable コンテンツをビルドし、成功した場合はプレイヤーもビルドします。
ドメインの再ロードが必要となる設定変更を行うビルドスクリプトは、エディターでインタラクティブに実行するのではなく、Unity コマンドラインオプションを使用して実行する必要があります。詳細については、[ドメインの再ロードと Addressable ビルド] を参照してください。
#if UNITY_EDITOR
using UnityEditor;
using UnityEditor.AddressableAssets.Build;
using UnityEditor.AddressableAssets.Settings;
using System;
using UnityEngine;
internal class BuildLauncher
{
public static string build_script
= "Assets/AddressableAssetsData/DataBuilders/BuildScriptPackedMode.asset";
public static string settings_asset
= "Assets/AddressableAssetsData/AddressableAssetSettings.asset";
public static string profile_name = "Default";
private static AddressableAssetSettings settings;
static void getSettingsObject(string settingsAsset)
{
// This step is optional, you can also use the default settings:
//settings = AddressableAssetSettingsDefaultObject.Settings;
settings
= AssetDatabase.LoadAssetAtPath<ScriptableObject>(settingsAsset)
as AddressableAssetSettings;
if (settings == null)
Debug.LogError($"{settingsAsset} couldn't be found or isn't " +
$"a settings object.");
}
static void setProfile(string profile)
{
string profileId = settings.profileSettings.GetProfileId(profile);
if (String.IsNullOrEmpty(profileId))
Debug.LogWarning($"Couldn't find a profile named, {profile}, " +
$"using current profile instead.");
else
settings.activeProfileId = profileId;
}
static void setBuilder(IDataBuilder builder)
{
int index = settings.DataBuilders.IndexOf((ScriptableObject)builder);
if (index > 0)
settings.ActivePlayerDataBuilderIndex = index;
else
Debug.LogWarning($"{builder} must be added to the " +
$"DataBuilders list before it can be made " +
$"active. Using last run builder instead.");
}
static bool buildAddressableContent()
{
AddressableAssetSettings
.BuildPlayerContent(out AddressablesPlayerBuildResult result);
bool success = string.IsNullOrEmpty(result.Error);
if (!success)
{
Debug.LogError("Addressables build error encountered: " + result.Error);
}
return success;
}
[MenuItem("Window/Asset Management/Addressables/Build Addressables only")]
public static bool BuildAddressables()
{
getSettingsObject(settings_asset);
setProfile(profile_name);
IDataBuilder builderScript
= AssetDatabase.LoadAssetAtPath<ScriptableObject>(build_script) as IDataBuilder;
if (builderScript == null)
{
Debug.LogError(build_script + " couldn't be found or isn't a build script.");
return false;
}
setBuilder(builderScript);
return buildAddressableContent();
}
[MenuItem("Window/Asset Management/Addressables/Build Addressables and Player")]
public static void BuildAddressablesAndPlayer()
{
bool contentBuildSucceeded = BuildAddressables();
if (contentBuildSucceeded)
{
var options = new BuildPlayerOptions();
BuildPlayerOptions playerSettings
= BuildPlayerWindow.DefaultBuildMethods.GetBuildPlayerOptions(options);
BuildPipeline.BuildPlayer(playerSettings);
}
}
}
#endif
ドメインの再ロードと Addressables ビルド
ビルドプロセスのスクリプトに変更設定が含まれ、Addressables ビルドの作成前にドメインの再ロードをトリガーする場合、そのようなビルドスクリプトは、エディターでインタラクティブに実行するのではなく、[Unity のコマンドライン引数] を使用するように作成される必要があります。これには、以下のようなタイプの設定が含まれます。
- 定義済みのコンパイラーシンボルの変更
- プラットフォームターゲットまたはターゲットグループの変更
ドメインの再ロードをトリガーするスクリプトを、エディターでインタラクティブに (例えばメニューコマンドを使用して) 実行すると、ドメインの再ロードが発生する前にエディターでのスクリプトの実行が終了します。このため、Addressables ビルドをすぐに開始しても、コードもインポートされたアセットも元の状態のままです。コンテンツビルドを開始する前に、ドメインの再ロードが完了するまで待つ必要があります。
ドメインの再ロードが終了するまで待つ処理は、コマンドラインからビルドを実行する場合は比較的単純ですが、対話形式のスクリプトで確実に実現するのは (さまざまな理由から) 困難または不可能である場合があります。
以下のスクリプト例では、コマンドラインでの Unity の実行時に呼び出すことができる 2 つの関数を定義しています。ChangeSettings
の例では、指定した定義シンボルを設定します。BuildContentAndPlayer
関数は、Addressables ビルドとプレイヤービルドを実行します。
#if UNITY_EDITOR
using System;
using UnityEditor;
using UnityEditor.AddressableAssets;
using UnityEditor.AddressableAssets.Build;
using UnityEditor.AddressableAssets.Settings;
using UnityEditor.Build.Reporting;
using UnityEngine;
internal class BatchBuild
{
public static string build_script
= "Assets/AddressableAssetsData/DataBuilders/BuildScriptPackedMode.asset";
public static string profile_name = "Default";
public static void ChangeSettings()
{
string defines = "";
string[] args = Environment.GetCommandLineArgs();
foreach (var arg in args)
if (arg.StartsWith("-defines=", System.StringComparison.CurrentCulture))
defines = arg.Substring(("-defines=".Length));
var buildSettings = EditorUserBuildSettings.selectedBuildTargetGroup;
PlayerSettings.SetScriptingDefineSymbolsForGroup(buildSettings, defines);
}
public static void BuildContentAndPlayer()
{
AddressableAssetSettings settings
= AddressableAssetSettingsDefaultObject.Settings;
settings.activeProfileId
= settings.profileSettings.GetProfileId(profile_name);
IDataBuilder builder
= AssetDatabase.LoadAssetAtPath<ScriptableObject>(build_script) as IDataBuilder;
settings.ActivePlayerDataBuilderIndex
= settings.DataBuilders.IndexOf((ScriptableObject)builder);
AddressableAssetSettings.BuildPlayerContent(out AddressablesPlayerBuildResult result);
if (!string.IsNullOrEmpty(result.Error))
throw new Exception(result.Error);
BuildReport buildReport
= BuildPipeline.BuildPlayer(EditorBuildSettings.scenes,
"d:/build/winApp.exe", EditorUserBuildSettings.activeBuildTarget,
BuildOptions.None);
if (buildReport.summary.result != BuildResult.Succeeded)
throw new Exception(buildReport.summary.ToString());
}
}
#endif
これらの関数を呼び出すには、端末、コマンドライン、またはシェルスクリプトで [Unity のコマンドライン引数] を使用します。
D:\Unity\2020.3.0f1\Editor\Unity.exe -quit -batchMode -projectPath . -executeMethod BatchBuild.ChangeSettings -defines=FOO;BAR -buildTarget Android
D:\Unity\2020.3.0f1\Editor\Unity.exe -quit -batchMode -projectPath . -executeMethod BatchBuild.BuildContentAndPlayer -buildTarget Android
Note
プラットフォームターゲットをコマンドラインパラメーターとして指定すると、同じコマンドで Addressables ビルドを実行できます。ただし、スクリプト内でプラットフォームを変更する場合は、この例の ChangeSettings
関数など、別のコマンドで変更する必要があります。
カスタムビルドスクリプトの作成
新しいカスタムスクリプトを設定するには、それを [ビルドスクリプトと再生モードのスクリプト] のリストに追加します。
カスタムスクリプトでは、BuildScriptBase クラスを拡張するか、IDataBuilder インターフェースを実装します。ClearCachedData
や CanBuildData<T>
など、いくつかのオーバーライドメソッドがあります。BuildScriptBase クラスを拡張する場合、最も注目すべきオーバーライドのためのメソッドは BuildDataImplementation<TResult>
です。これが、コンテンツの設定またはビルドに使用されるメソッドです。
カスタムスクリプトは、ビルドスクリプトまたは再生モードスクリプトです。これは、CanBuildData<T>
メソッドの実装方法によって決まります。ビルドスクリプトでビルドできるのは AddressablesPlayerBuildResult
型のデータだけなので、このメソッドは以下のように実装されます。
public override bool CanBuildData<T>()
{
return typeof(T).IsAssignableFrom(typeof(AddressablesPlayerBuildResult));
}
これにより、スクリプトが Build/New Build/ メニューに表示されます。
再生モードスクリプトでビルドできるのは AddressablesPlayModeBuildResult
型のデータだけなので、このメソッドは以下のように実装されます。
public override bool CanBuildData<T>()
{
return typeof(T).IsAssignableFrom(typeof(AddressablesPlayModeBuildResult));
}
これにより、スクリプトが Play Mode Scripts メニューに表示されます。
例については、[カスタムのビルドスクリプトと再生モードスクリプトのサンプル] を参照してください。
デフォルトビルドスクリプトの拡張
デフォルトのビルドスクリプト BuildScriptPackedMode と同じ基本ビルドを使用しながら、特定のグループやタイプのアセットを別の方法で処理する場合は、デフォルトのビルドスクリプトを拡張し、その中の関数をオーバーライドすることができます。ビルドスクリプトが処理しているグループやアセットを別の方法で処理する場合は、独自のコードを実行できます。それ以外の場合は、基本クラスの関数を呼び出してデフォルトのアルゴリズムを使用できます。
例については、[Addressable バリアントプロジェクト] を参照してください。
コンテンツ状態の保存
[コンテンツのリモート配布] をサポートし、プレイヤーリリース間でコンテンツを更新する場合は、ビルド時の Addressables グループの状態を記録する必要があります。状態を記録すると、Update a Previous Build スクリプトを使用して差分ビルドを実行することができます。
詳細については、BuildScriptPackedMode および ContentUpdateScript の実装を参照してください。