com.alicizax.unity.framework/Runtime/ABase/GameObjectPool/Data/PoolConfig.cs
2026-04-17 21:01:20 +08:00

272 lines
8.4 KiB
C#

using System;
using System.Collections.Generic;
using UnityEngine;
namespace AlicizaX
{
public enum PoolResourceLoaderType
{
AssetBundle = 0,
Resources = 1
}
public enum PoolMatchMode
{
Exact = 0,
Prefix = 1
}
public enum PoolOverflowPolicy
{
FailFast = 0,
InstantiateOneShot = 1,
AutoExpand = 2,
RecycleOldestInactive = 3,
DropNewestRequest = 4
}
public enum PoolTrimPolicy
{
None = 0,
IdleOnly = 1,
IdleAndPriority = 2,
AggressiveOnLowMemory = 3
}
public enum PoolActivationMode
{
SetActive = 0,
SleepWake = 1,
Custom = 2
}
public enum PoolResetMode
{
TransformOnly = 0,
PoolableCallbacks = 1,
FullReset = 2,
Custom = 3
}
[Serializable]
public sealed class PoolEntry
{
public const string DefaultGroup = "Default";
public const string DefaultEntryName = "DefaultPool";
public string entryName = DefaultEntryName;
public string group = DefaultGroup;
public string assetPath;
public PoolMatchMode matchMode = PoolMatchMode.Exact;
public PoolResourceLoaderType loaderType = PoolResourceLoaderType.AssetBundle;
public PoolOverflowPolicy overflowPolicy = PoolOverflowPolicy.FailFast;
public PoolTrimPolicy trimPolicy = PoolTrimPolicy.IdleOnly;
public PoolActivationMode activationMode = PoolActivationMode.SetActive;
public PoolResetMode resetMode = PoolResetMode.PoolableCallbacks;
[Min(0)]
public int minRetained = 0;
[Min(1)]
public int softCapacity = 8;
[Min(1)]
public int hardCapacity = 8;
[Min(0f)]
public float idleTrimDelay = 30f;
[Min(0f)]
public float prefabUnloadDelay = 60f;
[Min(0f)]
public float autoRecycleDelay = 0f;
[Min(1)]
public int trimBatchPerTick = 2;
[Min(1)]
public int warmupBatchPerFrame = 2;
[Min(0f)]
public float warmupFrameBudgetMs = 1f;
public bool allowRuntimeExpand;
public bool keepPrefabResident;
public bool aggressiveTrimOnLowMemory;
public int priority;
public void Normalize()
{
entryName = string.IsNullOrWhiteSpace(entryName) ? DefaultEntryName : entryName.Trim();
group = string.IsNullOrWhiteSpace(group) ? DefaultGroup : group.Trim();
assetPath = NormalizeAssetPath(assetPath);
minRetained = Mathf.Max(0, minRetained);
softCapacity = Mathf.Max(1, softCapacity);
hardCapacity = Mathf.Max(softCapacity, hardCapacity);
minRetained = Mathf.Min(minRetained, hardCapacity);
idleTrimDelay = Mathf.Max(0f, idleTrimDelay);
prefabUnloadDelay = Mathf.Max(0f, prefabUnloadDelay);
autoRecycleDelay = Mathf.Max(0f, autoRecycleDelay);
trimBatchPerTick = Mathf.Max(1, trimBatchPerTick);
warmupBatchPerFrame = Mathf.Max(1, warmupBatchPerFrame);
warmupFrameBudgetMs = Mathf.Max(0f, warmupFrameBudgetMs);
}
public bool Matches(string requestedAssetPath, string requestedGroup = null)
{
if (string.IsNullOrWhiteSpace(assetPath) || string.IsNullOrWhiteSpace(requestedAssetPath))
{
return false;
}
if (!string.IsNullOrWhiteSpace(requestedGroup) &&
!string.Equals(group, requestedGroup, StringComparison.Ordinal))
{
return false;
}
return matchMode switch
{
PoolMatchMode.Exact => string.Equals(requestedAssetPath, assetPath, StringComparison.Ordinal),
PoolMatchMode.Prefix => requestedAssetPath.StartsWith(assetPath, StringComparison.Ordinal),
_ => false
};
}
public string BuildResolvedPoolKey(string resolvedAssetPath)
{
string concretePath = NormalizeAssetPath(resolvedAssetPath);
return $"{group}|{(int)matchMode}|{assetPath}|{(int)loaderType}|{concretePath}|{entryName}";
}
public static int CompareByPriority(PoolEntry left, PoolEntry right)
{
if (ReferenceEquals(left, right))
{
return 0;
}
if (left == null)
{
return 1;
}
if (right == null)
{
return -1;
}
int priorityCompare = right.priority.CompareTo(left.priority);
if (priorityCompare != 0)
{
return priorityCompare;
}
int modeCompare = left.matchMode.CompareTo(right.matchMode);
if (modeCompare != 0)
{
return modeCompare;
}
int leftLength = left.assetPath?.Length ?? 0;
int rightLength = right.assetPath?.Length ?? 0;
int pathLengthCompare = rightLength.CompareTo(leftLength);
if (pathLengthCompare != 0)
{
return pathLengthCompare;
}
return string.Compare(left.group, right.group, StringComparison.Ordinal);
}
public static string NormalizeAssetPath(string value)
{
if (string.IsNullOrWhiteSpace(value))
{
return string.Empty;
}
return value.Trim().Replace('\\', '/');
}
}
[Serializable]
public sealed class ResolvedPoolConfig
{
public string entryName;
public string group;
public string assetPath;
public PoolMatchMode matchMode;
public PoolResourceLoaderType loaderType;
public PoolOverflowPolicy overflowPolicy;
public PoolTrimPolicy trimPolicy;
public PoolActivationMode activationMode;
public PoolResetMode resetMode;
public int minRetained;
public int softCapacity;
public int hardCapacity;
public float idleTrimDelay;
public float prefabUnloadDelay;
public float autoRecycleDelay;
public int trimBatchPerTick;
public int warmupBatchPerFrame;
public float warmupFrameBudgetMs;
public bool allowRuntimeExpand;
public bool keepPrefabResident;
public bool aggressiveTrimOnLowMemory;
public int priority;
public string BuildResolvedPoolKey(string resolvedAssetPath)
{
string concretePath = PoolEntry.NormalizeAssetPath(resolvedAssetPath);
return $"{group}|{(int)matchMode}|{assetPath}|{(int)loaderType}|{concretePath}|{entryName}";
}
public static ResolvedPoolConfig From(PoolEntry entry)
{
if (entry == null)
{
throw new ArgumentNullException(nameof(entry));
}
return new ResolvedPoolConfig
{
entryName = entry.entryName,
group = entry.group,
assetPath = entry.assetPath,
matchMode = entry.matchMode,
loaderType = entry.loaderType,
overflowPolicy = entry.overflowPolicy,
trimPolicy = entry.trimPolicy,
activationMode = entry.activationMode,
resetMode = entry.resetMode,
minRetained = entry.minRetained,
softCapacity = entry.softCapacity,
hardCapacity = entry.hardCapacity,
idleTrimDelay = entry.idleTrimDelay,
prefabUnloadDelay = entry.prefabUnloadDelay,
autoRecycleDelay = entry.autoRecycleDelay,
trimBatchPerTick = entry.trimBatchPerTick,
warmupBatchPerFrame = entry.warmupBatchPerFrame,
warmupFrameBudgetMs = entry.warmupFrameBudgetMs,
allowRuntimeExpand = entry.allowRuntimeExpand,
keepPrefabResident = entry.keepPrefabResident,
aggressiveTrimOnLowMemory = entry.aggressiveTrimOnLowMemory,
priority = entry.priority
};
}
}
[Serializable]
public sealed class PoolConfigCatalog
{
public readonly List<PoolEntry> entries;
public PoolConfigCatalog(List<PoolEntry> entries)
{
this.entries = entries ?? throw new ArgumentNullException(nameof(entries));
}
}
}