Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 13 Next capture
2021 2022 2023
1 capture
13 Jun 22 - 13 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
0
Question by a52 · Aug 05, 2021 at 05:24 AM · navmeshagentpathfinding

Stopping a NavMeshAgent gradually without loss of accuracy

Got a character that moves around based on where the player clicks, using the NavMesh system for pathfinding and movement and such. I've just hooked up a simple animation that's tied to the speed of the character, and that made me notice that while it speeds up nice and gradually, it stops almost instantly, with a noticeable jerk in animation as it snaps straight from its run animation to its idle animation.

There's the stopping distance parameter, but that adds a lack of accuracy -- not only is the stopping position not guaranteed, but if you try to move short distances at a time, it just won't happen. Since said character is pretty small, this is a problem!

Turning off Auto Braking doesn't really work either -- for whatever reason the character constantly oscillates between two points once it reaches the target -- maybe trying and failing to correct overshoot?

Anyway, is there a way to set some deceleration parameter, rather than stopping distance? So it looks ahead to some degree and decelerates roughly on time, rather than stopping instantly and prematurely.

Is my best bet here to manually adjust the speed as the character gets close to the target? Or is there an easier option?

Comment
Add comment
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

1 Reply

· Add your reply
  • Sort: 
avatar image
0

Answer by a52 · Aug 06, 2021 at 01:30 AM

I'd still like an easy answer implemented in Unity itself, but for now I've come up with the following code in the object that interacts with the NavMeshAgent component (this is just what's relevant, the actual object does other stuff as well):

 [RequireComponent(typeof(NavMeshAgent))]
 public class PlayerMotor: MonoBehaviour {
 
     private NavMeshAgent _agent;
 
     private float _defaultSpeed;
 
     private bool _decelerating;
 
     void Start() {
         _agent = GetComponent<NavMeshAgent>();
         _defaultSpeed = _agent.speed;
     }
 
     private void Update() {
         // slowly decelerate to avoid NavMeshAgent's instant stops
         if (_decelerating) {
             _agent.speed -= _agent.acceleration * Time.deltaTime;
             _decelerating = WithinBrakingDistanceOfTarget();
         }
         // if we need to start accelerating, do so, and set the speed to the correct value to start with
         else if (_agent.stoppingDistance == 0 && WithinBrakingDistanceOfTarget()) {
             _decelerating = true;
             _agent.speed = (float) (_agent.acceleration * Math.Sqrt(2 * _agent.remainingDistance / _agent.acceleration));
         }
         // reset if we've somehow moved away from the target or the target has changed/etc, allowing the agent
         // to again accelerate and decelerate at will
         else if (_agent.speed != _defaultSpeed) {
             _agent.speed = _defaultSpeed;
         }
     }
 
     private bool WithinBrakingDistanceOfTarget() {
         return _agent.remainingDistance <= 0.5f * _agent.velocity.sqrMagnitude / _agent.acceleration;
     }

A few notes:

  1. If you've got anything that depends on the NavMeshAgent's speed value (animations that depend on the current speed as a fraction of the maximum speed, for example), it will either have to refer to PlayerMotor's _defaultSpeed value or cache a copy of its own in Start(), as this obviously messes with it.

  2. This is disabled when stopping distance is not set to zero, as it will usually stop gradually on its own in that case, and I also wouldn't want the two systems "fighting". (At the moment my stopping distance changes dynamically, and is used whenever the player selects an object in order to tell the player character how close to the object to get. I may rework that so it's just its own "targetRadius" parameter, and stopping distance remains constant, so that my acceleration code is always what handles braking)

  3. This could (and I'd imagine should) probably be put into a Coroutine, just haven't done that yet.

Comment
Add comment · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

130 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

Way to ignore specific navmeshobstacles for specific navmeshagent when creating path? 0 Answers

How to sample a point on a navMesh Agent path 0 Answers

Is it possible to assign a custom path to a NavMeshAgent? 0 Answers

Custom Ai Movement using Unity's pathfinding 1 Answer

navmesh.sampleposition works strangely, what is going on here? 0 Answers


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges