301 lines
9.8 KiB
C#
301 lines
9.8 KiB
C#
using System.Collections;
|
||
using System.Collections.Generic;
|
||
using System.Linq;
|
||
using TMPro;
|
||
using UniRx;
|
||
using UnityEngine;
|
||
using UnityEngine.Networking;
|
||
using UnityEngine.Serialization;
|
||
|
||
namespace Ichni
|
||
{
|
||
public class ThemeBundleManager : MonoBehaviour
|
||
{
|
||
public static ThemeBundleManager instance;
|
||
|
||
public List<ThemeBundleAbstract> themeBundleAbstractList;
|
||
public List<string> selectedThemeBundleList;
|
||
public List<ThemeBundle> loadedThemeBundleList;
|
||
|
||
public IntReactiveProperty waitingBundleAmount;
|
||
|
||
// 只记录本 Manager 通过 AssetBundle.LoadFromFileAsync 加载的 Theme Bundle。
|
||
// Addressables(包括 Unity Localization)拥有自己的 Bundle 引用计数,绝不能通过
|
||
// AssetBundle.UnloadAllAssetBundles 代替各系统分别释放资源。
|
||
private readonly List<AssetBundle> loadedAssetBundles = new List<AssetBundle>();
|
||
|
||
private void Awake()
|
||
{
|
||
instance = this;
|
||
|
||
loadedThemeBundleList = new List<ThemeBundle>();
|
||
LoadAllThemeBundlesAbstract();
|
||
//LoadThemeBundle("basic");
|
||
//LoadThemeBundle("departure_to_multiverse");
|
||
}
|
||
|
||
private void OnDestroy()
|
||
{
|
||
// 仅卸载本实例拥有的 Theme Bundle,不影响 Addressables 管理的 Locale、String Table
|
||
// 或其它系统加载的 AssetBundle。
|
||
foreach (AssetBundle bundle in loadedAssetBundles)
|
||
{
|
||
if (bundle != null)
|
||
{
|
||
bundle.Unload(true);
|
||
}
|
||
}
|
||
|
||
loadedAssetBundles.Clear();
|
||
loadedThemeBundleList?.Clear();
|
||
|
||
if (instance == this)
|
||
{
|
||
instance = null;
|
||
}
|
||
}
|
||
|
||
public bool TryGetThemeBundle(string themeBundleName, out ThemeBundle themeBundle)
|
||
{
|
||
themeBundle = loadedThemeBundleList.Find(bundle => bundle.themeBundleName == themeBundleName);
|
||
return themeBundle != null;
|
||
}
|
||
|
||
public T GetObject<T>(string themeBundleName, string objectName) where T : class
|
||
{
|
||
return loadedThemeBundleList.Find(bundle => bundle.themeBundleName == themeBundleName)?.GetObject<T>(objectName);
|
||
}
|
||
|
||
public void LoadThemeBundles(List<string> list)
|
||
{
|
||
waitingBundleAmount = new IntReactiveProperty(list.Count);
|
||
Debug.Log("Waiting for " + list.Count + " AssetBundles to load.");
|
||
foreach (var bundle in list)
|
||
{
|
||
LoadThemeBundle(bundle);
|
||
}
|
||
|
||
selectedThemeBundleList = list;
|
||
}
|
||
|
||
public void LoadAllThemeBundlesAbstract()
|
||
{
|
||
string uri = Application.streamingAssetsPath + "/ThemeBundles/";
|
||
|
||
if (ES3.DirectoryExists(uri))
|
||
{
|
||
List<string> allFileList = ES3.GetFiles(uri).ToList();
|
||
List<string> absList = new List<string>();
|
||
foreach (var abs in allFileList)
|
||
{
|
||
if (abs.EndsWith(".abs"))
|
||
{
|
||
absList.Add(abs);
|
||
}
|
||
}
|
||
|
||
foreach (var abs in absList)
|
||
{
|
||
themeBundleAbstractList.Add(ES3.Load<ThemeBundleAbstract>("ThemeBundleAbstract", uri + abs));
|
||
}
|
||
}
|
||
}
|
||
|
||
public void LoadThemeBundle(string themeBundleName)
|
||
{
|
||
StartCoroutine(LoadThemeBundleCoroutine(themeBundleName));
|
||
}
|
||
|
||
IEnumerator LoadThemeBundleCoroutine(string themeBundleName)
|
||
{
|
||
string uri = "";
|
||
|
||
if (Application.platform == RuntimePlatform.WindowsEditor ||
|
||
Application.platform == RuntimePlatform.WindowsPlayer)
|
||
{
|
||
uri = Application.streamingAssetsPath + "/ThemeBundles/Windows64/" + themeBundleName;
|
||
}
|
||
else if (Application.platform == RuntimePlatform.OSXEditor ||
|
||
Application.platform == RuntimePlatform.OSXPlayer)
|
||
{
|
||
uri = Application.streamingAssetsPath + "/ThemeBundles/OSX/" + themeBundleName;
|
||
}
|
||
else if (Application.platform == RuntimePlatform.Android)
|
||
{
|
||
uri = Application.streamingAssetsPath + "/ThemeBundles/Android/" + themeBundleName;
|
||
}
|
||
else if (Application.platform == RuntimePlatform.IPhonePlayer)
|
||
{
|
||
uri = Application.streamingAssetsPath + "/ThemeBundles/IOS/" + themeBundleName;
|
||
}
|
||
else
|
||
{
|
||
Debug.LogError("Unsupported platform for loading theme bundles.");
|
||
yield break;
|
||
}
|
||
|
||
AssetBundleCreateRequest createRequest = AssetBundle.LoadFromFileAsync(uri);
|
||
yield return createRequest;
|
||
AssetBundle bundle = createRequest.assetBundle;
|
||
if (bundle == null)
|
||
{
|
||
Debug.LogError($"Theme Bundle 加载失败:{uri}");
|
||
waitingBundleAmount.Value--;
|
||
yield break;
|
||
}
|
||
|
||
loadedAssetBundles.Add(bundle);
|
||
|
||
try
|
||
{
|
||
Object[] ob = bundle.LoadAllAssets<Object>();
|
||
loadedThemeBundleList.Add(new ThemeBundle(themeBundleName));
|
||
|
||
for (int i = 0; i < ob.Length; i++)
|
||
{
|
||
if (ob[i].GetType() == typeof(GameObject))
|
||
{
|
||
loadedThemeBundleList[^1].assetList_GameObject.Add(ob[i] as GameObject);
|
||
}
|
||
else if (ob[i].GetType() == typeof(Material))
|
||
{
|
||
loadedThemeBundleList[^1].assetList_Material.Add(ob[i] as Material);
|
||
}
|
||
else if (ob[i].GetType() == typeof(Texture2D))
|
||
{
|
||
loadedThemeBundleList[^1].assetList_Texture.Add(ob[i] as Texture2D);
|
||
}
|
||
else
|
||
{
|
||
loadedThemeBundleList[^1].assetList_Other.Add(ob[i]);
|
||
}
|
||
}
|
||
}
|
||
catch (System.Exception exception)
|
||
{
|
||
Debug.LogException(exception, this);
|
||
}
|
||
finally
|
||
{
|
||
waitingBundleAmount.Value--;
|
||
}
|
||
|
||
yield return new WaitForEndOfFrame();
|
||
print(themeBundleName + " Done!");
|
||
}
|
||
}
|
||
|
||
[System.Serializable]
|
||
public class ThemeBundleAbstract
|
||
{
|
||
public string fileName;
|
||
public string displayName;
|
||
public string description;
|
||
public List<string> tags;
|
||
public string iconPath;
|
||
|
||
public ThemeBundleAbstract()
|
||
{
|
||
}
|
||
|
||
public ThemeBundleAbstract(string fileName)
|
||
{
|
||
this.fileName = fileName;
|
||
this.displayName = fileName;
|
||
this.description = "Default Description";
|
||
this.tags = new List<string>();
|
||
this.iconPath = "Icons/Default.png";
|
||
}
|
||
|
||
public Texture2D GetIcon()
|
||
{
|
||
string uri = Application.streamingAssetsPath + "/" + iconPath;
|
||
if (ES3.FileExists(uri))
|
||
{
|
||
Texture2D sp = ES3.LoadImage(uri);
|
||
return sp;
|
||
}
|
||
return null;
|
||
}
|
||
}
|
||
|
||
[System.Serializable]
|
||
public class ThemeBundle
|
||
{
|
||
public string themeBundleName;
|
||
public List<GameObject> assetList_GameObject;
|
||
public List<Material> assetList_Material;
|
||
public List<Texture2D> assetList_Texture;
|
||
public List<Object> assetList_Other;
|
||
|
||
public ThemeBundle(string name)
|
||
{
|
||
themeBundleName = name;
|
||
assetList_GameObject = new List<GameObject>();
|
||
assetList_Material = new List<Material>();
|
||
assetList_Texture = new List<Texture2D>();
|
||
assetList_Other = new List<Object>();
|
||
}
|
||
|
||
public T GetObject<T>(string name) where T : class
|
||
{
|
||
if (name == "None")
|
||
{
|
||
return null;
|
||
}
|
||
|
||
T[] assetList;
|
||
|
||
if (typeof(T) == typeof(GameObject))
|
||
{
|
||
assetList = assetList_GameObject.ToArray() as T[];
|
||
|
||
for (int i = 0; i < assetList_GameObject.Count; i++)
|
||
{
|
||
if (name == assetList_GameObject[i].name)
|
||
{
|
||
if (assetList != null) return assetList[i];
|
||
}
|
||
}
|
||
}
|
||
else if (typeof(T) == typeof(Material))
|
||
{
|
||
assetList = assetList_Material.ToArray() as T[];
|
||
|
||
for (int i = 0; i < assetList_Material.Count; i++)
|
||
{
|
||
if (name == assetList_Material[i].name)
|
||
{
|
||
if (assetList != null) return assetList[i];
|
||
}
|
||
}
|
||
}
|
||
else if (typeof(T) == typeof(Texture2D))
|
||
{
|
||
assetList = assetList_Texture.ToArray() as T[];
|
||
|
||
for (int i = 0; i < assetList_Texture.Count; i++)
|
||
{
|
||
if (name == assetList_Texture[i].name)
|
||
{
|
||
if (assetList != null) return assetList[i];
|
||
}
|
||
}
|
||
}
|
||
else
|
||
{
|
||
assetList = assetList_Other.ToArray() as T[];
|
||
for (int i = 0; i < assetList_Other.Count; i++)
|
||
{
|
||
if (name == assetList_Other[i].name)
|
||
{
|
||
if (assetList != null) return assetList[i];
|
||
}
|
||
}
|
||
}
|
||
|
||
return null;
|
||
}
|
||
}
|
||
}
|