using UnityEngine;
public class MomentumController : MonoBehaviour
{
[Header("References")]
[SerializeField] private CharacterController controller;
[Header("Movement Settings")]
[SerializeField] private float moveSpeed = 15f; // Max movement speed
[SerializeField] private float dampenRate = 5f; // How quickly momentum slows when no input
[SerializeField] private float inputInfluence = 10f; // How fast input overrides existing velocity
[Header("Gravity Settings")]
[SerializeField] private float gravity = -9.81f;
[SerializeField] private float groundedGravity = -2f;
private Vector3 currentVelocity; // tracks players velocity
private Vector3 inputDirection;
private void Reset()
{
controller = GetComponent<CharacterController>();
}
private void Update()
{
HandleInput();
ApplyMovement();
}
private void HandleInput()
{
// grab our input
float h = Input.GetAxisRaw("Horizontal");
float v = Input.GetAxisRaw("Vertical");
Vector3 localInput = new Vector3(h, 0f, v).normalized;
inputDirection = transform.TransformDirection(localInput); // Convert to world space
inputDirection.y = 0f;
}
private void ApplyMovement()
{
// Horizontal momentum (X/Z)
Vector3 horizontal = new Vector3(currentVelocity.x, 0f, currentVelocity.z);
if (inputDirection != Vector3.zero)
{
Vector3 desiredVelocity = inputDirection * moveSpeed;
// Accelerate toward input
horizontal = Vector3.MoveTowards(horizontal, desiredVelocity, moveSpeed * inputInfluence * Time.deltaTime);
}
else
{
// Decelerate to zero
horizontal = Vector3.MoveTowards(horizontal, Vector3.zero, moveSpeed * dampenRate * Time.deltaTime);
}
// Vertical movement (Y)
float vertical = currentVelocity.y;
if (controller.isGrounded && vertical < 0f)
vertical = groundedGravity; // Stick to ground
else
vertical += gravity * Time.deltaTime; // Apply gravity
// Combine horizontal + vertical and move
currentVelocity = new Vector3(horizontal.x, vertical, horizontal.z);
controller.Move(currentVelocity * Time.deltaTime);
}
}