Search Unity

Dynamic Obstacle Avoidance

Discussion in 'Assets and Asset Store' started by username_unity_of_my, Apr 25, 2017.

  1. username_unity_of_my

    username_unity_of_my

    Joined:
    Feb 24, 2015
    Posts:
    330
    Hello!

    I released new package on Asset Store. Its Dynamic Obstacle Avoidance package.
    Its usefull for using on npc characters, movable objects without nav mesh carving and behaviour that need local avoidance.


    Here is demo video:





    ... and here is link to demos so you can test how it works.
    DEMO/S

    Usage:
    In this demos I made it so chracters can push objects if there is no other way of traversing through obstacle but you assign high repulsion value so characters will not go near. It all depends how you tweek certain object.
    Also you can assign character more persistance value in path following so it will more likely to go through obstacles or asssign lower persistance to make them less likely to go through.

    You can get it at: AssetStorePage

    Thank you !
     
    Firlefanz73 likes this.
  2. motatob

    motatob

    Joined:
    Nov 20, 2012
    Posts:
    11
    WOW nice asset!
    How easy is it to add the obstacle avoidance to mercenaries/fallowers or enemy that is already in an RPG project???
     
  3. username_unity_of_my

    username_unity_of_my

    Joined:
    Feb 24, 2015
    Posts:
    330

    Hello,
    On objects all it takes is to put 'Obstacle' component on it

    On npcs, you have to implement IAvoider interface and
    add:
    ' ObstacleManager.CalculateObstacleAvoidance(ref move, this);'
    after all movement ( after path is calculated, being it NavMesh or other )

    There is also an option to smooth npc avoidance if you like.
    For that you can copy code from examples which is between SMOOTH_MOVEMENT macro.
    Look at the _add_local_avoidance() method, its the main one.

    Note that in some npc scripts I set movement y to zero because npcs are walking on ground and physics is responsible for Y axis movement ( jumping, falling )
    But you dont have to do that if npc if flying.
     
    Last edited: May 28, 2018
  4. motatob

    motatob

    Joined:
    Nov 20, 2012
    Posts:
    11
    I definitely need this for all my fallowers/mercenaries and enemies, hope this helps make them smarter..
    Thank You..
     
  5. betaFlux

    betaFlux

    Joined:
    Jan 7, 2013
    Posts:
    112
    And did it help?

    Can anyone tell how well it works with ai agents controlled by mecanim?

    I'm making my mecanim agents move via:

    Code (CSharp):
    1. ai.navAgent.speed = (_animator.deltaPosition / Time.deltaTime).magnitude;
    Does it make any difference how the NavMeshAgent is controlled or do I need to rewrite some code?
     
    Last edited: May 30, 2018
  6. motatob

    motatob

    Joined:
    Nov 20, 2012
    Posts:
    11
    Not sure yet, still have one more question to ask the developer.
     
  7. motatob

    motatob

    Joined:
    Nov 20, 2012
    Posts:
    11
    Hi, I have one more question if you don't mind. Will this support automatic integration with an existing movement system script that is already being used on an enemy???

    Thank You again..
     
  8. username_unity_of_my

    username_unity_of_my

    Joined:
    Feb 24, 2015
    Posts:
    330
    It doesn't matter what movement calculations you are using as long as you put avoidance method/s last ( after movement)
    It takes existing movement vector ( velocity ) and modify it to take avoidance into account.
     
  9. motatob

    motatob

    Joined:
    Nov 20, 2012
    Posts:
    11
    Allright sir, I'm making my purchase today..
     
  10. betaFlux

    betaFlux

    Joined:
    Jan 7, 2013
    Posts:
    112
    Please let us now how it goes. I just can't get it to work with mecanim (without root motion).

    This is how I handle the ai movement:
    Code (CSharp):
    1.  
    2. void OnAnimatorMove() {
    3.  
    4.      RotateTo(orientationDir);
    5.  
    6.      Vector3 localDesiredVelocity = transform.InverseTransformDirection(navAgent.steeringTarget - this.transform.position).normalized * movementSpeed;
    7.  
    8.      animator.SetBool("Move", (Arrived() == false));
    9.  
    10.      navAgent.speed = (animator.deltaPosition / Time.deltaTime).magnitude;
    11.  
    12.      animator.SetFloat("X", localDesiredVelocity.x);
    13.      animator.SetFloat("Z", localDesiredVelocity.z);
    14. }
    What would be the best way to integrate the avoidance velocity? Sorry I just can't get my head around this.
     
    Last edited: Jun 4, 2018
  11. username_unity_of_my

    username_unity_of_my

    Joined:
    Feb 24, 2015
    Posts:
    330

    Hi,
    Ok, try this:
    get world move direction which is:
    Vector3 direction= (navAgent.steeringTarget - this.transform.position).normalized.
    After that add ObstacleManager.CalculateObstacleAvoidynce( ref direction, this);
    Then you'll get modified direction for avoidance.
    And than you can continue like you do:

    Vector3 localDesiredVelocity = transform.InverseTransformDirection(direction).normalized * movementSpeed;

    animator.SetBool("Move", (Arrived() == false));

    navAgent.speed = (animator.deltaPosition / Time.deltaTime).magnitude;

    animator.SetFloat("X", localDesiredVelocity.x);
    animator.SetFloat("Z", localDesiredVelocity.z);
     
  12. betaFlux

    betaFlux

    Joined:
    Jan 7, 2013
    Posts:
    112
    Thanks, this helps. Now the actors are at least playing the correct directional move animations, however they still move along the path without avoidance. I think it's because the avoidance velocity isn't added to the actual navmeshAgent velocity which moves the ai? I've looked through the example scripts but couldn't find anything helpful for my case. Can you tell me what I need to add?
     
  13. username_unity_of_my

    username_unity_of_my

    Joined:
    Feb 24, 2015
    Posts:
    330

    In the start or awake method set navAgent.updatePosition = false;
    now calculate path manualy:
    create this method:
    Code (CSharp):
    1.  
    2. NavMeshPath path;
    3.         protected bool calculate_path(NavMeshAgent navAgent, Vector3 destination, ref Vector3 moveDirection)
    4.         {
    5.             if (path == null) path = new NavMeshPath();
    6.  
    7.             Vector3 transformPosition = transform.position;
    8.             if (!navAgent.CalculatePath(destination, path))
    9.                 return false;
    10.  
    11.             if (path.status != UnityEngine.AI.NavMeshPathStatus.PathComplete)
    12.                 return false;
    13.  
    14.             if (path.corners.Length < 2)
    15.                 return false;
    16.  
    17.  
    18.             Vector3 currentWaypoint = path.corners[1];
    19.             Vector3 toTarget = currentWaypoint - transformPosition;
    20.             moveDirection += toTarget.normalized;
    21.  
    22.             return true;
    23.         }
    24.  
    now change code with this:
    Vector3 movement = Vector3.zero;
    calculate_path(navAgent, DESTINATION_VECTOR, ref movement); // calculating nav mesh path
    ObstacleManager.CalculateObstacleAvoidance(ref movement, this); // adding avoidance

    rest like it was:

    Vector3 localDesiredVelocity = transform.InverseTransformDirection(movement).normalized * movementSpeed;

    animator.SetBool("Move", (Arrived() == false));

    navAgent.speed = (animator.deltaPosition / Time.deltaTime).magnitude;

    animator.SetFloat("X", localDesiredVelocity.x);
    animator.SetFloat("Z", localDesiredVelocity.z);
     
  14. betaFlux

    betaFlux

    Joined:
    Jan 7, 2013
    Posts:
    112
    Thank you for your help! I did what you posted but can't get it to work. Now the navagent moves but the animator avatar won't follow, it's keeping its initial position doing animations and turning like it's supposed to but not changing position.

    I'll study the example scripts some more, maybe i'm overlooking a simple thing.
     
  15. username_unity_of_my

    username_unity_of_my

    Joined:
    Feb 24, 2015
    Posts:
    330
    Oh yes, your character was moved by nav agent.
    Lets try implement root motion controlled by script in OnAnimatorMove method
    Add this code in OnAnimatorMove():
    Code (CSharp):
    1.      
    2. if (Time.deltaTime > 0 )
    3.             {
    4.                 Vector3 v = (m_Animator.deltaPosition * moveSpeedMultiplier ) / Time.deltaTime;
    5.            
    6.  // IF USING RIGIDBODY
    7.                 if (m_Rigidbody)
    8.                 {
    9.                     if (m_Rigidbody.isKinematic)
    10.                         transform.position += v * Time.deltaTime;
    11.                     else
    12.                     {
    13.                         if (m_Rigidbody.useGravity) v.y = m_Rigidbody.velocity.y;
    14.                         m_Rigidbody.velocity = v;
    15.                     }
    16.                 }
    17.                 // ELSE
    18.                 else
    19.                 {
    20.                     transform.position += v * Time.deltaTime;
    21.                 }
    22.             }
    23.  
    Just make sure that Root Transform Position ( XZ )is not baked into pose.

    Im my script 'CharacterObstacleAvoidanceAgent' you can see how I implemented NavMeshAgent and obstacle avoidance.
    Disabling NavMeshAgent update, calculating path manualy ( like here ) and moving character by root motion by script.
    Look in 'CharacterObstacleAvoidanceAgent.cs' and 'ThirdPersonCharacter.cs'
     
    Last edited: Jun 6, 2018
  16. betaFlux

    betaFlux

    Joined:
    Jan 7, 2013
    Posts:
    112
    Thank you very much for your time. The thing is that I try to avoid rootmotion because the movement is too unprecise for my project.
    That's why I decided to go with something like:
    Code (CSharp):
    1. navAgent.speed = (animator.deltaPosition / Time.deltaTime).magnitude
    Sorry I should have mentioned this before.

    But with all you posted I can make DOA easily work in my other non-mecanim projects. Thanks for your help and this great asset!
     
  17. dienat

    dienat

    Joined:
    May 27, 2016
    Posts:
    417
    i also dont use root motion, just the navmeshagent using the animator deltaposition like is show in the previous post. I dont have clear if it works with this solution.
     
  18. username_unity_of_my

    username_unity_of_my

    Joined:
    Feb 24, 2015
    Posts:
    330
    To use on NavMeshAgent you have to find the way to modify agent's position to include avoidance direction.
    I did it by using NavMeshAgent.nextPosition.

    I'll update the package with example of it.
     
  19. joferjoe

    joferjoe

    Joined:
    Feb 2, 2016
    Posts:
    95
    Was looking at this package and it looks great, do i need to use navmesh with this, or can they handle basic tracking and avoidance without it?
     
  20. username_unity_of_my

    username_unity_of_my

    Joined:
    Feb 24, 2015
    Posts:
    330
    No nav mesh not required.
    Examples are using nav meshes but I can be used without it.
    Core obstacle avoidance do not take nav mesh into calculations.
     
  21. Firlefanz73

    Firlefanz73

    Joined:
    Apr 2, 2015
    Posts:
    1,316
    Hello,

    I am working on a 3d rpg, which has a landscape just made of chunks and each chunks contains blocks (like Minecraft... but with 45° slopes).
    Each chunk has one collider and one mesh where many blocks are "melted" together.

    So I cannot add a "Obstacle" script to each block, but I could add it to each chunk? Would this be possible or is it to slow then and not detecting ground anymore etc?

    Or can it just works using raycasts and "all in one" chunk colliders?

    Thanks a lot! This Looks very interesting :)
     
  22. username_unity_of_my

    username_unity_of_my

    Joined:
    Feb 24, 2015
    Posts:
    330
    Obstacle does not need to have collider attached.
    It can detect object by point ( position of object ), sphere ( position + radius ) or line ( two points ) and it calculates avoidance by those values.
    You can add Obstacle to all blocks or you can add on runtime when needed to object which needs it.
    Just remember to add newly created obstacle to ObstacleManager.obstacles list
     
  23. joferjoe

    joferjoe

    Joined:
    Feb 2, 2016
    Posts:
    95
    excellent thanks, is this usable for voxel terrains and navigating around walls and under caves (if they can see) or is this too much for this system?
     
  24. username_unity_of_my

    username_unity_of_my

    Joined:
    Feb 24, 2015
    Posts:
    330
    Hmmm, It can avoid convex shapes. This is not a pathfinding system.Its meant to work along with or without pathfinding systems.
     
  25. username_unity_of_my

    username_unity_of_my

    Joined:
    Feb 24, 2015
    Posts:
    330
    Hello,

    I released an update in which I added an example on how to use avoidance with Unity's nav mesh agent.

    Thx.
     
  26. bingofly

    bingofly

    Joined:
    Sep 15, 2018
    Posts:
    27
    Just bought it. I Test it by myself, the NPC is jitter and rotating like a fool, I can't find the reason.
     
  27. username_unity_of_my

    username_unity_of_my

    Joined:
    Feb 24, 2015
    Posts:
    330
    Can you be more precise?
    Is it problem with any demo scene?
    What type of character is causing you problems - one with nav mesh agent or one without ?
    Is creating new bot is causing problems?
    Does it show any errors?
    ...
     
  28. jh092

    jh092

    Joined:
    Sep 2, 2018
    Posts:
    55
    Hello, I have just purchased your component, thank you I am making good progress.

    May I ask two questions please...

    1. How can I tell when my NPC has "arrived" at Target (I am not using navmesh or anything) ?

    2. How can I move my agent. I am not using physics or rigidbody or velocity as in your BasicObstacleAvoidance example, just a simple cube I want to move and rotate in the correct direction on the way to the Target.

    thanks again and best wishes from Australia

    John
     
  29. username_unity_of_my

    username_unity_of_my

    Joined:
    Feb 24, 2015
    Posts:
    330
    Hi,

    1. Your NPC is 'arrived' if your NPC distance to target is lesser or equal to assigned range.
    In 'BasicObstacleAvoidance' that is 'waypoint distance' variable.

    2. You can move your agent by assigning direction ( plus speed ) to current position.
    So, calculate direction and, before you add to NPC position, let direction go through obstacle avoidance calc.
    ( ObstacleManager.CalculateObstacleAvoidance(...); ) which will give you modified direction.

    There is example of this in 'BasicObstacleAvoidance.cs'.
     
  30. Tomasz_Pasterski

    Tomasz_Pasterski

    Joined:
    Aug 12, 2014
    Posts:
    99
  31. username_unity_of_my

    username_unity_of_my

    Joined:
    Feb 24, 2015
    Posts:
    330
    Hi,

    I created this to resolve that kind of problems.
    But to be sure, maybe best thing for you is to try demos and see if it is the behaviour you are looking for.

    Thank you!
     
  32. Tomasz_Pasterski

    Tomasz_Pasterski

    Joined:
    Aug 12, 2014
    Posts:
    99
    I already tried behaviour in follow example and it is what i look for.
    But can you precise if i must interfere much into my project using your asset? It is something i can add to my agents and they start to properly avoid each other?
     
  33. username_unity_of_my

    username_unity_of_my

    Joined:
    Feb 24, 2015
    Posts:
    330
    Well, I would say not much.
    Unity NavMesh is not needed - there are examples in project where I set dynamic avoidance move.Y result to zero to make object use navmesh y position. You dont need to do that if in space for instance.
    Avoidance is calculated last and you can apply to your existing moving velocity.
     
  34. Mythran

    Mythran

    Joined:
    Feb 26, 2013
    Posts:
    85
    Hey,
    I have the same question as @Tomasz_Pasterski, i have a npc that uses navmesh, how hard is it to implement this with my character, is it a matter of adding a component to the character and it will avoid, or will it be necessary to adjust the code of my npc to implement the avoidance?
    Another question is, must be added the obstacle component to every object desired the npc to avoid or is there a layer allowing the npc to avoid objects with selected layers?

    Thank you!
     
  35. Milionario

    Milionario

    Joined:
    Feb 21, 2014
    Posts:
    138
    See my video, this just doesn't work as advertised.

     
  36. username_unity_of_my

    username_unity_of_my

    Joined:
    Feb 24, 2015
    Posts:
    330
    Hello,
    I didnt see you created nav mesh on new scene you copied the contents of test scene.
    Bots use nav mesh to walk on.

    Also there is some documentation in docs folder.
     
    SteveKouts likes this.
  37. Mythran

    Mythran

    Joined:
    Feb 26, 2013
    Posts:
    85
    Too late, i bought it 2 days ago, but thanks.
    @username_unity_of_my, i'm having a problem with the detection. When the character happen to go in the same direction (wich in my case happens alot) and the detection kicks in, the characters just stick together and keep going and going in the average direction of both, never evading one from the other.
    If the explanation is not understandable i can send a video.
    Can you do something about this?

    Thanks!
     
  38. username_unity_of_my

    username_unity_of_my

    Joined:
    Feb 24, 2015
    Posts:
    330
    That usually happens when there is no zero friction material set on the character collider.
    Did you put zero friction mat on characters?
    Also a randomizing small differences in stats would help against that. ( So bots dont have exactly the same avoidance parameters )
     
    Last edited: Feb 25, 2021
  39. Mythran

    Mythran

    Joined:
    Feb 26, 2013
    Posts:
    85
    They actually had no material at all. Changed it to zero friction on all npc's and it keeps the same.
    It seems to me that the avoidence direction cross one another, and they keep avoiding, but since they are colliding, they keep moving in the same direction colliding with one another.
     
  40. username_unity_of_my

    username_unity_of_my

    Joined:
    Feb 24, 2015
    Posts:
    330
    Try to randomize small differences in parameters. Also make their move speed not exacly the same. That should prevent that kind of behaviour.
    But if you want to make sure that never happens, make a script that will keep changing parameters by small amount. That way, even if their paths do come to deadlock, they will part ways upon parameter change.
     
  41. Mythran

    Mythran

    Joined:
    Feb 26, 2013
    Posts:
    85
    Wich parameters should i randomize?
    distance, angle, strength, power and persistance?
     
  42. Mythran

    Mythran

    Joined:
    Feb 26, 2013
    Posts:
    85
    Tried that and not working. It has in fact worsened it... :\
     
  43. Milionario

    Milionario

    Joined:
    Feb 21, 2014
    Posts:
    138
    Ah ok, will look into it. Btw, my scene is gonna be entirely procedural, generated at runtime, will this still work?

    On the docs it doesn't tell me to create a navmesh
     
    Last edited: Feb 25, 2021
  44. Mythran

    Mythran

    Joined:
    Feb 26, 2013
    Posts:
    85
  45. Milionario

    Milionario

    Joined:
    Feb 21, 2014
    Posts:
    138
    Do you know how to change the size of a navmeshsurface during runtime? I tried modifiying its properties
    GetComponent<NavMeshSurface>().center = transform.position;
    GetComponent<NavMeshSurface>().size = new Vector3(1, 0, 1);
    But it doesn't change, it still bakes navmesh for the entire scene.
     
  46. Milionario

    Milionario

    Joined:
    Feb 21, 2014
    Posts:
    138
    I added a Debug.Log if UnityEngine.AI.NavMesh.CalculatePath returns false on BasicObstacleAvoidance, it is still failing, but i do have the navmesh on my scene

    upload_2021-2-25_12-11-43.png
     
  47. username_unity_of_my

    username_unity_of_my

    Joined:
    Feb 24, 2015
    Posts:
    330
    ... also you can randomize move speed.
    Just remeber that parameters are very sensitive so change very little.
    Although I think changing move speed should be enough.
     
  48. username_unity_of_my

    username_unity_of_my

    Joined:
    Feb 24, 2015
    Posts:
    330

    Actual avoidance calculations dont use nav mesh but that demo scene does.
    I just set avoidance velocity result y to zero so that bots use y from physics collider.
     
  49. Milionario

    Milionario

    Joined:
    Feb 21, 2014
    Posts:
    138
    The BasicObstacleAvoidance does use navmesh because it requires UnityEngine.AI.NavMesh.CalculatePath to calculate the path to the destination.

    I am considering asking for a refund on this since its really not clear on how you implement it on a blank scene and there is no easy way to plug this in your project
     
  50. Mythran

    Mythran

    Joined:
    Feb 26, 2013
    Posts:
    85
    I tried that after trying randomizing all of the parameters, and isn't working either. Lowering the angle to 45 is what seems to work the best.
    The problem is that this way the npc's collide when avoiding each other with that angle.

    With the angle greater than that they enter the deadlock...