Skip to content

Commit

Permalink
Add support for asset bundles without an architecture suffix
Browse files Browse the repository at this point in the history
Unity requires specifying the architecture when building asset bundles as part of BuildTarget. While compatibility between targets isn't guaranteed, in practice there are no differences between architectures.

<!-- ps-id: 49397d5b-21fc-4201-a0d6-e0c2f9627bf3 -->
  • Loading branch information
js6pak committed Aug 1, 2024
1 parent 86b5a29 commit 127f48f
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 34 deletions.
8 changes: 4 additions & 4 deletions Reactor.Assets/Assets/Build.cs
Original file line number Diff line number Diff line change
Expand Up @@ -69,14 +69,14 @@ public static void BuildAssetBundles()
}
}

private static string GetTargetName(BuildTarget target)
private static string GetTargetName(BuildTarget target, bool includeArchitecture = false)
{
return target switch
{
BuildTarget.StandaloneWindows => "win-x86",
BuildTarget.StandaloneWindows64 => "win-x64",
BuildTarget.StandaloneWindows => includeArchitecture ? "win-x86" : "win",
BuildTarget.StandaloneWindows64 => includeArchitecture ? "win-x64" : "win",
BuildTarget.Android => "android",
BuildTarget.StandaloneLinux64 => "linux-x64",
BuildTarget.StandaloneLinux64 => includeArchitecture ? "linux-x64" : "linux",
_ => throw new ArgumentOutOfRangeException(nameof(target), target, null),
};
}
Expand Down
File renamed without changes.
92 changes: 62 additions & 30 deletions Reactor/Utilities/AssetBundleManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using MonoMod.Utils;
using Reactor.Utilities.Extensions;
using UnityEngine;

Expand All @@ -23,46 +23,65 @@ public static class AssetBundleManager
/// <summary>
/// Gets the target name of the current system.
/// </summary>
public static string TargetName { get; }
[Obsolete("Use AssetBundleManager#GetTargetName instead")]
public static string TargetName { get; } = GetTargetName(true);

static AssetBundleManager()
/// <summary>
/// Gets the target name of the current system.
/// </summary>
/// <param name="includeArchitecture">A value indicating whether to include the process architecture.</param>
/// <returns>Target name of the current system.</returns>
public static string GetTargetName(bool includeArchitecture)
{
if (PlatformHelper.Is(Platform.Android))
string operatingSystem;

if (OperatingSystem.IsWindows())
{
TargetName = "android";
operatingSystem = "win";
}
else if (OperatingSystem.IsLinux())
{
operatingSystem = "linux";
}
else if (OperatingSystem.IsAndroid())
{
operatingSystem = "android";
}
else
{
if (PlatformHelper.Is(Platform.Windows))
{
TargetName = "win";
}
else if (PlatformHelper.Is(Platform.Linux))
{
TargetName = "linux";
}
else
{
throw new PlatformNotSupportedException();
}
throw new PlatformNotSupportedException();
}

if (PlatformHelper.Is(Platform.ARM))
{
TargetName += Environment.Is64BitProcess ? "-arm64" : "-arm";
}
else
{
TargetName += Environment.Is64BitProcess ? "-x64" : "-x86";
}
if (!includeArchitecture)
{
return operatingSystem;
}

return $"{operatingSystem}-{RuntimeInformation.ProcessArchitecture switch
{
Architecture.X86 => "x86",
Architecture.X64 => "x64",
Architecture.Arm => "arm",
Architecture.Arm64 => "arm64",
_ => throw new PlatformNotSupportedException(),
}}";
}

/// <summary>
/// Gets the file name for an asset bundle named <paramref name="assetBundleName"/>.
/// </summary>
/// <param name="assetBundleName">The name of the asset bundle.</param>
/// <returns>File name of the asset bundle.</returns>
public static string GetFileName(string assetBundleName) => $"{assetBundleName}-{TargetName}{BundleExtension}";
[Obsolete("Use the overload with includeArchitecture instead")]
public static string GetFileName(string assetBundleName) => GetFileName(assetBundleName, true);

/// <summary>
/// Gets the file name for an asset bundle named <paramref name="assetBundleName"/>.
/// </summary>
/// <param name="assetBundleName">The name of the asset bundle.</param>
/// <param name="includeArchitecture">A value indicating whether to include the process architecture.</param>
/// <returns>File name of the asset bundle.</returns>
public static string GetFileName(string assetBundleName, bool includeArchitecture) => $"{assetBundleName}-{GetTargetName(includeArchitecture)}{BundleExtension}";

private static bool TryFindFile(Assembly assembly, string fileName, [NotNullWhen(true)] out string? path)
{
Expand All @@ -72,6 +91,7 @@ private static bool TryFindFile(Assembly assembly, string fileName, [NotNullWhen
var filePath = Path.Combine(pluginDirectoryPath, fileName);
if (File.Exists(filePath))
{
Debug($"Loading an asset bundle from {filePath}");
path = filePath;
return true;
}
Expand All @@ -86,6 +106,8 @@ private static bool TryLoadResource(Assembly assembly, string fileName, [NotNull
var resourceName = assembly.GetManifestResourceNames().SingleOrDefault(n => n.EndsWith(fileName, StringComparison.Ordinal));
if (resourceName != null)
{
Debug($"Loading an asset bundle from {resourceName}");

using var stream = assembly.GetManifestResourceStream(resourceName) ?? throw new InvalidOperationException("Resource stream was null");

var length = (int) stream.Length;
Expand Down Expand Up @@ -119,8 +141,13 @@ public static AssetBundle Load(string name)
/// <exception cref="AssetBundleNotFoundException">Couldn't find an assetbundle named <paramref name="name"/>.</exception>
public static AssetBundle Load(Assembly assembly, string name)
{
var fileName = GetFileName(name);
return TryLoad(assembly, GetFileName(name, includeArchitecture: true))
?? TryLoad(assembly, GetFileName(name, includeArchitecture: false))
?? throw new AssetBundleNotFoundException(name);
}

private static AssetBundle? TryLoad(Assembly assembly, string fileName)
{
if (TryFindFile(assembly, fileName, out var filePath))
{
return AssetBundle.LoadFromFile(filePath);
Expand All @@ -131,7 +158,7 @@ public static AssetBundle Load(Assembly assembly, string name)
return AssetBundle.LoadFromMemory(data);
}

throw new AssetBundleNotFoundException(name);
return null;
}

/// <summary>
Expand All @@ -154,8 +181,13 @@ public static AssetBundleCreateRequest LoadAsync(string name)
/// <exception cref="AssetBundleNotFoundException">Couldn't find an assetbundle named <paramref name="name"/>.</exception>
public static AssetBundleCreateRequest LoadAsync(Assembly assembly, string name)
{
var fileName = GetFileName(name);
return TryLoadAsync(assembly, GetFileName(name, includeArchitecture: true))
?? TryLoadAsync(assembly, GetFileName(name, includeArchitecture: false))
?? throw new AssetBundleNotFoundException(name);
}

private static AssetBundleCreateRequest? TryLoadAsync(Assembly assembly, string fileName)
{
if (TryFindFile(assembly, fileName, out var filePath))
{
return AssetBundle.LoadFromFileAsync(filePath);
Expand All @@ -166,7 +198,7 @@ public static AssetBundleCreateRequest LoadAsync(Assembly assembly, string name)
return AssetBundle.LoadFromMemoryAsync(data);
}

throw new AssetBundleNotFoundException(name);
return null;
}
}

Expand Down

0 comments on commit 127f48f

Please sign in to comment.