From 1ccf724281e63020b66544b36844c58ba41cef8a Mon Sep 17 00:00:00 2001 From: Chris Date: Sat, 9 Aug 2025 16:02:55 -0400 Subject: [PATCH] change: separated all functions of movement into separate tasks --- .../Core/Graph Tasks/FinalizeMovement.cs | 48 +++++++ .../Core/Graph Tasks/FinalizeMovement.cs.meta | 2 + .../Core/Graph Tasks/ProcessMovement.cs | 118 ---------------- ...ssGravity.cs => UpdateGravityDirection.cs} | 26 ++-- ...cs.meta => UpdateGravityDirection.cs.meta} | 0 .../Graph Tasks/UpdateMovementDirection.cs | 126 ++++++++++++++++++ ...s.meta => UpdateMovementDirection.cs.meta} | 0 .../Core/Graph Tasks/UpdateMovementSpeed.cs | 60 +++++++++ .../Graph Tasks/UpdateMovementSpeed.cs.meta | 2 + .../{ProcessRotation.cs => UpdateRotation.cs} | 39 ++---- ...otation.cs.meta => UpdateRotation.cs.meta} | 0 ...ayerMovement.cs => UnitMovementHandler.cs} | 0 ...nt.cs.meta => UnitMovementHandler.cs.meta} | 0 13 files changed, 263 insertions(+), 158 deletions(-) create mode 100644 Assets/Scripts/Core/Graph Tasks/FinalizeMovement.cs create mode 100644 Assets/Scripts/Core/Graph Tasks/FinalizeMovement.cs.meta delete mode 100644 Assets/Scripts/Core/Graph Tasks/ProcessMovement.cs rename Assets/Scripts/Core/Graph Tasks/{ProcessGravity.cs => UpdateGravityDirection.cs} (74%) rename Assets/Scripts/Core/Graph Tasks/{ProcessGravity.cs.meta => UpdateGravityDirection.cs.meta} (100%) create mode 100644 Assets/Scripts/Core/Graph Tasks/UpdateMovementDirection.cs rename Assets/Scripts/Core/Graph Tasks/{ProcessMovement.cs.meta => UpdateMovementDirection.cs.meta} (100%) create mode 100644 Assets/Scripts/Core/Graph Tasks/UpdateMovementSpeed.cs create mode 100644 Assets/Scripts/Core/Graph Tasks/UpdateMovementSpeed.cs.meta rename Assets/Scripts/Core/Graph Tasks/{ProcessRotation.cs => UpdateRotation.cs} (71%) rename Assets/Scripts/Core/Graph Tasks/{ProcessRotation.cs.meta => UpdateRotation.cs.meta} (100%) rename Assets/Scripts/Player/{PlayerMovement.cs => UnitMovementHandler.cs} (100%) rename Assets/Scripts/Player/{PlayerMovement.cs.meta => UnitMovementHandler.cs.meta} (100%) diff --git a/Assets/Scripts/Core/Graph Tasks/FinalizeMovement.cs b/Assets/Scripts/Core/Graph Tasks/FinalizeMovement.cs new file mode 100644 index 0000000..10734ea --- /dev/null +++ b/Assets/Scripts/Core/Graph Tasks/FinalizeMovement.cs @@ -0,0 +1,48 @@ +using NodeCanvas.Framework; +using ParadoxNotion.Design; +using UnityEngine; + +namespace Reset.Movement { + + [Category("Reset/Movement")] + [Description("Finalize the move direction to the agent's CharacterController")] + public class FinalizeMovement : ActionTask{ + public BBParameter moveDirection; + public BBParameter currentSpeed; + + //Use for initialization. This is called only once in the lifetime of the task. + //Return null if init was successfull. Return an error string otherwise + protected override string OnInit() { + if (currentSpeed == null || !currentSpeed.useBlackboard) { + Debug.LogError("This Finalize Movement does not have it's current value attached to a Blackboard variable. Nothing will happen.", agent.gameObject); + } + return null; + } + + //This is called once each time the task is enabled. + //Call EndAction() to mark the action as finished, either in success or failure. + //EndAction can be called from anywhere. + protected override void OnExecute(){ + + } + + //Called once per frame while the action is active. + protected override void OnUpdate(){ + Vector3 usableVector3 = new Vector3(moveDirection.value.x * currentSpeed.value, moveDirection.value.y, moveDirection.value.z * currentSpeed.value); + agent.Move(Camera.main.transform.rotation * usableVector3 * Time.deltaTime); + + Debug.Log("Finalize Done"); + // EndAction(true); + } + + //Called when the task is disabled. + protected override void OnStop() { + + } + + //Called when the task is paused. + protected override void OnPause() { + + } + } +} \ No newline at end of file diff --git a/Assets/Scripts/Core/Graph Tasks/FinalizeMovement.cs.meta b/Assets/Scripts/Core/Graph Tasks/FinalizeMovement.cs.meta new file mode 100644 index 0000000..c2256de --- /dev/null +++ b/Assets/Scripts/Core/Graph Tasks/FinalizeMovement.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: fea4d34f26d30b24e8cb99acf1766b6f \ No newline at end of file diff --git a/Assets/Scripts/Core/Graph Tasks/ProcessMovement.cs b/Assets/Scripts/Core/Graph Tasks/ProcessMovement.cs deleted file mode 100644 index 826ef84..0000000 --- a/Assets/Scripts/Core/Graph Tasks/ProcessMovement.cs +++ /dev/null @@ -1,118 +0,0 @@ -using System; -using System.Collections; -using NodeCanvas.Framework; -using ParadoxNotion.Design; -using ParadoxNotion.Services; -using Unity.Cinemachine; -using Unity.Mathematics; -using UnityEngine; -using Reset.Movement; - -namespace Reset.Movement{ - public enum PlayerFacingDirection{ - Target = 0, - Movement, - MatchCamera, - Static - } -} - - -namespace NodeCanvas.Tasks.Actions { - - [Category("Reset/Movement")] - [Description("Finalizes movement and sends the final move commands to the controller")] - public class ProcessMovement : ActionTask{ - public BBParameter groundMoveDirection; - public BBParameter airMoveDirection; - - - - // Rotation - public BBParameter playerFacingDirection; - - - - - private float lastLookMagnitude; - - private Vector3 currentMoveDir; - - // References - private PlayerControls controls; - - - - //Use for initialization. This is called only once in the lifetime of the task. - //Return null if init was successfull. Return an error string otherwise - protected override string OnInit() { - // Append the late update method to actually happen on late update - - - - // Reference to controls - controls = agent.GetComponent(); - - return null; - } - - //This is called once each time the task is enabled. - //Call EndAction() to mark the action as finished, either in success or failure. - //EndAction can be called from anywhere. - protected override void OnExecute(){ - currentMoveDir = groundMoveDirection.value; - } - - //Called once per frame while the action is active. - protected override void OnUpdate(){ - - // Construct move direction - Vector3 finalMoveDir = Vector3.zero; - - // Change how input is managed based on facing state - currentMoveDir = Vector3.Slerp(currentMoveDir, groundMoveDirection.value, 1f * Time.deltaTime); // NOTE: This used to be t: currentRotSpeed * Time.deltaTime. - // See how it feels with a hard set value and go fro there. - - // Add input movement - if (agent.isGrounded){ - finalMoveDir += currentMoveDir; // + Vector3.down * .03f; - } else { - finalMoveDir += currentMoveDir; - } - - switch (playerFacingDirection.value) { - - } - - finalMoveDir += new Vector3(controls.rawMoveInput.x, 0f, controls.rawMoveInput.y); - - // Do final movement - if (agent.isGrounded) { - agent.Move((Quaternion.Euler(Camera.main.transform.rotation.eulerAngles.Flatten(0f, null, 0f)) * finalMoveDir) * Time.deltaTime); - } else { - agent.Move((Quaternion.Euler(Camera.main.transform.rotation.eulerAngles.Flatten(0f, null, 0f)) * finalMoveDir) * Time.deltaTime); - // agent.Move((finalMoveDir) * Time.deltaTime); - } - - // ???? Moved this above but don't remember if this needs to be here still - // if (agent.isGrounded) { - // jumpPower.value = 0f; - // } - EndAction(true); - - } - - // Gravity is processed in LateUpdate (added to MonoManager's onLateUpdate in OnInit()) - - - //Called when the task is disabled. - protected override void OnStop() { - EndAction(true); - } - - //Called when the task is paused. - protected override void OnPause() { - - } - } -} \ No newline at end of file diff --git a/Assets/Scripts/Core/Graph Tasks/ProcessGravity.cs b/Assets/Scripts/Core/Graph Tasks/UpdateGravityDirection.cs similarity index 74% rename from Assets/Scripts/Core/Graph Tasks/ProcessGravity.cs rename to Assets/Scripts/Core/Graph Tasks/UpdateGravityDirection.cs index 61f2e68..76d9297 100644 --- a/Assets/Scripts/Core/Graph Tasks/ProcessGravity.cs +++ b/Assets/Scripts/Core/Graph Tasks/UpdateGravityDirection.cs @@ -3,12 +3,12 @@ using ParadoxNotion.Design; using ParadoxNotion.Services; using UnityEngine; - namespace Reset.Movement { [Category("Reset/Movement")] [Description("Process Y-axis movement for the agent")] - public class ProcessGravity : ActionTask{ + // TODO: Rename to UpdateGravitytDirection + public class UpdateGravityDirection : ActionTask{ public BBParameter moveDirection; public BBParameter jumpPower; public BBParameter jumpPowerDecay; @@ -16,7 +16,6 @@ namespace Reset.Movement { [Space(5)] public BBParameter gravityAcceleration = 1f; public BBParameter gravityMax = 8f; - public BBParameter gravityPower; @@ -31,7 +30,6 @@ namespace Reset.Movement { //Call EndAction() to mark the action as finished, either in success or failure. //EndAction can be called from anywhere. protected override void OnExecute() { - } //Called once per frame while the action is active. @@ -40,19 +38,21 @@ namespace Reset.Movement { gravityPower.value += gravityAcceleration.value * Time.deltaTime; gravityPower.value = Mathf.Min(gravityPower.value, gravityMax.value); - Vector3 gravityMoveDirection; - - gravityMoveDirection = new(0f, jumpPower.value + (Physics.gravity.y * gravityPower.value), 0f); - - // Reset gravity power when grounded - agent.Move((gravityMoveDirection) * Time.deltaTime); - + // Apply a constant gravity if the player is grounded if (agent.isGrounded) { - gravityPower.value = 0f; - jumpPower.value = 0f; + gravityPower.value = .1f; } + // Create the gravity direction + float gravityMoveDirection = jumpPower.value + Physics.gravity.y * gravityPower.value; + + // Commit gravity to move direction, ignoring XZ since those are done in UpdateMovementDirection + moveDirection.value = new Vector3(moveDirection.value.x, gravityMoveDirection, moveDirection.value.z); + + Debug.Log("Gravity Done"); + EndAction(true); + } public void LateUpdate(){ // Decay jump power diff --git a/Assets/Scripts/Core/Graph Tasks/ProcessGravity.cs.meta b/Assets/Scripts/Core/Graph Tasks/UpdateGravityDirection.cs.meta similarity index 100% rename from Assets/Scripts/Core/Graph Tasks/ProcessGravity.cs.meta rename to Assets/Scripts/Core/Graph Tasks/UpdateGravityDirection.cs.meta diff --git a/Assets/Scripts/Core/Graph Tasks/UpdateMovementDirection.cs b/Assets/Scripts/Core/Graph Tasks/UpdateMovementDirection.cs new file mode 100644 index 0000000..2954cdb --- /dev/null +++ b/Assets/Scripts/Core/Graph Tasks/UpdateMovementDirection.cs @@ -0,0 +1,126 @@ +using System; +using System.Collections; +using NodeCanvas.Framework; +using ParadoxNotion.Design; +using ParadoxNotion.Services; +using Unity.Cinemachine; +using Unity.Mathematics; +using UnityEngine; +using Reset.Movement; + +namespace Reset.Movement{ + public enum PlayerFacingDirection{ + TowardsTarget = 0, + MatchForward, + MatchCamera, + Static + } +} + +namespace NodeCanvas.Tasks.Actions { + + [Category("Reset/Movement")] + [Description("Finalizes movement and sends the final move commands to the controller")] + // TODO: Rename to UpdateMovementDirection + public class UpdateMovementDirection : ActionTask{ + [ParadoxNotion.Design.Header("References")] + public BBParameter moveDirection; + // TODO: Remove this reference and let each copy of this use their own settings. + public BBParameter playerFacingDirection; + + [ParadoxNotion.Design.Header("Settings")] + public BBParameter accelerationSmoothing = 5f; + public BBParameter deaccelerationSmoothing = 5f; + public BBParameter deaccelerationCurve; + + public BBParameter directionChangeMinimumMagnitude; // Unused. Use to only make input change if it's over a certain input threshold. Maybe smoothing can affect this? + + private float lastLookMagnitude; + private Vector3 currentMoveDir; + + // References + private PlayerControls controls; + + //Use for initialization. This is called only once in the lifetime of the task. + //Return null if init was successfull. Return an error string otherwise + protected override string OnInit() { + // Reference to controls + controls = agent.GetComponent(); + + return null; + } + + //This is called once each time the task is enabled. + //Call EndAction() to mark the action as finished, either in success or failure. + //EndAction can be called from anywhere. + protected override void OnExecute(){ + // Initialize the smoothed direction with the value as is on input + // currentMoveDir = new Vector3(moveDirection.value.x, moveDirection.value.y, moveDirection.value.z); + } + + //Called once per frame while the action is active. + protected override void OnUpdate(){ + // Construct move direction + Vector3 targetDirection = moveDirection.value; + + // Get input value + Vector3 inputMovement = new Vector3(controls.rawMoveInput.x, 0f, controls.rawMoveInput.y); + + if (inputMovement.magnitude < .1f) { + inputMovement = Vector3.zero; + } + + // Change how movement is managed based on facing state + switch (playerFacingDirection.value) { + case PlayerFacingDirection.TowardsTarget: + break; + case PlayerFacingDirection.MatchForward: // TODO: Recomment + // targetDirection = agent.transform.forward * inputMovement.magnitude; + targetDirection = inputMovement; + break; + case PlayerFacingDirection.MatchCamera: + targetDirection = Quaternion.Euler(Camera.main.transform.forward.DirectionTo(agent.transform.forward)) * inputMovement; // NOTE: This used to be t: currentRotSpeed * Time.deltaTime. + // See how it feels with a hard set value and go fro there. + break; + case PlayerFacingDirection.Static: + break; + default: + throw new ArgumentOutOfRangeException(); + } + + // Remove Y from variables + Vector3 targetNoY = new Vector3(targetDirection.x, 0f, targetDirection.z); + Vector3 currentNoY = new Vector3(currentMoveDir.x, 0f, currentMoveDir.z); + + // Smooth movement + if (targetNoY.magnitude > currentNoY.magnitude) { + currentMoveDir = Vector3.Lerp(currentMoveDir, targetNoY,accelerationSmoothing.value * Time.deltaTime); + + } else { + float deaccelValue = deaccelerationCurve.value.Evaluate(inputMovement.magnitude); + + currentMoveDir = Vector3.Lerp(currentMoveDir, targetNoY, deaccelerationSmoothing.value * Time.deltaTime); + } + + + currentMoveDir.y = moveDirection.value.y; + // Commit move direction + moveDirection.value = currentMoveDir; + // Debug.Log(moveDirection.value); + EndAction(true); + } + + // Gravity is processed in LateUpdate (added to MonoManager's onLateUpdate in OnInit()) + + + //Called when the task is disabled. + protected override void OnStop() { + EndAction(true); + } + + //Called when the task is paused. + protected override void OnPause() { + + } + } +} \ No newline at end of file diff --git a/Assets/Scripts/Core/Graph Tasks/ProcessMovement.cs.meta b/Assets/Scripts/Core/Graph Tasks/UpdateMovementDirection.cs.meta similarity index 100% rename from Assets/Scripts/Core/Graph Tasks/ProcessMovement.cs.meta rename to Assets/Scripts/Core/Graph Tasks/UpdateMovementDirection.cs.meta diff --git a/Assets/Scripts/Core/Graph Tasks/UpdateMovementSpeed.cs b/Assets/Scripts/Core/Graph Tasks/UpdateMovementSpeed.cs new file mode 100644 index 0000000..0160aa9 --- /dev/null +++ b/Assets/Scripts/Core/Graph Tasks/UpdateMovementSpeed.cs @@ -0,0 +1,60 @@ +using System; +using NodeCanvas.Framework; +using ParadoxNotion.Design; +using UnityEngine; + + +namespace Reset.Movement { + + [Category("Reset/Movement")] + [Description("Updates the movespeed for this agent")] + public class UpdateMovementSpeed : ActionTask{ + public BBParameter target; + public BBParameter speed; + public BBParameter smoothing = 10f; + + private float currentSpeed; + + //Use for initialization. This is called only once in the lifetime of the task. + //Return null if init was successfull. Return an error string otherwise + protected override string OnInit() { + if (!speed.useBlackboard) { + Debug.LogError("This Update Movement Speed does not have it's current value attached to a Blackboard variable. Nothing will happen.", agent.gameObject); + } + + return null; + } + + //This is called once each time the task is enabled. + //Call EndAction() to mark the action as finished, either in success or failure. + //EndAction can be called from anywhere. + protected override void OnExecute(){ + // currentSpeed = speed.value; + + } + + //Called once per frame while the action is active. + protected override void OnUpdate(){ + currentSpeed = Mathf.Lerp(currentSpeed, target.value, smoothing.value * Time.deltaTime); + + speed.value = currentSpeed; + + if (Mathf.Abs(currentSpeed - speed.value) < .01f) { + + } + + Debug.Log("Speed Done"); + EndAction(true); + } + + //Called when the task is disabled. + protected override void OnStop() { + + } + + //Called when the task is paused. + protected override void OnPause() { + + } + } +} \ No newline at end of file diff --git a/Assets/Scripts/Core/Graph Tasks/UpdateMovementSpeed.cs.meta b/Assets/Scripts/Core/Graph Tasks/UpdateMovementSpeed.cs.meta new file mode 100644 index 0000000..34e234f --- /dev/null +++ b/Assets/Scripts/Core/Graph Tasks/UpdateMovementSpeed.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 6a4c5896d783ad845861edd0c9eea14b \ No newline at end of file diff --git a/Assets/Scripts/Core/Graph Tasks/ProcessRotation.cs b/Assets/Scripts/Core/Graph Tasks/UpdateRotation.cs similarity index 71% rename from Assets/Scripts/Core/Graph Tasks/ProcessRotation.cs rename to Assets/Scripts/Core/Graph Tasks/UpdateRotation.cs index 5ddfcbf..73bd643 100644 --- a/Assets/Scripts/Core/Graph Tasks/ProcessRotation.cs +++ b/Assets/Scripts/Core/Graph Tasks/UpdateRotation.cs @@ -8,7 +8,8 @@ using UnityEngine.TextCore.Text; namespace Reset.Player.Movement { [Category("Reset/Movement")] [Description("Finalizes the character rotation and commits it to the Transform")] - public class ProcessRotation : ActionTask { + // TODO: Rename to UpdateRotation + public class UpdateRotation : ActionTask { // Rotation public BBParameter moveDirection; @@ -25,24 +26,13 @@ namespace Reset.Player.Movement { [ShowIf("playerFacingDirection", 0)] public Vector3 rotationTargetPosition; - //Use for initialization. This is called only once in the lifetime of the task. //Return null if init was successfull. Return an error string otherwise protected override string OnInit() { - - controls = agent.GetComponent(); - return null; } - - //This is called once each time the task is enabled. - //Call EndAction() to mark the action as finished, either in success or failure. - //EndAction can be called from anywhere. - protected override void OnExecute() { - - } - + //Called once per frame while the action is active. protected override void OnUpdate() { // Calculate rotation speed @@ -51,26 +41,21 @@ namespace Reset.Player.Movement { // Set ingitial rotation power currentRotSpeed = rotationSpeed.value; + // Get input value + Vector3 inputMovement = new Vector3(controls.rawMoveInput.x, 0f, controls.rawMoveInput.y); + switch (playerFacingDirection.value) { - case PlayerFacingDirection.Target: + case PlayerFacingDirection.TowardsTarget: // Set rotation to just the direction of the target targetRotation = Quaternion.LookRotation((agent.transform.position.DirectionTo(rotationTargetPosition)).Flatten(null, 0)); break; - case PlayerFacingDirection.Movement: - // Check magnitude to avoid the "Look rotation viewing vector is zero" debug + case PlayerFacingDirection.MatchForward: + if (controls.rawMoveInput.magnitude < 0.01f) { break; } - // Set desired rotation to input direction, with respect to camera rotation - if (agent.isGrounded){ - if (controls.rawMoveInput.magnitude == 0) { break; } + targetRotation = Quaternion.LookRotation(inputMovement) * + Quaternion.Euler(Camera.main.transform.rotation.eulerAngles.Flatten(0f, null, 0f)); - targetRotation = Quaternion.LookRotation(currentMoveDir) * - Quaternion.Euler(Camera.main.transform.rotation.eulerAngles.Flatten(0f, null, 0f)); - } else { - if (moveDirection.value.magnitude == 0) { break; } - - targetRotation = Quaternion.LookRotation(moveDirection.value); - } break; case PlayerFacingDirection.MatchCamera: // Craft a new rotation that flattens the camera's rotation to the ground @@ -85,10 +70,10 @@ namespace Reset.Player.Movement { // Set final rotation agent.transform.rotation = Quaternion.Lerp(agent.transform.rotation, targetRotation, 10f * Time.deltaTime).Flatten(0, null, 0); + Debug.Log("Rotation Done"); EndAction(true); } - //Called when the task is disabled. protected override void OnStop() { diff --git a/Assets/Scripts/Core/Graph Tasks/ProcessRotation.cs.meta b/Assets/Scripts/Core/Graph Tasks/UpdateRotation.cs.meta similarity index 100% rename from Assets/Scripts/Core/Graph Tasks/ProcessRotation.cs.meta rename to Assets/Scripts/Core/Graph Tasks/UpdateRotation.cs.meta diff --git a/Assets/Scripts/Player/PlayerMovement.cs b/Assets/Scripts/Player/UnitMovementHandler.cs similarity index 100% rename from Assets/Scripts/Player/PlayerMovement.cs rename to Assets/Scripts/Player/UnitMovementHandler.cs diff --git a/Assets/Scripts/Player/PlayerMovement.cs.meta b/Assets/Scripts/Player/UnitMovementHandler.cs.meta similarity index 100% rename from Assets/Scripts/Player/PlayerMovement.cs.meta rename to Assets/Scripts/Player/UnitMovementHandler.cs.meta