RiftMayhem/Assets/Scripts/Player/PlayerMovement.cs
Pedro Gomes 8db9d99a02 Input updates
- point and click
- WASD + mouse (WIP)
- Gamepad (WIP)
2025-01-16 19:33:19 +00:00

384 lines
11 KiB
C#

using Photon.Pun;
using UnityEngine;
using UnityEngine.AI;
public enum MovementType
{
PointAndClick,
DirectionalInput
}
[RequireComponent(typeof(NavMeshAgent))]
public class PlayerMovement : MonoBehaviour
{
[Header("Movement Settings")]
[SerializeField] private float lookSpeed = 10f;
[SerializeField] private float gamepadRotationSpeed = 300f;
[SerializeField] private float minimumInputThreshold = 0.1f;
[SerializeField] private MovementType movementType = MovementType.DirectionalInput;
[Header("Controller Settings")]
[SerializeField] private float gamepadDeadzone = 0.2f;
[SerializeField] private AnimationCurve gamepadInputCurve = AnimationCurve.Linear(0, 0, 1, 1);
[Header("Debug Visualization")]
[SerializeField] private bool showDebugVisuals = false;
private Transform target;
private NavMeshAgent agent;
private Vector3 direction = Vector3.zero;
private Quaternion lookRotation = Quaternion.identity;
private Camera mainCamera;
private Plane groundPlane;
private Vector2 lastGamepadAimInput;
private Vector3 lastAimDirection;
private bool isUsingGamepad;
private Vector3 currentMoveDirection;
private bool isMoving;
private PhotonView photonView;
private ProjectileSpawnLocationController aimController;
private Vector3 currentAimPoint;
private bool isAiming;
public Vector2 currentMovementDirection= new Vector2();
public Vector2 currentAimDirection = new Vector2();
public Vector2 lastAimDirection2 = new Vector2();
public Vector2 relativeMovementDirection = new Vector2();
private Vector3 mouseAimPoint;
private bool hasMouseAimPoint;
private void Awake()
{
agent = GetComponent<NavMeshAgent>();
photonView = GetComponent<PhotonView>();
mainCamera = Camera.main;
groundPlane = new Plane(Vector3.up, Vector3.zero);
aimController = GetComponentInChildren<ProjectileSpawnLocationController>();
lastAimDirection = transform.forward;
}
void Start()
{
if (!photonView.IsMine)
{
this.enabled = false;
return;
}
SetupAgentForDirectionalMovement();
}
private void Update()
{
if (movementType == MovementType.DirectionalInput)
{
DetectInputMethod();
// Handle movement first
HandleDirectionalMovement();
// Then handle aiming, with mouse taking priority
if (!isUsingGamepad)
{
HandleMouseAiming();
}
else
{
HandleGamepadAiming();
hasMouseAimPoint = false; // Reset mouse aim when using gamepad
}
HandleRelativeForAnimation();
}
else if (target != null)
{
HandlePointAndClickMovement();
}
// Handle channeled ability rotation
if (CastBarHandler.Instance.currentAbility is ChanneledAbility &&
CastBarHandler.Instance.castBar.activeSelf)
{
var channelAbility = (ChanneledAbility)CastBarHandler.Instance.currentAbility;
if (channelAbility.allowAiming)
{
InstantFaceCast(aimController.GetLookat());
}
}
}
private void DetectInputMethod()
{
Vector2 gamepadMove = new Vector2(
Input.GetAxisRaw(GameConstants.Input.HorizontalAxis),
Input.GetAxisRaw(GameConstants.Input.VerticalAxis));
Vector2 gamepadLook = new Vector2(
Input.GetAxisRaw(GameConstants.Input.AimHorizontalAxis),
Input.GetAxisRaw(GameConstants.Input.AimVerticalAxis));
// Check for mouse movement
if (Input.GetAxis("Mouse X") != 0 || Input.GetAxis("Mouse Y") != 0)
{
isUsingGamepad = false;
return;
}
// Check for gamepad input
if (gamepadMove.magnitude > gamepadDeadzone || gamepadLook.magnitude > gamepadDeadzone)
{
isUsingGamepad = true;
hasMouseAimPoint = false; // Reset mouse aim when using gamepad
}
}
private void HandleDirectionalMovement()
{
if (agent.isStopped) return;
currentMovementDirection = new Vector2(
Input.GetAxisRaw(GameConstants.Input.HorizontalAxis),
Input.GetAxisRaw(GameConstants.Input.VerticalAxis));
Vector3 cameraForward = mainCamera.transform.forward;
Vector3 cameraRight = mainCamera.transform.right;
cameraForward.y = 0f;
cameraRight.y = 0f;
cameraForward.Normalize();
cameraRight.Normalize();
currentMoveDirection = (cameraForward * currentMovementDirection.y +
cameraRight * currentMovementDirection.x).normalized;
isMoving = currentMoveDirection.magnitude >= minimumInputThreshold;
if (isMoving)
{
agent.SetDestination(transform.position + currentMoveDirection);
}
else
{
agent.velocity = Vector3.zero;
agent.SetDestination(transform.position);
}
// If we're using mouse aim, maintain character rotation even while moving
if (!isUsingGamepad && hasMouseAimPoint)
{
Vector3 aimDirection = (mouseAimPoint - transform.position).normalized;
if (aimDirection != Vector3.zero)
{
transform.rotation = Quaternion.LookRotation(aimDirection);
}
}
}
private void HandleAimingRotation()
{
if (isUsingGamepad)
{
HandleGamepadAiming();
}
else
{
HandleMouseAiming();
}
}
private void HandleGamepadAiming()
{
currentAimDirection = new Vector2(
Input.GetAxisRaw(GameConstants.Input.AimHorizontalAxis),
Input.GetAxisRaw(GameConstants.Input.AimVerticalAxis)
);
if (currentAimDirection.magnitude > gamepadDeadzone)
{
isAiming = true;
Vector3 cameraForward = mainCamera.transform.forward;
Vector3 cameraRight = mainCamera.transform.right;
cameraForward.y = 0f;
cameraRight.y = 0f;
Vector3 aimDirection = (cameraForward * currentAimDirection.y + cameraRight * currentAimDirection.x).normalized;
lastAimDirection = aimDirection;
lastAimDirection2.x = aimDirection.x;
lastAimDirection2.y = aimDirection.z;
Quaternion targetRotation = Quaternion.LookRotation(aimDirection);
transform.rotation = Quaternion.RotateTowards(
transform.rotation,
targetRotation,
gamepadRotationSpeed * Time.deltaTime
);
}
// Remove the else { isAiming = false; } - we want to maintain the last aim direction
// Instead, maintain the last valid aim direction
else if (lastAimDirection != Vector3.zero)
{
Quaternion targetRotation = Quaternion.LookRotation(lastAimDirection);
transform.rotation = Quaternion.RotateTowards(
transform.rotation,
targetRotation,
gamepadRotationSpeed * Time.deltaTime
);
}
}
private void HandleRelativeForAnimation()
{
// Calculate forward/backward movement relative to aim direction
relativeMovementDirection.y = Vector2.Dot(lastAimDirection2, currentMovementDirection);
// Calculate strafe movement relative to aim direction
// Cross product for left/right movement
relativeMovementDirection.x = lastAimDirection2.x * currentMovementDirection.y -
lastAimDirection2.y * currentMovementDirection.x;
}
private void HandleMouseAiming()
{
Ray ray = mainCamera.ScreenPointToRay(Input.mousePosition);
if (groundPlane.Raycast(ray, out float distance))
{
mouseAimPoint = ray.GetPoint(distance);
mouseAimPoint.y = transform.position.y;
hasMouseAimPoint = true;
Vector3 aimDirection = (mouseAimPoint - transform.position).normalized;
if (aimDirection != Vector3.zero)
{
lastAimDirection = aimDirection;
lastAimDirection2.x = aimDirection.x;
lastAimDirection2.y = aimDirection.z;
// Always update rotation when using mouse
transform.rotation = Quaternion.LookRotation(aimDirection);
}
}
}
private void HandlePointAndClickMovement()
{
agent.SetDestination(target.position);
FaceTarget();
}
private void SetupAgentForDirectionalMovement()
{
agent.updateRotation = false;
agent.stoppingDistance = 0f;
agent.acceleration = 100f;
agent.angularSpeed = 0f;
}
#region Public Methods
public void SetMovementType(MovementType type)
{
movementType = type;
if (movementType == MovementType.DirectionalInput)
{
SetupAgentForDirectionalMovement();
}
else
{
agent.updateRotation = true;
agent.stoppingDistance = 0.5f;
agent.acceleration = 8f;
agent.angularSpeed = 120f;
}
}
public void ToggleAgentMoving(bool busy)
{
agent.isStopped = busy;
if (busy)
{
agent.SetDestination(transform.position);
}
}
public void MoveToPoint(Vector3 point)
{
agent.SetDestination(point);
}
public void FollowTarget(Interactable newTarget)
{
agent.stoppingDistance = newTarget.radius * 0.8f;
agent.updateRotation = false;
target = newTarget.interactionTransform;
FaceTarget();
}
public void StopFollowingTarget()
{
agent.stoppingDistance = 0f;
agent.updateRotation = true;
target = null;
}
public void FaceAttack(int index)
{
if (target != null)
FaceTarget();
}
public void FaceTarget()
{
if (target == null) return;
direction = (target.position - transform.position).normalized;
direction.y = 0f;
lookRotation = Quaternion.LookRotation(direction);
transform.rotation = Quaternion.Slerp(transform.rotation, lookRotation, Time.deltaTime * lookSpeed);
}
public void InstantFaceTarget()
{
if (target != null)
{
direction = (target.position - transform.position).normalized;
direction.y = 0f;
lookRotation = Quaternion.LookRotation(direction);
transform.rotation = lookRotation;
}
}
public void InstantFaceCast(Vector3 lookat)
{
transform.forward = lookat;
}
public void StopLocomotion(int index)
{
StopFollowingTarget();
agent.SetDestination(transform.position);
}
#endregion
#region Debug
private void OnDrawGizmos()
{
if (!showDebugVisuals) return;
// Draw movement direction
Gizmos.color = Color.blue;
Gizmos.DrawRay(transform.position, currentMoveDirection * 2f);
// Draw aim direction
Gizmos.color = Color.red;
Gizmos.DrawRay(transform.position, lastAimDirection * 2f);
// Draw aim point if using mouse
if (!isUsingGamepad)
{
Gizmos.color = Color.yellow;
Gizmos.DrawWireSphere(currentAimPoint, 0.2f);
}
}
#endregion
}