// Copyright (C) 2023 Nicholas Maltbie // // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and // associated documentation files (the "Software"), to deal in the Software without restriction, // including without limitation the rights to use, copy, modify, merge, publish, distribute, // sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in all copies or // substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING // BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. using nickmaltbie.OpenKCC.Character.Action; using nickmaltbie.OpenKCC.Input; using nickmaltbie.OpenKCC.Tests.TestCommon; using nickmaltbie.OpenKCC.Utils; using nickmaltbie.TestUtilsUnity; using nickmaltbie.TestUtilsUnity.Tests.TestCommon; using NUnit.Framework; using UnityEngine; using UnityEngine.InputSystem; namespace nickmaltbie.OpenKCC.Tests.EditMode.Character.Action { /// /// Basic tests for ConditionalAction in edit mode. /// [TestFixture] public class JumpActionTests : TestBase { private MockUnityService unityServiceMock; private KCCConfig kccConfigMock; private MockKCCGrounded kccGroundedMock; private MockJumping jumpingMock; private Gamepad gamepad; private InputAction testAction; private JumpAction jumpAction; private bool condition = true; private Vector3 inputJump = Vector3.zero; [SetUp] public void SetUp() { base.Setup(); unityServiceMock = new MockUnityService(); unityServiceMock.deltaTime = 1.0f; jumpAction = new JumpAction(); jumpAction.unityService = unityServiceMock; jumpAction.SetCondition(() => condition); InputActionMap actionMap; (gamepad, _, actionMap) = base.SetupInputDevice(); testAction = actionMap.AddAction("testAction", InputActionType.Button, gamepad.aButton.path, interactions: "press"); var bufferedInput = new BufferedInput(); bufferedInput.unityService = unityServiceMock; bufferedInput.inputActionReference = InputActionReference.Create(testAction); bufferedInput.cooldown = 1.0f; bufferedInput.bufferTime = 3.0f; jumpingMock = new MockJumping(); kccConfigMock = new KCCConfig { Up = Vector3.up, }; kccGroundedMock = new MockKCCGrounded(); jumpingMock.OnJump = (Vector3 jump) => inputJump = jump; jumpAction.jumpInput = bufferedInput; jumpAction.Setup(kccGroundedMock, kccConfigMock, jumpingMock); testAction.Enable(); } [Test] public void Verify_JumpAction_JumpDirection([NUnit.Framework.Range(0.0f, 1.0f, 0.2f)] float jumpWeight) { jumpAction.jumpAngleWeightFactor = jumpWeight; kccGroundedMock.StandingOnGround = true; kccGroundedMock.SurfaceNormal = Vector3.forward; jumpAction.Jump(); Vector3 expected = Vector3.Lerp(Vector3.up, Vector3.forward, jumpWeight).normalized * jumpAction.jumpVelocity; TestUtils.AssertInBounds(inputJump, expected); } [Test] public void Verify_JumpAction_JumpedWhileSliding() { kccGroundedMock.Sliding = true; Assert.IsFalse(jumpAction.JumpedWhileSliding); jumpAction.Jump(); Assert.IsTrue(jumpAction.JumpedWhileSliding); jumpAction.Update(); Assert.IsTrue(jumpAction.JumpedWhileSliding); kccGroundedMock.StandingOnGround = true; kccGroundedMock.Sliding = false; jumpAction.Update(); Assert.IsFalse(jumpAction.JumpedWhileSliding); } [Test] public void Verify_JumpAction_ApplyJumpIfPossible() { jumpAction.maxJumpAngle = 60.0f; kccGroundedMock.StandingOnGround = true; kccGroundedMock.Angle = 30; kccGroundedMock.Sliding = false; // Assert that can jump when standing on flat ground. Set(gamepad.aButton, 1); jumpAction.Update(); Assert.IsTrue(jumpAction.AttemptingJump); Assert.IsTrue(jumpAction.ApplyJumpIfPossible(kccGroundedMock)); Assert.IsFalse(jumpAction.ApplyJumpIfPossible(kccGroundedMock)); } [Test] public void Verify_JumpAction_CanJump_Sliding() { jumpAction.maxJumpAngle = 60.0f; kccGroundedMock.StandingOnGround = true; kccGroundedMock.Angle = 30; kccGroundedMock.Sliding = false; // Assert that can jump when standing on flat ground. Assert.IsTrue(jumpAction.CanJump()); // Assert that can jump while sliding. kccGroundedMock.Sliding = true; Assert.IsTrue(jumpAction.CanJump()); // Assert that cannot jump two times while sliding. jumpAction.Jump(); Assert.IsFalse(jumpAction.CanJump()); } [Test] public void Verify_JumpAction_CanJump_SteepSlope() { jumpAction.maxJumpAngle = 60.0f; kccGroundedMock.StandingOnGround = true; kccGroundedMock.Angle = 30; kccGroundedMock.Sliding = false; // Assert that can jump when standing on flat ground. Assert.IsTrue(jumpAction.CanJump()); // Assert that can jump while sliding. kccGroundedMock.Sliding = true; Assert.IsTrue(jumpAction.CanJump()); jumpAction.maxJumpAngle = 20.0f; // Assert that cannot jump too steep slope Assert.IsFalse(jumpAction.CanJump()); } [Test] public void Validate_JumpAction_AttemptingJump() { // set the value as true and update the input device Press(gamepad.aButton); jumpAction.Update(); Assert.IsTrue(jumpAction.AttemptingJump); jumpAction.Update(); Assert.IsTrue(jumpAction.AttemptingJump); unityServiceMock.deltaTime = 100; jumpAction.Update(); Assert.IsFalse(jumpAction.CanJump()); } [Test] public void Verify_JumpAction_CanJump_NotGrounded() { jumpAction.maxJumpAngle = 60.0f; kccGroundedMock.StandingOnGround = false; kccGroundedMock.Angle = 30; kccGroundedMock.Sliding = false; // Assert that can jump when standing on flat ground. Assert.IsFalse(jumpAction.CanJump()); } } }