Files
Click-PointRPG/Assets/Scripts/NavMeshMovementController.cs

104 lines
3.1 KiB
C#

using UnityEngine;
using UnityEngine.AI;
[RequireComponent(typeof(NavMeshAgent))]
public class NavMeshMovementController : MonoBehaviour
{
[Header("Movement")]
public float stopDistanceTolerance = 0.1f;
[Header("Rotation")]
public bool enableSmartRotation = true;
public float rotationSpeed = 10f;
NavMeshAgent agent;
Vector3 lastVelocity = Vector3.zero;
Vector3? lookAtTarget = null; // Optional target to face when stopped
void Awake()
{
agent = GetComponent<NavMeshAgent>();
if (agent != null)
{
agent.updateRotation = false; // We handle rotation manually
}
}
void Update()
{
if (agent == null) return;
// Update rotation based on movement direction
if (enableSmartRotation)
{
Vector3 vel = agent.velocity;
if (vel.sqrMagnitude > 0.01f)
{
// Moving - rotate toward movement direction
Quaternion targetRot = Quaternion.LookRotation(vel.normalized);
transform.rotation = Quaternion.Slerp(transform.rotation, targetRot, rotationSpeed * Time.deltaTime);
}
else if (lookAtTarget.HasValue)
{
// Stopped - rotate toward look target if set
Vector3 directionToTarget = (lookAtTarget.Value - transform.position).normalized;
if (directionToTarget.sqrMagnitude > 0.01f)
{
directionToTarget.y = 0; // Keep rotation on horizontal plane
Quaternion targetRot = Quaternion.LookRotation(directionToTarget);
transform.rotation = Quaternion.Slerp(transform.rotation, targetRot, rotationSpeed * Time.deltaTime);
}
}
lastVelocity = vel;
}
// Auto-stop when reaching destination
if (!agent.pathPending && agent.remainingDistance <= agent.stoppingDistance + stopDistanceTolerance)
{
agent.isStopped = true;
}
}
public void MoveTo(Vector3 worldPosition)
{
if (agent == null) return;
agent.isStopped = false;
agent.SetDestination(worldPosition);
lookAtTarget = null; // Clear look target when starting new movement
}
public void MoveToAndLookAt(Vector3 worldPosition, Vector3 lookTarget)
{
if (agent == null) return;
agent.isStopped = false;
agent.SetDestination(worldPosition);
lookAtTarget = lookTarget; // Set look target for when we arrive
}
public void Stop()
{
if (agent == null) return;
agent.isStopped = true;
}
public void SetLookTarget(Vector3 target)
{
lookAtTarget = target;
}
public void ClearLookTarget()
{
lookAtTarget = null;
}
public bool IsAtDestination(float tolerance = 0.1f)
{
if (agent == null) return true;
return !agent.pathPending && agent.remainingDistance <= agent.stoppingDistance + tolerance;
}
public Vector3 GetVelocity() => lastVelocity;
public float GetSpeed() => agent != null ? agent.velocity.magnitude : 0f;
}