Repository navigation
Search.Modifiers
Modify search behavior with predicates, negation, OR, and availability options.
Modifiers let you:
- Filter by component property values
- Filter by custom GameObject conditions
- Negate conditions
- Combine searches with OR logic
- Include inactive or off-screen elements
Filter by a component on the matched object. Objects without a T don't match.
await Click(Type<Slider>().With<Slider>(s => s.value > 0.5f));
await TextInput(
Type<TMP_InputField>().With<TMP_InputField>(f => string.IsNullOrEmpty(f.text)),
"new value"
);
await Click(Type<Toggle>().With<Toggle>(t => t.isOn));Filter by an arbitrary GameObject predicate.
await Click(Type<Button>().Where(go => go.CompareTag("Important")));
await Click(Type<Button>().Where(go => go.layer == LayerMask.NameToLayer("UI")));Keep only objects with a Selectable (Button, Toggle, Slider, InputField, …) whose interactable is true. Objects with no Selectable are dropped.
await Click(Type<Button>().Interactable());
await ClickSlider(Type<Slider>().Interactable().First(), 0.5f);
// Equivalent to:
await Click(Type<Button>().With<Selectable>(s => s.interactable));This reads Selectable.interactable only; it does not consider a parent CanvasGroup.
Keep only objects whose screen centre is on screen and that overlap their parent ScrollRect viewport (if any). See Search.Spatial.
Keep only objects where an EventSystem raycast at their screen position hits a handler of the given interface types. See Search.Spatial.
Negate the next condition in the chain.
await Click(Type<Button>().Not.HasAncestor("DisabledPanel"));
await Click(Name("Item*").Not.InRegion(ScreenRegion.TopCenter));
await Click(Type<Button>().Not.Name("*Cancel*"));Not only negates the immediately following condition:
// NOT under "Disabled", but IS interactable
await Click(Type<Button>().Not.HasAncestor("Disabled").Interactable());
// Negate several conditions with several Nots
await Click(Type<Button>().Not.HasAncestor("Panel1").Not.HasAncestor("Panel2"));Put Not directly before the condition you mean. Ordering, selection (Skip/Take/First/Last) and Include* calls can't be negated — a Not in front of them carries over to the next condition instead.
Match elements that satisfy either search.
await Click(Name("OK").Or(Name("Confirm")));
await Click(Text("Yes").Or(Text("Accept")));
await Click(
Type<Button>().HasAncestor("Panel1")
.Or(Type<Button>().HasAncestor("Panel2"))
);Or returns a new search. Include* options are kept if either side set them; ordering/Skip/Take come from the left-hand search. Chain any further conditions after Or(...) — they apply to the combined result.
For simple alternatives, the | pattern syntax is shorter:
await Click(Text("OK|Confirm|Yes"));
await Click(Name("Button*|Btn*"));Also search GameObjects that are not active in the hierarchy.
var panel = await Find<RectTransform>(Name("HiddenPanel").IncludeInactive());
var allItems = await FindAll<RectTransform>(Name("Item*").IncludeInactive());Also return objects whose screen bounds are empty or entirely off screen — including objects with no RectTransform, enabled Renderer or enabled Collider (managers, cameras, empty parents).
var manager = await Find<Transform>(Name("GameManager").IncludeOffScreen());Non-interactable elements need no opt-in — searches already return them. Use .Interactable() to require interactable elements, or With<Selectable>(s => !s.interactable) to find disabled ones. See Availability Filtering.
// First empty field (top-to-bottom)
var emptyField = await Find<TMP_InputField>(
Type<TMP_InputField>()
.With<TMP_InputField>(f => string.IsNullOrEmpty(f.text))
.First()
);
// Wait for Submit to become clickable, then click
await WaitFor(Name("Submit").Interactable(), 10f);
await Click(Name("Submit"));var button = await Find<Button>(Name("SubmitButton"));
Assert.IsFalse(button.interactable, "Submit should be disabled when form is empty");
var disabledButtons = await FindAll<Button>(Type<Button>().With<Button>(b => !b.interactable));var hiddenPanels = await FindAll<RectTransform>(
Name("*Panel").IncludeInactive().Where(go => !go.activeSelf)
);
var panel = await Find<RectTransform>(Name("SettingsPanel").IncludeInactive());
panel.gameObject.SetActive(true);var lowSliders = await FindAll<Slider>(
Type<Slider>()
.HasAncestor("Settings")
.Not.HasAncestor("DisabledSection")
.With<Slider>(s => s.value < 0.5f)
.Interactable()
);
// Random clickable button that isn't close/cancel (reproducible with SetRandomSeed)
await RandomClick(
Type<Button>()
.Interactable()
.Not.Name("*Close*")
.Not.Name("*Cancel*")
.Not.HasDescendant(Text("X"))
);Basic Filters
Proximity
Hierarchy
Spatial
Ordering
Modifiers
Combining
Reflection
- Test Actions
- Click Actions
- Text Input
- Drag Actions
- Gesture Input
- Wait and Find
- Assertions
- GameObject Manipulation