-
Notifications
You must be signed in to change notification settings - Fork 0
GameObject Manipulation
Methods for controlling GameObjects during tests: disable/enable, freeze physics, teleport, and toggle collisions.
All manipulation methods are async and wait up to 10 seconds (configurable) for elements to appear, consistent with other action methods. They return restoration tokens that can restore the original state:
using static ODDGames.UIAutomation.ActionExecutor;
// Via Search (async - require await)
await new Search().Name("Player").Freeze();
await Search.Reflect("GameManager.Instance.player").NoClip();
// Via static helpers
await Freeze(Name("Player"));
await NoClip(Static("GameManager.Instance.player"));| Method | Returns | Description |
|---|---|---|
.Disable(searchTime) |
UniTask<ActiveState> |
Deactivate a GameObject |
.Enable(searchTime) |
UniTask<ActiveState> |
Activate a GameObject (can find inactive) |
.Freeze(includeChildren, searchTime) |
UniTask<FreezeState> |
Zero velocity + set kinematic on Rigidbodies |
.Teleport(Vector3, searchTime) |
UniTask<PositionState> |
Move transform to world position |
.NoClip(includeChildren, searchTime) |
UniTask<ColliderState> |
Disable all colliders |
.Clip(includeChildren, searchTime) |
UniTask<ColliderState> |
Enable all colliders |
All methods have a searchTime parameter (default 10 seconds) that controls how long to wait for the element to appear.
Control GameObject active state:
// Disable a GameObject
await new Search().Name("TutorialPanel").Disable();
// Enable an inactive GameObject (Enable() can find inactive objects)
await new Search().Name("TutorialPanel").Enable();
// Via Static path
await Search.Reflect("GameManager.Instance.tutorialPanel").Disable();
// Custom timeout (default is 10 seconds)
await new Search().Name("TutorialPanel").Disable(searchTime: 5f);Stop physics simulation on Rigidbodies:
// Freeze a single object (includes children by default)
await new Search().Name("AITruck").Freeze();
// Freeze only the root object
await new Search().Name("Player").Freeze(includeChildren: false);
// Via Static path
await Search.Reflect("GameManager.Instance.player").Freeze();Freeze sets:
isKinematic = truelinearVelocity = Vector3.zeroangularVelocity = Vector3.zero
Works with both Rigidbody (3D) and Rigidbody2D (2D).
Move a transform instantly to a world position:
// Teleport to position
await new Search().Name("Player").Teleport(new Vector3(100, 0, 50));
// Via Static path
await Search.Reflect("GameManager.Instance.player").Teleport(Vector3.zero);Children maintain their local positions relative to the parent.
Toggle collider states for pass-through or collision:
// Disable all colliders (pass through objects)
await new Search().Name("Player").NoClip();
// Enable all colliders (restore collisions)
await new Search().Name("Player").Clip();
// Only affect root object, not children
await new Search().Name("Player").NoClip(includeChildren: false);Works with both Collider (3D) and Collider2D (2D).
All methods return state objects that capture the original state before modification.
// Capture state
var state = await new Search().Name("Player").NoClip();
// ... test code with colliders disabled ...
// Restore original state
state.Restore();State tokens implement IDisposable for automatic restoration:
using (await new Search().Name("Player").NoClip())
{
// Colliders disabled here
await Click(Name("Button"));
}
// Colliders automatically restoredStack multiple using blocks for complex setups:
using (await new Search().Name("AITruck").Freeze())
using (await new Search().Name("Player").NoClip())
{
// AI frozen, player has no collision
await Teleport(Name("Player"), targetPosition);
}
// Both states restored| Property | Description |
|---|---|
.Count |
Number of affected components |
.Restore() |
Restore original state (idempotent) |
var state = await new Search().Name("Vehicle").Freeze();
Debug.Log($"Froze {state.Count} rigidbodies");Static helper methods are available via ActionExecutor:
using NUnit.Framework;
using static ODDGames.UIAutomation.ActionExecutor;
[TestFixture]
public class GameObjectManipulationTests
{
[Test]
public async Task TestGameObjectManipulation()
{
// Helper methods (all async)
await Disable(Name("TutorialPanel"));
await Enable(Name("TutorialPanel"));
await Freeze(Name("AITruck"));
await Teleport(Name("Player"), new Vector3(100, 0, 50));
await NoClip(Name("Player"));
await Clip(Name("Player"));
// They also return restoration tokens
using (await Freeze(Name("AITruck")))
{
// AI frozen
}
}
}// Disable tutorial UI without clicking through it
await Disable(Name("TutorialPanel"));
await Click(Name("StartGame"));using (await Freeze(Name("EnemySpawner")))
{
// Position player without AI interference
await Teleport(Name("Player"), spawnPoint);
await WaitForSeconds(1);
}
// AI resumesusing (await NoClip(Name("Player")))
{
// Move through walls to reach test location
await Teleport(Name("Player"), new Vector3(500, 0, 500));
}
// Collisions restoredUse [Test] public async Task with try/finally for cleanup:
using NUnit.Framework;
using static ODDGames.UIAutomation.ActionExecutor;
[TestFixture]
public class AITests
{
[Test]
public async Task TestWithFrozenAI()
{
var frozenAI = await Freeze(Name("AIManager"));
try
{
// ... test code ...
}
finally
{
frozenAI?.Restore();
}
}
}Methods throw TimeoutException if the target is not found within the search time:
// Throws TimeoutException after 10s if "NonExistent" not found
await new Search().Name("NonExistent").Disable();
// Use shorter timeout for faster failure
await new Search().Name("NonExistent").Disable(searchTime: 1f);Methods return zero-count states if no applicable components exist:
// Returns FreezeState with Count = 0 if no Rigidbodies
var state = await new Search().Name("StaticObject").Freeze();
Debug.Log(state.Count); // 0Basic Filters
Proximity
Hierarchy
Spatial
Ordering
Modifiers
Combining
Reflection
- Click Actions
- Text Input
- Drag Actions
- Gesture Input
- Wait and Find
- Assertions
- GameObject Manipulation