285 lines
9.0 KiB
C#
285 lines
9.0 KiB
C#
using System;
|
||
using AlicizaX;
|
||
using UnityEngine;
|
||
using UnityEngine.Serialization;
|
||
using YooAsset;
|
||
|
||
namespace AlicizaX.Resource.Runtime
|
||
{
|
||
/// <summary>
|
||
/// 资源组件。
|
||
/// </summary>
|
||
[DisallowMultipleComponent]
|
||
public class ResourceComponent : MonoBehaviour
|
||
{
|
||
#region Propreties
|
||
|
||
private const int DEFAULT_PRIORITY = 0;
|
||
|
||
private IResourceModule _resourceModule;
|
||
|
||
private bool _forceUnloadUnusedAssets = false;
|
||
|
||
private bool _preorderUnloadUnusedAssets = false;
|
||
|
||
private bool _performGCCollect = false;
|
||
|
||
private AsyncOperation _asyncOperation = null;
|
||
|
||
private float _lastUnloadUnusedAssetsOperationElapseSeconds = 0f;
|
||
|
||
[SerializeField] private float minUnloadUnusedAssetsInterval = 60f;
|
||
|
||
[SerializeField] private float maxUnloadUnusedAssetsInterval = 300f;
|
||
|
||
[SerializeField] private bool useSystemUnloadUnusedAssets = true;
|
||
|
||
[SerializeField] private string decryptionServices = "";
|
||
|
||
/// <summary>
|
||
/// 自动释放资源引用计数为0的资源包
|
||
/// </summary>
|
||
[SerializeField] public bool autoUnloadBundleWhenUnused = false;
|
||
|
||
[SerializeField] private EPlayMode _playMode = EPlayMode.EditorSimulateMode;
|
||
|
||
/// <summary>
|
||
/// 当前最新的包裹版本。
|
||
/// </summary>
|
||
public string PackageVersion { set; get; }
|
||
|
||
/// <summary>
|
||
/// 资源包名称。
|
||
/// </summary>
|
||
[SerializeField] private string packageName = "DefaultPackage";
|
||
|
||
/// <summary>
|
||
/// 资源包名称。
|
||
/// </summary>
|
||
public string PackageName
|
||
{
|
||
get => packageName;
|
||
set => packageName = value;
|
||
}
|
||
|
||
|
||
/// <summary>
|
||
/// 设置异步系统参数,每帧执行消耗的最大时间切片(单位:毫秒)
|
||
/// </summary>
|
||
[SerializeField] public long milliseconds = 30;
|
||
|
||
public int downloadingMaxNum = 10;
|
||
|
||
/// <summary>
|
||
/// 获取或设置同时最大下载数目。
|
||
/// </summary>
|
||
public int DownloadingMaxNum
|
||
{
|
||
get => downloadingMaxNum;
|
||
set => downloadingMaxNum = value;
|
||
}
|
||
|
||
[SerializeField] public int failedTryAgain = 3;
|
||
|
||
public int FailedTryAgain
|
||
{
|
||
get => failedTryAgain;
|
||
set => failedTryAgain = value;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取当前资源适用的游戏版本号。
|
||
/// </summary>
|
||
public string ApplicableGameVersion => _resourceModule.ApplicableGameVersion;
|
||
|
||
/// <summary>
|
||
/// 获取当前内部资源版本号。
|
||
/// </summary>
|
||
public int InternalResourceVersion => _resourceModule.InternalResourceVersion;
|
||
|
||
/// <summary>
|
||
/// 获取或设置无用资源释放的最小间隔时间,以秒为单位。
|
||
/// </summary>
|
||
public float MinUnloadUnusedAssetsInterval
|
||
{
|
||
get => minUnloadUnusedAssetsInterval;
|
||
set => minUnloadUnusedAssetsInterval = value;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取或设置无用资源释放的最大间隔时间,以秒为单位。
|
||
/// </summary>
|
||
public float MaxUnloadUnusedAssetsInterval
|
||
{
|
||
get => maxUnloadUnusedAssetsInterval;
|
||
set => maxUnloadUnusedAssetsInterval = value;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 使用系统释放无用资源策略。
|
||
/// </summary>
|
||
public bool UseSystemUnloadUnusedAssets
|
||
{
|
||
get => useSystemUnloadUnusedAssets;
|
||
set => useSystemUnloadUnusedAssets = value;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取无用资源释放的等待时长,以秒为单位。
|
||
/// </summary>
|
||
public float LastUnloadUnusedAssetsOperationElapseSeconds => _lastUnloadUnusedAssetsOperationElapseSeconds;
|
||
|
||
[SerializeField] private float assetAutoReleaseInterval = 60f;
|
||
|
||
[SerializeField] private int assetCapacity = 64;
|
||
|
||
[SerializeField] private float assetExpireTime = 60f;
|
||
|
||
[SerializeField] private int assetPriority = 0;
|
||
|
||
/// <summary>
|
||
/// 获取或设置资源对象池自动释放可释放对象的间隔秒数。
|
||
/// </summary>
|
||
public float AssetAutoReleaseInterval
|
||
{
|
||
get => _resourceModule.AssetAutoReleaseInterval;
|
||
set => _resourceModule.AssetAutoReleaseInterval = assetAutoReleaseInterval = value;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取或设置资源对象池的容量。
|
||
/// </summary>
|
||
public int AssetCapacity
|
||
{
|
||
get => _resourceModule.AssetCapacity;
|
||
set => _resourceModule.AssetCapacity = assetCapacity = value;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取或设置资源对象池对象过期秒数。
|
||
/// </summary>
|
||
public float AssetExpireTime
|
||
{
|
||
get => _resourceModule.AssetExpireTime;
|
||
set => _resourceModule.AssetExpireTime = assetExpireTime = value;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取或设置资源对象池的优先级。
|
||
/// </summary>
|
||
public int AssetPriority
|
||
{
|
||
get => _resourceModule.AssetPriority;
|
||
set => _resourceModule.AssetPriority = assetPriority = value;
|
||
}
|
||
|
||
#endregion
|
||
|
||
public void SetPlayMode(int playMode)
|
||
{
|
||
_playMode = (EPlayMode)playMode;
|
||
}
|
||
|
||
public void SetDecryptionServices(string decryption)
|
||
{
|
||
decryptionServices = decryption;
|
||
}
|
||
|
||
private void Awake()
|
||
{
|
||
_resourceModule = ModuleSystem.RegisterModule<IResourceModule, ResourceModule>();
|
||
if (_resourceModule == null)
|
||
{
|
||
Log.Error("Resource module is invalid.");
|
||
return;
|
||
}
|
||
|
||
Application.lowMemory += OnLowMemory;
|
||
}
|
||
|
||
public static string PrefsKey = Application.dataPath.GetHashCode() + "GamePlayMode";
|
||
|
||
private void Start()
|
||
{
|
||
#if UNITY_EDITOR
|
||
_playMode = (EPlayMode)UnityEditor.EditorPrefs.GetInt(ResourceComponent.PrefsKey, 0);
|
||
#endif
|
||
_resourceModule.DefaultPackageName = PackageName;
|
||
_resourceModule.DecryptionServices = decryptionServices;
|
||
_resourceModule.AutoUnloadBundleWhenUnused = autoUnloadBundleWhenUnused;
|
||
_resourceModule.PlayMode = _playMode;
|
||
_resourceModule.Milliseconds = milliseconds;
|
||
_resourceModule.DownloadingMaxNum = DownloadingMaxNum;
|
||
_resourceModule.FailedTryAgain = FailedTryAgain;
|
||
_resourceModule.Initialize();
|
||
_resourceModule.AssetAutoReleaseInterval = assetAutoReleaseInterval;
|
||
_resourceModule.AssetCapacity = assetCapacity;
|
||
_resourceModule.AssetExpireTime = assetExpireTime;
|
||
_resourceModule.AssetPriority = assetPriority;
|
||
_resourceModule.SetForceUnloadUnusedAssetsAction(ForceUnloadUnusedAssets);
|
||
Log.Info($"ResourceModule Run Mode:{_playMode}");
|
||
}
|
||
|
||
private void OnApplicationQuit()
|
||
{
|
||
Application.lowMemory -= OnLowMemory;
|
||
}
|
||
|
||
#region 释放资源
|
||
|
||
/// <summary>
|
||
/// 强制执行释放未被使用的资源。
|
||
/// </summary>
|
||
/// <param name="performGCCollect">是否使用垃圾回收。</param>
|
||
public void ForceUnloadUnusedAssets(bool performGCCollect)
|
||
{
|
||
_forceUnloadUnusedAssets = true;
|
||
if (performGCCollect)
|
||
{
|
||
_performGCCollect = true;
|
||
}
|
||
}
|
||
|
||
|
||
private void Update()
|
||
{
|
||
_lastUnloadUnusedAssetsOperationElapseSeconds += Time.unscaledDeltaTime;
|
||
if (_asyncOperation == null && (_forceUnloadUnusedAssets || _lastUnloadUnusedAssetsOperationElapseSeconds >= maxUnloadUnusedAssetsInterval ||
|
||
_preorderUnloadUnusedAssets && _lastUnloadUnusedAssetsOperationElapseSeconds >= minUnloadUnusedAssetsInterval))
|
||
{
|
||
Log.Info("Unload unused assets...");
|
||
_forceUnloadUnusedAssets = false;
|
||
_preorderUnloadUnusedAssets = false;
|
||
_lastUnloadUnusedAssetsOperationElapseSeconds = 0f;
|
||
_asyncOperation = Resources.UnloadUnusedAssets();
|
||
if (useSystemUnloadUnusedAssets)
|
||
{
|
||
_resourceModule.UnloadUnusedAssets();
|
||
}
|
||
}
|
||
|
||
if (_asyncOperation is { isDone: true })
|
||
{
|
||
_asyncOperation = null;
|
||
if (_performGCCollect)
|
||
{
|
||
Log.Info("GC.Collect...");
|
||
_performGCCollect = false;
|
||
GC.Collect();
|
||
}
|
||
}
|
||
}
|
||
|
||
private void OnLowMemory()
|
||
{
|
||
Log.Warning("Low memory reported...");
|
||
if (_resourceModule != null)
|
||
{
|
||
_resourceModule.OnLowMemory();
|
||
}
|
||
}
|
||
|
||
#endregion
|
||
}
|
||
}
|