This commit is contained in:
陈思海 2026-04-15 14:23:30 +08:00
parent 52eaadb67d
commit 6f897a7af7
2 changed files with 58 additions and 10 deletions

View File

@ -23,6 +23,9 @@ namespace UnityEngine.UI
private ulong _activationSerial;
private bool _missingEventSystemLogged;
private bool _topScopeDirty = true;
private bool _suppressionDirty = true;
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.AfterSceneLoad)]
private static void Bootstrap()
{
@ -101,6 +104,8 @@ namespace UnityEngine.UI
}
_scopes.Add(scope);
_topScopeDirty = true;
_suppressionDirty = true;
}
internal void UnregisterScope(UXNavigationScope scope)
@ -117,7 +122,17 @@ namespace UnityEngine.UI
scope.IsAvailable = false;
scope.SetNavigationSuppressed(false);
_scopes.Remove(scope);
int idx = _scopes.IndexOf(scope);
if (idx >= 0)
{
int last = _scopes.Count - 1;
_scopes[idx] = _scopes[last];
_scopes.RemoveAt(last);
}
_topScopeDirty = true;
_suppressionDirty = true;
}
internal void MarkDiscoveryDirty()
@ -138,13 +153,22 @@ namespace UnityEngine.UI
DiscoverScopes();
}
if (_topScopeDirty)
{
UXNavigationScope newTopScope = FindTopScope();
_topScopeDirty = false;
if (!ReferenceEquals(_topScope, newTopScope))
{
_topScope = newTopScope;
_suppressionDirty = true;
}
}
if (_suppressionDirty)
{
ApplyScopeSuppression();
_suppressionDirty = false;
}
if (UXInputModeService.CurrentMode == UXInputMode.Gamepad)
{
@ -237,6 +261,9 @@ namespace UnityEngine.UI
{
_scopes[i]?.InvalidateSelectableCache();
}
_topScopeDirty = true;
_suppressionDirty = true;
}
}
@ -275,6 +302,8 @@ namespace UnityEngine.UI
{
scope.ActivationSerial = ++_activationSerial;
}
_suppressionDirty = true;
}
if (!available)
@ -304,11 +333,13 @@ namespace UnityEngine.UI
return false;
}
return !IsNavigationSkipped(scope.transform)
return !scope.IsNavigationSkipped
&& scope.HasAvailableSelectable()
&& TryGetInteractiveLayerRoot(scope.transform, out _);
}
// 保留静态方法用于 DiscoverScopes 中对 LayerRoot / Holder 节点的检测
// 这些节点无 UXNavigationScope调用频次低仅在 dirty 时),无需缓存
private static bool IsNavigationSkipped(Transform current)
{
return current != null && current.GetComponentInParent<UXNavigationSkip>(true) != null;

View File

@ -33,6 +33,9 @@ namespace UnityEngine.UI
private bool _navigationSuppressed;
private int _cachedHierarchyDepth = -1;
private bool _cachedIsSkipped;
private bool _isSkippedCacheValid;
internal ulong ActivationSerial { get; set; }
internal bool IsAvailable { get; set; }
internal bool WasAvailable { get; set; }
@ -47,6 +50,19 @@ namespace UnityEngine.UI
public bool RequireSelectionWhenGamepad => _requireSelectionWhenGamepad;
public bool BlockLowerScopes => _blockLowerScopes;
internal bool IsNavigationSkipped
{
get
{
if (!_isSkippedCacheValid)
{
_cachedIsSkipped = GetComponentInParent<UXNavigationSkip>(true) != null;
_isSkippedCacheValid = true;
}
return _cachedIsSkipped;
}
}
internal Canvas Canvas
{
get
@ -108,6 +124,7 @@ namespace UnityEngine.UI
_cachedCanvas = null;
_cachedHolder = null;
_cachedHierarchyDepth = -1;
_isSkippedCacheValid = false;
}
#if UNITY_EDITOR
@ -219,12 +236,12 @@ namespace UnityEngine.UI
internal void SetNavigationSuppressed(bool suppressed)
{
RefreshSelectableCache();
if (_navigationSuppressed == suppressed)
{
return;
}
RefreshSelectableCache();
_navigationSuppressed = suppressed;
for (int i = 0; i < _cachedSelectables.Count; i++)
{
@ -281,11 +298,11 @@ namespace UnityEngine.UI
}
_removeBuffer.Clear();
foreach (var pair in _baselineNavigation)
foreach (Selectable key in _baselineNavigation.Keys)
{
if (!_cachedSelectableSet.Contains(pair.Key))
if (!_cachedSelectableSet.Contains(key))
{
_removeBuffer.Add(pair.Key);
_removeBuffer.Add(key);
}
}