diff --git a/Runtime/InteractiveComponent.cs b/Runtime/InteractiveComponent.cs index 9d0364a..d30c3c3 100644 --- a/Runtime/InteractiveComponent.cs +++ b/Runtime/InteractiveComponent.cs @@ -48,21 +48,42 @@ private readonly Func, PointerEventData, L private readonly PointerEventData _eventData = new PointerEventData(EventSystem.current); private readonly List _results = new List(); + internal InteractiveComponent(MonoBehaviour component, + Func getScreenPoint = null, + Func, PointerEventData, List, bool> isReachable = null) + { + this.component = component; + _getScreenPoint = getScreenPoint ?? DefaultScreenPointStrategy.GetScreenPoint; + _isReachable = isReachable ?? DefaultReachableStrategy.IsReachable; + } + /// - /// Constructor + /// Create InteractableComponent instance from MonoBehaviour. /// /// /// The function returns the screen position where raycast for the found GameObject. /// Default is DefaultScreenPointStrategy.GetScreenPoint. /// The function returns the GameObject is reachable from user or not. /// Default is DefaultReachableStrategy.IsReachable. - public InteractiveComponent(MonoBehaviour component, + /// The function returns the Component is interactable or not. + /// Default is DefaultComponentInteractableStrategy.IsInteractable. + /// Returns new InteractableComponent instance from MonoBehaviour. If MonoBehaviour is not interactable so, return null. + public static InteractiveComponent CreateInteractableComponent(MonoBehaviour component, Func getScreenPoint = null, - Func, PointerEventData, List, bool> isReachable = null) + Func, PointerEventData, List, bool> isReachable = null, + Func isComponentInteractable = null) { - this.component = component; - _getScreenPoint = getScreenPoint ?? DefaultScreenPointStrategy.GetScreenPoint; - _isReachable = isReachable ?? DefaultReachableStrategy.IsReachable; + getScreenPoint = getScreenPoint ?? DefaultScreenPointStrategy.GetScreenPoint; + isReachable = isReachable ?? DefaultReachableStrategy.IsReachable; + isComponentInteractable = isComponentInteractable ?? DefaultComponentInteractableStrategy.IsInteractable; + + if (isComponentInteractable.Invoke(component)) + { + return new InteractiveComponent(component, getScreenPoint, isReachable); + } + + Debug.LogWarning($"Component `{component}` is not interactable."); + return null; } /// @@ -76,14 +97,15 @@ public InteractiveComponent(MonoBehaviour component, /// The function returns the Component is interactable or not. /// Default is DefaultComponentInteractableStrategy.IsInteractable. /// Returns new InteractableComponent instance from GameObject. If GameObject is not interactable so, return null. + [Obsolete("Obsolete due to non-deterministic behavior when GameObject has multiple interactable components.")] public static InteractiveComponent CreateInteractableComponent(GameObject gameObject, Func getScreenPoint = null, Func, PointerEventData, List, bool> isReachable = null, Func isComponentInteractable = null) { getScreenPoint = getScreenPoint ?? DefaultScreenPointStrategy.GetScreenPoint; - isComponentInteractable = isComponentInteractable ?? DefaultComponentInteractableStrategy.IsInteractable; isReachable = isReachable ?? DefaultReachableStrategy.IsReachable; + isComponentInteractable = isComponentInteractable ?? DefaultComponentInteractableStrategy.IsInteractable; foreach (var component in gameObject.GetComponents()) { @@ -93,6 +115,7 @@ public static InteractiveComponent CreateInteractableComponent(GameObject gameOb } } + Debug.LogWarning($"GameObject `{gameObject}` has not interactable component."); return null; } diff --git a/Runtime/InteractiveComponentCollector.cs b/Runtime/InteractiveComponentCollector.cs index 0924e18..ee63c76 100644 --- a/Runtime/InteractiveComponentCollector.cs +++ b/Runtime/InteractiveComponentCollector.cs @@ -58,7 +58,7 @@ public IEnumerable FindInteractableComponents() { if (_isInteractable.Invoke(component)) { - yield return new InteractiveComponent(component, + yield return InteractiveComponent.CreateInteractableComponent(component, _getScreenPoint, _isReachable); } diff --git a/Samples~/uGUI Demo/Tests/Runtime/ScenarioTest.cs b/Samples~/uGUI Demo/Tests/Runtime/ScenarioTest.cs index 3aba08a..8c463d3 100644 --- a/Samples~/uGUI Demo/Tests/Runtime/ScenarioTest.cs +++ b/Samples~/uGUI Demo/Tests/Runtime/ScenarioTest.cs @@ -4,6 +4,7 @@ using System.Threading.Tasks; using NUnit.Framework; using TestHelper.Attributes; +using UnityEngine.UI; namespace TestHelper.Monkey.Samples.UGUIDemo { @@ -25,17 +26,23 @@ public async Task OpenSubScreens(string target) // When click Start button, then open Home screen. var startButton = await _finder.FindByNameAsync("StartButton", interactable: true); - InteractiveComponent.CreateInteractableComponent(startButton).Click(); + var startComponent = InteractiveComponent.CreateInteractableComponent(startButton.GetComponent