From f1dee5c0e4ca06e3087618251198995766f836a0 Mon Sep 17 00:00:00 2001 From: Chris Date: Thu, 23 Oct 2025 21:55:14 -0400 Subject: [PATCH] improv: UnitMovementHandler.cs uses IUnitDirectionProvider.cs for direction instead of input direction directly --- .../Scripts/Units/Enemy/EnemyPathfinding.cs | 74 +++++++++++++++++++ .../Units/Enemy/EnemyPathfinding.cs.meta | 3 + .../Scripts/Units/IUnitDirectionProvider.cs | 2 +- Assets/Scripts/Units/PlayerControls.cs | 7 +- Assets/Scripts/Units/UnitMovementHandler.cs | 16 ++-- 5 files changed, 91 insertions(+), 11 deletions(-) create mode 100644 Assets/Scripts/Units/Enemy/EnemyPathfinding.cs create mode 100644 Assets/Scripts/Units/Enemy/EnemyPathfinding.cs.meta diff --git a/Assets/Scripts/Units/Enemy/EnemyPathfinding.cs b/Assets/Scripts/Units/Enemy/EnemyPathfinding.cs new file mode 100644 index 0000000..8025683 --- /dev/null +++ b/Assets/Scripts/Units/Enemy/EnemyPathfinding.cs @@ -0,0 +1,74 @@ +using Pathfinding; +using UnityEngine; + +namespace Reset.Units{ + public class EnemyPathfinding : MonoBehaviour, IUnitDirectionProvider{ + public Vector2 Direction{ get; set; } + + public Transform targetPosition; + + private Seeker seeker; + + public float nextWaypointDistance = 3; + private int currentWaypoint; + + public Path path; + public bool reachedEndOfPath; + + public void Start(){ + seeker = GetComponent(); + // If you are writing a 2D game you should remove this line + // and use the alternative way to move sugggested further below. + + seeker.StartPath(transform.position, targetPosition.position, OnPathComplete); + } + + public void OnPathComplete(Path p){ + if (!p.error) { + path = p; + // Reset the waypoint counter so that we start to move towards the first point in the path + currentWaypoint = 0; + } + } + + public void Update(){ + if (path == null) { + // We have no path to follow yet, so don't do anything + return; + } + + reachedEndOfPath = false; + // The distance to the next waypoint in the path + float distanceToWaypoint; + while (true) { + // If you want maximum performance you can check the squared distance instead to get rid of a + // square root calculation. But that is outside the scope of this tutorial. + distanceToWaypoint = Vector3.Distance(transform.position, path.vectorPath[currentWaypoint]); + if (distanceToWaypoint < nextWaypointDistance) { + // Check if there is another waypoint or if we have reached the end of the path + if (currentWaypoint + 1 < path.vectorPath.Count) { + currentWaypoint++; + } else { + // Set a status variable to indicate that the agent has reached the end of the path. + // You can use this to trigger some special code if your game requires that. + reachedEndOfPath = true; + break; + } + } else { + break; + } + } + + // Slow down smoothly upon approaching the end of the path + // This value will smoothly go from 1 to 0 as the agent approaches the last waypoint in the path. + var speedFactor = reachedEndOfPath ? Mathf.Sqrt(distanceToWaypoint / nextWaypointDistance) : 1f; + + // Direction to the next waypoint + // Normalize it so that it has a length of 1 world unit + Vector3 dirToPoint = (path.vectorPath[currentWaypoint] - transform.position).normalized * speedFactor; + + Direction = dirToPoint.ToVector2(); + } + } + +} \ No newline at end of file diff --git a/Assets/Scripts/Units/Enemy/EnemyPathfinding.cs.meta b/Assets/Scripts/Units/Enemy/EnemyPathfinding.cs.meta new file mode 100644 index 0000000..7641310 --- /dev/null +++ b/Assets/Scripts/Units/Enemy/EnemyPathfinding.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 1a67969fa2454c8f8b5c84c31c95d890 +timeCreated: 1761268522 \ No newline at end of file diff --git a/Assets/Scripts/Units/IUnitDirectionProvider.cs b/Assets/Scripts/Units/IUnitDirectionProvider.cs index d4b3203..a5329ad 100644 --- a/Assets/Scripts/Units/IUnitDirectionProvider.cs +++ b/Assets/Scripts/Units/IUnitDirectionProvider.cs @@ -2,6 +2,6 @@ namespace Reset.Units{ public interface IUnitDirectionProvider{ - public Vector2 direction{ get; set; } + public Vector2 Direction{ get; } } } \ No newline at end of file diff --git a/Assets/Scripts/Units/PlayerControls.cs b/Assets/Scripts/Units/PlayerControls.cs index c403f07..2efc6ff 100644 --- a/Assets/Scripts/Units/PlayerControls.cs +++ b/Assets/Scripts/Units/PlayerControls.cs @@ -13,14 +13,17 @@ using Sirenix.OdinInspector; using Unity.Cinemachine; using Object = UnityEngine.Object; -public class PlayerControls : MonoBehaviour{ +public class PlayerControls : MonoBehaviour, IUnitDirectionProvider{ // References private Player thisPlayer; private PlayerInput input; private SignalDefinition inputSignal; private SignalDefinition blockSignal; - + + // IUnitDirectionProvider + public Vector2 Direction => rawMoveInput; + // TODO: Turn these into accessors public Vector2 rawMoveInput; public Vector2 rawLookInput; diff --git a/Assets/Scripts/Units/UnitMovementHandler.cs b/Assets/Scripts/Units/UnitMovementHandler.cs index ec3d529..2389af5 100644 --- a/Assets/Scripts/Units/UnitMovementHandler.cs +++ b/Assets/Scripts/Units/UnitMovementHandler.cs @@ -19,7 +19,7 @@ namespace Reset.Units{ // References private CharacterController controller; - private PlayerControls controls; + private IUnitDirectionProvider directionProvider; private IUnitTargetProvider targetProvider; // Movement Data @@ -30,7 +30,7 @@ namespace Reset.Units{ void Awake(){ controller = GetComponent(); - controls = GetComponent(); + directionProvider = GetComponent(); targetProvider = GetComponent(); InitAllSettings(); @@ -59,7 +59,7 @@ namespace Reset.Units{ // Update the direction, called every frame private void UpdateCurrentDirection(){ // Get input value - Vector2 targetDirection = new Vector2(controls.rawMoveInput.x, controls.rawMoveInput.y); + Vector2 targetDirection = new Vector2(directionProvider.Direction.x, directionProvider.Direction.y); // Rotate input by camera rotation (instead of rotating the output direction by camera rotation) targetDirection = (Camera.main.transform.rotation * targetDirection.ToVector3()).ToVector2(); @@ -97,7 +97,7 @@ namespace Reset.Units{ newDirection = Vector2.SmoothDamp(currentDirection, targetDirection, ref refVelocityDirectionChangingHardness, data.directionChangingSoftness.Value * data.airDirectionDecay.Value * Time.deltaTime); } - newDirection = Vector3.Slerp(resolvedMovement.moveDirection.World, newDirection, controls.rawMoveInput.magnitude); + newDirection = Vector3.Slerp(resolvedMovement.moveDirection.World, newDirection, directionProvider.Direction.magnitude); // Commit the new direction resolvedMovement.moveDirection.World = newDirection; @@ -108,7 +108,7 @@ namespace Reset.Units{ // ""Smooth"" the speed float smoothedSpeed; - if (resolvedMovement.moveDirection.Local.magnitude < controls.rawMoveInput.magnitude) { + if (resolvedMovement.moveDirection.Local.magnitude < directionProvider.Direction.magnitude) { smoothedSpeed = Mathf.MoveTowards(resolvedMovement.moveSpeed, data.moveSpeed.Value, data.acceleration.Value * Time.deltaTime); } else { smoothedSpeed = Mathf.MoveTowards(resolvedMovement.moveSpeed, 0f, data.deacceleration.Value * Time.deltaTime); @@ -135,7 +135,7 @@ namespace Reset.Units{ // Update the rotation, called every frame private void UpdateCurrentRotation(){ // Get input value - Vector3 inputMovement = new Vector3(controls.rawMoveInput.x, 0f, controls.rawMoveInput.y); + Vector3 inputMovement = new Vector3(directionProvider.Direction.x, 0f, directionProvider.Direction.y); Quaternion targetRotation = Quaternion.identity; // Switch the desired rotation based on current movement setting @@ -162,7 +162,7 @@ namespace Reset.Units{ break; case PlayerFacingDirection.MatchInput: // Look towards the input direction- similar to Momentum but snappier - if (controls.rawMoveInput.magnitude < 0.05f) { break; } + if (directionProvider.Direction.magnitude < 0.05f) { break; } targetRotation = Camera.main.transform.rotation * Quaternion.LookRotation(inputMovement); break; @@ -181,7 +181,7 @@ namespace Reset.Units{ // Add the current input into the created rotation if (data.facingDirection.Value == PlayerFacingDirection.MatchCamera || data.facingDirection.Value == PlayerFacingDirection.TowardsTarget) { resolvedMovement.rotation = targetRotation; - } else if (controls.rawMoveInput.sqrMagnitude > .1){ + } else if (directionProvider.Direction.sqrMagnitude > .1){ resolvedMovement.rotation = targetRotation; }