优化性能
This commit is contained in:
parent
0f7d062a9f
commit
bc66728a65
@ -9,11 +9,13 @@ namespace UnityEngine.UI
|
||||
internal sealed class UXNavigationRuntime : MonoBehaviour
|
||||
{
|
||||
private static UXNavigationRuntime _instance;
|
||||
private static readonly string CacheLayerName = $"Layer{(int)UILayer.All}-{UILayer.All}";
|
||||
|
||||
private const float DiscoveryInterval = 0.5f;
|
||||
private readonly HashSet<UXNavigationScope> _scopeSet = new();
|
||||
private readonly List<UXNavigationScope> _scopes = new(32);
|
||||
private readonly HashSet<Transform> _interactiveLayerRoots = new();
|
||||
private readonly List<UIHolderObjectBase> _holderBuffer = new(32);
|
||||
|
||||
private Transform _uiCanvasRoot;
|
||||
private UXNavigationScope _topScope;
|
||||
@ -116,6 +118,7 @@ namespace UnityEngine.UI
|
||||
_topScope = null;
|
||||
}
|
||||
|
||||
scope.IsAvailable = false;
|
||||
scope.SetNavigationSuppressed(false);
|
||||
_scopes.Remove(scope);
|
||||
MarkDiscoveryDirty();
|
||||
@ -185,11 +188,10 @@ namespace UnityEngine.UI
|
||||
return;
|
||||
}
|
||||
|
||||
string cacheLayerName = $"Layer{(int)UILayer.All}-{UILayer.All}";
|
||||
for (int i = 0; i < _uiCanvasRoot.childCount; i++)
|
||||
{
|
||||
Transform child = _uiCanvasRoot.GetChild(i);
|
||||
if (child == null || child.name == cacheLayerName)
|
||||
if (child == null || child.name == CacheLayerName)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
@ -217,10 +219,11 @@ namespace UnityEngine.UI
|
||||
continue;
|
||||
}
|
||||
|
||||
UIHolderObjectBase[] holders = layerRoot.GetComponentsInChildren<UIHolderObjectBase>(true);
|
||||
for (int i = 0; i < holders.Length; i++)
|
||||
_holderBuffer.Clear();
|
||||
layerRoot.GetComponentsInChildren(true, _holderBuffer);
|
||||
for (int i = 0; i < _holderBuffer.Count; i++)
|
||||
{
|
||||
UIHolderObjectBase holder = holders[i];
|
||||
UIHolderObjectBase holder = _holderBuffer[i];
|
||||
if (holder == null
|
||||
|| holder.GetComponent<UXNavigationScope>() != null
|
||||
|| IsNavigationSkipped(holder.transform))
|
||||
@ -233,6 +236,8 @@ namespace UnityEngine.UI
|
||||
}
|
||||
}
|
||||
|
||||
_holderBuffer.Clear();
|
||||
|
||||
if (addedScope)
|
||||
{
|
||||
for (int i = 0; i < _scopes.Count; i++)
|
||||
@ -254,6 +259,7 @@ namespace UnityEngine.UI
|
||||
}
|
||||
|
||||
bool available = IsScopeAvailable(scope);
|
||||
scope.IsAvailable = available;
|
||||
if (scope.WasAvailable != available)
|
||||
{
|
||||
scope.WasAvailable = available;
|
||||
@ -348,7 +354,7 @@ namespace UnityEngine.UI
|
||||
continue;
|
||||
}
|
||||
|
||||
bool suppress = IsScopeAvailable(scope)
|
||||
bool suppress = scope.IsAvailable
|
||||
&& _topScope != null
|
||||
&& !ReferenceEquals(scope, _topScope)
|
||||
&& _topScope.BlockLowerScopes
|
||||
|
||||
@ -21,16 +21,20 @@ namespace UnityEngine.UI
|
||||
[SerializeField, Header("自动选中首个可用控件")] private bool _autoSelectFirstAvailable = true;
|
||||
|
||||
private readonly List<Selectable> _cachedSelectables = new(16);
|
||||
private readonly HashSet<Selectable> _cachedSelectableSet = new();
|
||||
private readonly Dictionary<Selectable, Navigation> _baselineNavigation = new();
|
||||
private readonly List<Selectable> _removeBuffer = new(8);
|
||||
private readonly List<Selectable> _selectableScanBuffer = new(16);
|
||||
|
||||
private Canvas _cachedCanvas;
|
||||
private UIHolderObjectBase _cachedHolder;
|
||||
private Selectable _lastSelected;
|
||||
private bool _cacheDirty = true;
|
||||
private bool _navigationSuppressed;
|
||||
private int _cachedHierarchyDepth = -1;
|
||||
|
||||
internal ulong ActivationSerial { get; set; }
|
||||
internal bool IsAvailable { get; set; }
|
||||
internal bool WasAvailable { get; set; }
|
||||
|
||||
public Selectable DefaultSelectable
|
||||
@ -98,6 +102,14 @@ namespace UnityEngine.UI
|
||||
_cacheDirty = true;
|
||||
}
|
||||
|
||||
private void OnTransformParentChanged()
|
||||
{
|
||||
_cacheDirty = true;
|
||||
_cachedCanvas = null;
|
||||
_cachedHolder = null;
|
||||
_cachedHierarchyDepth = -1;
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
private void OnValidate()
|
||||
{
|
||||
@ -107,6 +119,11 @@ namespace UnityEngine.UI
|
||||
|
||||
internal int GetHierarchyDepth()
|
||||
{
|
||||
if (_cachedHierarchyDepth >= 0)
|
||||
{
|
||||
return _cachedHierarchyDepth;
|
||||
}
|
||||
|
||||
int depth = 0;
|
||||
Transform current = transform;
|
||||
while (current != null)
|
||||
@ -115,7 +132,8 @@ namespace UnityEngine.UI
|
||||
current = current.parent;
|
||||
}
|
||||
|
||||
return depth;
|
||||
_cachedHierarchyDepth = depth;
|
||||
return _cachedHierarchyDepth;
|
||||
}
|
||||
|
||||
internal bool Owns(GameObject target)
|
||||
@ -151,7 +169,7 @@ namespace UnityEngine.UI
|
||||
for (int i = 0; i < _cachedSelectables.Count; i++)
|
||||
{
|
||||
Selectable selectable = _cachedSelectables[i];
|
||||
if (IsSelectableValid(selectable))
|
||||
if (IsSelectableUsable(selectable))
|
||||
{
|
||||
return selectable;
|
||||
}
|
||||
@ -171,7 +189,7 @@ namespace UnityEngine.UI
|
||||
|
||||
for (int i = 0; i < _cachedSelectables.Count; i++)
|
||||
{
|
||||
if (IsSelectableValid(_cachedSelectables[i]))
|
||||
if (IsSelectableUsable(_cachedSelectables[i]))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@ -187,12 +205,7 @@ namespace UnityEngine.UI
|
||||
return;
|
||||
}
|
||||
|
||||
Selectable selectable = selectedObject.GetComponent<Selectable>();
|
||||
if (selectable == null)
|
||||
{
|
||||
selectable = selectedObject.GetComponentInParent<Selectable>();
|
||||
}
|
||||
|
||||
Selectable selectable = GetSelectableFromObject(selectedObject);
|
||||
if (IsSelectableValid(selectable))
|
||||
{
|
||||
_lastSelected = selectable;
|
||||
@ -201,18 +214,7 @@ namespace UnityEngine.UI
|
||||
|
||||
internal bool IsSelectableOwnedAndValid(GameObject selectedObject)
|
||||
{
|
||||
if (selectedObject == null || !Owns(selectedObject))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
Selectable selectable = selectedObject.GetComponent<Selectable>();
|
||||
if (selectable == null)
|
||||
{
|
||||
selectable = selectedObject.GetComponentInParent<Selectable>();
|
||||
}
|
||||
|
||||
return IsSelectableValid(selectable);
|
||||
return IsSelectableValid(GetSelectableFromObject(selectedObject));
|
||||
}
|
||||
|
||||
internal void SetNavigationSuppressed(bool suppressed)
|
||||
@ -259,6 +261,7 @@ namespace UnityEngine.UI
|
||||
|
||||
_cacheDirty = false;
|
||||
_cachedSelectables.Clear();
|
||||
_cachedSelectableSet.Clear();
|
||||
|
||||
if (_explicitSelectables != null && _explicitSelectables.Count > 0)
|
||||
{
|
||||
@ -269,17 +272,18 @@ namespace UnityEngine.UI
|
||||
}
|
||||
else
|
||||
{
|
||||
Selectable[] selectables = GetComponentsInChildren<Selectable>(true);
|
||||
for (int i = 0; i < selectables.Length; i++)
|
||||
_selectableScanBuffer.Clear();
|
||||
GetComponentsInChildren(true, _selectableScanBuffer);
|
||||
for (int i = 0; i < _selectableScanBuffer.Count; i++)
|
||||
{
|
||||
TryAddSelectable(selectables[i]);
|
||||
TryAddSelectable(_selectableScanBuffer[i]);
|
||||
}
|
||||
}
|
||||
|
||||
_removeBuffer.Clear();
|
||||
foreach (var pair in _baselineNavigation)
|
||||
{
|
||||
if (!_cachedSelectables.Contains(pair.Key))
|
||||
if (!_cachedSelectableSet.Contains(pair.Key))
|
||||
{
|
||||
_removeBuffer.Add(pair.Key);
|
||||
}
|
||||
@ -289,6 +293,8 @@ namespace UnityEngine.UI
|
||||
{
|
||||
_baselineNavigation.Remove(_removeBuffer[i]);
|
||||
}
|
||||
|
||||
_selectableScanBuffer.Clear();
|
||||
}
|
||||
|
||||
public void InvalidateSelectableCache()
|
||||
@ -298,7 +304,7 @@ namespace UnityEngine.UI
|
||||
|
||||
private void TryAddSelectable(Selectable selectable)
|
||||
{
|
||||
if (selectable == null || !Owns(selectable.gameObject))
|
||||
if (selectable == null || !Owns(selectable.gameObject) || !_cachedSelectableSet.Add(selectable))
|
||||
{
|
||||
return;
|
||||
}
|
||||
@ -311,11 +317,28 @@ namespace UnityEngine.UI
|
||||
}
|
||||
|
||||
private bool IsSelectableValid(Selectable selectable)
|
||||
{
|
||||
return IsSelectableUsable(selectable)
|
||||
&& (_cachedSelectableSet.Contains(selectable) || Owns(selectable.gameObject));
|
||||
}
|
||||
|
||||
private static bool IsSelectableUsable(Selectable selectable)
|
||||
{
|
||||
return selectable != null
|
||||
&& selectable.IsActive()
|
||||
&& selectable.IsInteractable()
|
||||
&& Owns(selectable.gameObject);
|
||||
&& selectable.IsInteractable();
|
||||
}
|
||||
|
||||
private static Selectable GetSelectableFromObject(GameObject selectedObject)
|
||||
{
|
||||
if (selectedObject == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return selectedObject.TryGetComponent(out Selectable selectable)
|
||||
? selectable
|
||||
: selectedObject.GetComponentInParent<Selectable>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -17,6 +17,8 @@ namespace UnityEngine.UI
|
||||
{
|
||||
[SerializeField] private List<TransitionData> m_ChildTransitions = new();
|
||||
|
||||
private SelectionState _state;
|
||||
|
||||
void StartChildColorTween(TransitionData transitionData, Color targetColor, bool instant)
|
||||
{
|
||||
if (transitionData.targetGraphic == null)
|
||||
@ -68,7 +70,8 @@ namespace UnityEngine.UI
|
||||
protected override void DoStateTransition(SelectionState state, bool instant)
|
||||
{
|
||||
base.DoStateTransition(state, instant);
|
||||
|
||||
if (_state == state) return;
|
||||
_state = state;
|
||||
for (int i = 0; i < m_ChildTransitions.Count; i++)
|
||||
{
|
||||
TransitionData transitionData = m_ChildTransitions[i];
|
||||
|
||||
Loading…
Reference in New Issue
Block a user