docs.unity3d.com
Search Results for

    Show / Hide Table of Contents

    Control Agent Speed for corners

    You can take control of an agent's speed when a corner is too tight for them to make. To do this, you need to look ahead to the next corner and interpolate between maximum speed of the agent and the maximum corner speed based on agent's proximity to the corner and its angle.

    The following script implements this behavior. Add this component to the GameObject that has the NavMeshAgent component that you want to control. Try sample "9_agent_cornering_control" to see this behavior in action.

    using System;
    using UnityEngine;
    using UnityEngine.AI;
    using UnityEngine.Serialization;
    
    public class AgentSpeedController : MonoBehaviour
    {
        private NavMeshAgent m_Agent;
        private Vector3[] m_PathCorners = new Vector3[3];
    
        [SerializeField] private Transform m_Target;
    
        private float MaxSpeedInStraightLine = 5.0f;
        [SerializeField] private float MaxSpeedAtTightCorner = 0.1f;
        [SerializeField] private float DistanceThreshold = 0.5f;
    
        void OnEnable()
        {
            if (m_Agent == null)
                m_Agent = GetComponent<NavMeshAgent>();
    
            if (m_Agent != null)
            {
                m_Agent.SetDestination(m_Target.position);
                MaxSpeedInStraightLine = m_Agent.speed;
            }
        }
    
        void Update()
        {
            if (m_Agent == null)
                return;
    
            int numCorners = m_Agent.path.GetCornersNonAlloc(m_PathCorners);
    
            if (numCorners > 2)
            {
                // m_PathCorners[0] is the agent position path so find the angle of the next corner.
                Vector3 first = (m_PathCorners[1] - m_PathCorners[0]).normalized;
                Vector3 second = (m_PathCorners[2] - m_PathCorners[1]).normalized;
    
                // A 90 degree turn requires the biggest reduction in speed.
                float speedFactor = Mathf.Clamp01(Vector3.Dot(first, second));
    
                // Only apply speed reduction based on angle if distance to next corner is less than DistanceThreshold.
                float distance = Vector3.Distance(m_PathCorners[0], m_PathCorners[1]);
                float distanceRatio = Mathf.Clamp01(distance / DistanceThreshold);
    
                // Pick a new max speed based on the upcoming turn.
                float angleMaxSpeed = Mathf.Lerp(MaxSpeedAtTightCorner, MaxSpeedInStraightLine, speedFactor);
    
                m_Agent.speed = Mathf.Lerp(angleMaxSpeed, MaxSpeedInStraightLine, distanceRatio);
            }
            else
            {
                m_Agent.speed = MaxSpeedInStraightLine;
            }
        }
    
        private void OnValidate()
        {
            MaxSpeedAtTightCorner = Mathf.Clamp(MaxSpeedAtTightCorner, 0.0f, MaxSpeedInStraightLine);
        }
    }
    
    In This Article
    Back to top
    Copyright © 2025 Unity Technologies — Trademarks and terms of use
    • Legal
    • Privacy Policy
    • Cookie Policy
    • Do Not Sell or Share My Personal Information
    • Your Privacy Choices (Cookie Settings)