156 lines
6.4 KiB
C#
156 lines
6.4 KiB
C#
#if UNITY_EDITOR
|
|
using System.IO;
|
|
using UnityEditor;
|
|
using UnityEditor.AddressableAssets;
|
|
using UnityEditor.AddressableAssets.Build;
|
|
using UnityEditor.AddressableAssets.Settings;
|
|
using UnityEditor.AddressableAssets.Settings.GroupSchemas;
|
|
using UnityEngine;
|
|
|
|
public static class OtaAddressablesSetup
|
|
{
|
|
const string RemoteLoadUrl = "https://kkapi.playpoolstudios.com/ota/[BuildTarget]";
|
|
const string GameContentLabel = "game-content";
|
|
const string BootstrapScenePath = "Assets/Scenes/Bootstrap.unity";
|
|
|
|
static readonly string[] RemoteScenePaths =
|
|
{
|
|
"Assets/Scenes/Intro.unity",
|
|
"Assets/Scenes/MainMenu.unity",
|
|
"Assets/Scenes/Game.unity"
|
|
};
|
|
|
|
[MenuItem("Tools/OTA/Configure Addressables")]
|
|
public static void Configure()
|
|
{
|
|
AddressableAssetSettings settings = AddressableAssetSettingsDefaultObject.GetSettings(true);
|
|
settings.BuildRemoteCatalog = true;
|
|
settings.DisableCatalogUpdateOnStartup = true;
|
|
settings.OverridePlayerVersion = "";
|
|
|
|
string profileId = settings.activeProfileId;
|
|
settings.profileSettings.SetValue(profileId, AddressableAssetSettings.kRemoteBuildPath, "ServerData/[BuildTarget]");
|
|
settings.profileSettings.SetValue(profileId, AddressableAssetSettings.kRemoteLoadPath, RemoteLoadUrl);
|
|
settings.RemoteCatalogBuildPath.SetVariableByName(settings, AddressableAssetSettings.kRemoteBuildPath);
|
|
settings.RemoteCatalogLoadPath.SetVariableByName(settings, AddressableAssetSettings.kRemoteLoadPath);
|
|
|
|
for (int i = 0; i < settings.DataBuilders.Count; i++)
|
|
{
|
|
if (settings.GetDataBuilder(i) != null && settings.GetDataBuilder(i).Name.Contains("Asset Database"))
|
|
{
|
|
settings.ActivePlayModeDataBuilderIndex = i;
|
|
break;
|
|
}
|
|
}
|
|
|
|
AddressableAssetGroup local = GetOrCreateGroup(settings, "Local_Bootstrap");
|
|
AddressableAssetGroup remote = GetOrCreateGroup(settings, "Remote_Game");
|
|
ConfigureGroup(settings, local, true);
|
|
ConfigureGroup(settings, remote, false);
|
|
|
|
MarkScene(settings, local, BootstrapScenePath, "Bootstrap", false);
|
|
for (int i = 0; i < RemoteScenePaths.Length; i++)
|
|
{
|
|
string path = RemoteScenePaths[i];
|
|
string address = Path.GetFileNameWithoutExtension(path);
|
|
MarkScene(settings, remote, path, address, true);
|
|
}
|
|
|
|
settings.SetDirty(AddressableAssetSettings.ModificationEvent.BatchModification, null, true, true);
|
|
AssetDatabase.SaveAssets();
|
|
|
|
var scenes = new EditorBuildSettingsScene[1];
|
|
scenes[0] = new EditorBuildSettingsScene(BootstrapScenePath, true);
|
|
EditorBuildSettings.scenes = scenes;
|
|
Debug.Log("OTA Addressables configured. Remote load path: " + RemoteLoadUrl);
|
|
}
|
|
|
|
[MenuItem("Tools/OTA/Build Content")]
|
|
public static void BuildContent()
|
|
{
|
|
Configure();
|
|
AddressableAssetSettings.BuildPlayerContent(out AddressablesPlayerBuildResult result);
|
|
if (!string.IsNullOrEmpty(result.Error))
|
|
{
|
|
Debug.LogError("OTA content build failed: " + result.Error);
|
|
return;
|
|
}
|
|
|
|
string statePath = ContentUpdateScript.GetContentStateDataPath(false);
|
|
Debug.Log("OTA content build finished. Keep this file for later patches: " + statePath);
|
|
}
|
|
|
|
[MenuItem("Tools/OTA/Build Content Update")]
|
|
public static void BuildContentUpdate()
|
|
{
|
|
AddressableAssetSettings settings = AddressableAssetSettingsDefaultObject.Settings;
|
|
if (settings == null)
|
|
{
|
|
Debug.LogError("Addressables settings are missing. Run Tools/OTA/Configure Addressables first.");
|
|
return;
|
|
}
|
|
|
|
string statePath = ContentUpdateScript.GetContentStateDataPath(false);
|
|
if (!File.Exists(statePath))
|
|
{
|
|
Debug.LogError("Missing content state at " + statePath + ". Run Tools/OTA/Build Content from the player build you shipped.");
|
|
return;
|
|
}
|
|
|
|
ContentUpdateScript.BuildContentUpdate(settings, statePath);
|
|
Debug.Log("OTA content update built. Upload ServerData and keep " + statePath);
|
|
}
|
|
|
|
static AddressableAssetGroup GetOrCreateGroup(AddressableAssetSettings settings, string name)
|
|
{
|
|
AddressableAssetGroup group = settings.FindGroup(name);
|
|
if (group != null)
|
|
return group;
|
|
|
|
return settings.CreateGroup(name, false, false, false, null, typeof(BundledAssetGroupSchema), typeof(ContentUpdateGroupSchema));
|
|
}
|
|
|
|
static void ConfigureGroup(AddressableAssetSettings settings, AddressableAssetGroup group, bool local)
|
|
{
|
|
BundledAssetGroupSchema bundle = group.GetSchema<BundledAssetGroupSchema>();
|
|
if (bundle == null)
|
|
bundle = group.AddSchema<BundledAssetGroupSchema>();
|
|
|
|
if (local)
|
|
{
|
|
bundle.BuildPath.SetVariableByName(settings, AddressableAssetSettings.kLocalBuildPath);
|
|
bundle.LoadPath.SetVariableByName(settings, AddressableAssetSettings.kLocalLoadPath);
|
|
}
|
|
else
|
|
{
|
|
bundle.BuildPath.SetVariableByName(settings, AddressableAssetSettings.kRemoteBuildPath);
|
|
bundle.LoadPath.SetVariableByName(settings, AddressableAssetSettings.kRemoteLoadPath);
|
|
}
|
|
|
|
bundle.BundleMode = BundledAssetGroupSchema.BundlePackingMode.PackTogether;
|
|
bundle.UseAssetBundleCrc = true;
|
|
bundle.UseAssetBundleCache = true;
|
|
|
|
ContentUpdateGroupSchema update = group.GetSchema<ContentUpdateGroupSchema>();
|
|
if (update == null)
|
|
update = group.AddSchema<ContentUpdateGroupSchema>();
|
|
update.StaticContent = local;
|
|
}
|
|
|
|
static void MarkScene(AddressableAssetSettings settings, AddressableAssetGroup group, string assetPath, string address, bool gameContent)
|
|
{
|
|
string guid = AssetDatabase.AssetPathToGUID(assetPath);
|
|
if (string.IsNullOrEmpty(guid))
|
|
{
|
|
Debug.LogWarning("OTA scene missing, skipped: " + assetPath);
|
|
return;
|
|
}
|
|
|
|
AddressableAssetEntry entry = settings.CreateOrMoveEntry(guid, group, false, false);
|
|
entry.address = address;
|
|
if (gameContent)
|
|
entry.SetLabel(GameContentLabel, true, true, true);
|
|
}
|
|
}
|
|
#endif
|