public IEnumerator SmoothTurn() { // Create a stick control to serve as the input action source for the turn provider var gamepad = InputSystem.InputSystem.AddDevice <Gamepad>(); var asset = ScriptableObject.CreateInstance <InputActionAsset>(); var actionMap = asset.AddActionMap("Locomotion"); var action = actionMap.AddAction("Turn", InputActionType.Value, "<Gamepad>/rightStick"); var xrRig = TestUtilities.CreateXRRig(); var rigTransform = xrRig.rig.transform; // Config continuous turn on XR rig var locoSys = xrRig.gameObject.AddComponent <LocomotionSystem>(); locoSys.xrRig = xrRig; var turnProvider = xrRig.gameObject.AddComponent <ActionBasedContinuousTurnProvider>(); turnProvider.system = locoSys; turnProvider.leftHandTurnAction = new InputActionProperty(action); turnProvider.turnSpeed = 60f; // Partially push stick directly right. // This tests that the turn speed will be scaled by the input magnitude. var input = new Vector2(0.5f, 0f); var processedInput = new StickDeadzoneProcessor().Process(input); Set(gamepad.rightStick, input); var startTime = Time.time; yield return(new WaitForSeconds(1f)); var turnAmount = processedInput.magnitude * turnProvider.turnSpeed * (Time.time - startTime); var actualRotation = rigTransform.rotation; Assert.That(actualRotation, Is.EqualTo(Quaternion.Euler(0f, turnAmount, 0f)).Using(QuaternionEqualityComparer.Instance)); // Stop turning Set(gamepad.rightStick, Vector2.zero); yield return(new WaitForSeconds(0.1f)); // ReSharper disable Unity.InefficientPropertyAccess -- Property value accessed after yield Assert.That(actualRotation, Is.EqualTo(rigTransform.rotation).Using(QuaternionEqualityComparer.Instance)); // ReSharper restore Unity.InefficientPropertyAccess }
public void Controls_CanHaveStickDeadzones() { const string json = @" { ""name"" : ""MyDevice"", ""extend"" : ""Gamepad"", ""controls"" : [ { ""name"" : ""leftStick"", ""processors"" : ""stickDeadzone(min=0.1,max=0.9)"" } ] } "; InputSystem.RegisterLayout(json); var device = (Gamepad)InputSystem.AddDevice("MyDevice"); var firstState = new GamepadState { leftStick = new Vector2(0.05f, 0.05f) }; var secondState = new GamepadState { leftStick = new Vector2(0.5f, 0.5f) }; InputSystem.QueueStateEvent(device, firstState); InputSystem.Update(); Assert.That(device.leftStick.ReadValue(), Is.EqualTo(default(Vector2))); InputSystem.QueueStateEvent(device, secondState); InputSystem.Update(); var processedVector = new StickDeadzoneProcessor { min = 0.1f, max = 0.9f }.Process(new Vector2(0.5f, 0.5f)); Assert.That(device.leftStick.ReadValue(), Is.EqualTo(processedVector)); // Deadzoning on the stick axes is independent so we shouldn't see equivalent values on // the axes here. Assert.That(device.leftStick.x.ReadValue(), Is.Not.EqualTo(processedVector.x)); Assert.That(device.leftStick.y.ReadValue(), Is.Not.EqualTo(processedVector.y)); }
IEnumerator MoveInDirection(ForwardSource forwardSource) { // Create a stick control to serve as the input action source for the move provider var gamepad = InputSystem.InputSystem.AddDevice <Gamepad>(); var asset = ScriptableObject.CreateInstance <InputActionAsset>(); var actionMap = asset.AddActionMap("Locomotion"); var action = actionMap.AddAction("Move", InputActionType.Value, "<Gamepad>/leftStick"); var xrRig = TestUtilities.CreateXRRig(); var rigTransform = xrRig.rig.transform; var cameraTransform = xrRig.cameraGameObject.transform; // Rotate the camera to face a different direction than rig forward to test // that the move provider will move with respect to a selected forward object. cameraTransform.Rotate(0f, 45f, 0f); var cameraForward = cameraTransform.forward; Assert.That(rigTransform.forward, Is.Not.EqualTo(cameraForward).Using(Vector3ComparerWithEqualsOperator.Instance)); // Create a controller object to serve as another forward source var controllerGO = new GameObject("Controller"); controllerGO.transform.SetParent(xrRig.cameraFloorOffsetObject.transform, false); controllerGO.transform.Rotate(0f, -45f, 0f); var controllerForward = controllerGO.transform.forward; Assert.That(rigTransform.forward, Is.Not.EqualTo(controllerForward).Using(Vector3ComparerWithEqualsOperator.Instance)); // Config continuous move on XR rig var locoSys = xrRig.gameObject.AddComponent <LocomotionSystem>(); locoSys.xrRig = xrRig; var moveProvider = xrRig.gameObject.AddComponent <ActionBasedContinuousMoveProvider>(); moveProvider.system = locoSys; moveProvider.leftHandMoveAction = new InputActionProperty(action); moveProvider.moveSpeed = 1f; switch (forwardSource) { case ForwardSource.Default: break; case ForwardSource.Camera: moveProvider.forwardSource = xrRig.cameraGameObject.transform; break; case ForwardSource.Controller: moveProvider.forwardSource = controllerGO.transform; break; default: Assert.Fail($"Unhandled {nameof(ForwardSource)}={forwardSource}"); break; } // See Script Execution Order diagram https://docs.unity3d.com/Manual/ExecutionOrder.html // This test will begin after Update() during the yield null/yield WaitForSeconds/yield StartCoroutine stage. // The move provider will process input during Update() of the next frame, and scale the move based on Time.deltaTime. // After yielding for 1 second with the stick pushed forward, the stick will be released back to center. // The move provider will process the release during Update() of the next frame, and should not apply any more movement. // Partially push stick directly forward. // This tests that the move speed will be scaled by the input magnitude. var input = new Vector2(0f, 0.5f); var processedInput = new StickDeadzoneProcessor().Process(input); Set(gamepad.leftStick, input); var startTime = Time.time; yield return(new WaitForSeconds(1f)); var actualPosition = rigTransform.position; var actualDistance = Vector3.Distance(Vector3.zero, actualPosition); var expectedDistance = processedInput.magnitude * moveProvider.moveSpeed * (Time.time - startTime); Assert.That(actualDistance, Is.EqualTo(expectedDistance).Within(1e-5f)); switch (forwardSource) { case ForwardSource.Default: case ForwardSource.Camera: Assert.That(actualPosition, Is.EqualTo(cameraForward * expectedDistance).Using(Vector3ComparerWithEqualsOperator.Instance)); break; case ForwardSource.Controller: Assert.That(actualPosition, Is.EqualTo(controllerForward * expectedDistance).Using(Vector3ComparerWithEqualsOperator.Instance)); break; default: Assert.Fail($"Unhandled {nameof(ForwardSource)}={forwardSource}"); break; } // Stop moving Set(gamepad.leftStick, Vector2.zero); yield return(new WaitForSeconds(0.1f)); // ReSharper disable Unity.InefficientPropertyAccess -- Property value accessed after yield Assert.That(Vector3.Distance(actualPosition, rigTransform.position), Is.EqualTo(0f)); // ReSharper restore Unity.InefficientPropertyAccess }