Unity Community


Results 1 to 11 of 11

  1. Location
    Rochester NY
    Posts
    651

    Navmesh Agent and Smooth Alignment with surface normals

    Hello,

    My question is regarding the use of the unity Navmesh agent component and handling rotation of an object to align with the surface it is on(IE you have a Bug AI Agent pathing around on a terrain and it moves up a slope but does not align with the slope so its face ends up under ground and its tail and hind legs end up floating off the terrain). Now i know how to accomplish this but the issue is that the navmesh agent componenet takes explicit control over the objects rotation, if i disable its control it stops steering in the correct direction that its moving. Is there anyway around this or am i just stuck with it until unity adds some sort of functionality? Thanks in advance for your input.
    Team Lead | Project Lead | Systems Designer and Programmer | Graphical Artist | and Scene Designer of Legacy Online Entertainment's Rise of Guardian's


  2. Location
    Rochester NY
    Posts
    651
    Anyone have any suggestions?
    Team Lead | Project Lead | Systems Designer and Programmer | Graphical Artist | and Scene Designer of Legacy Online Entertainment's Rise of Guardian's


  3. Location
    Rochester NY
    Posts
    651
    Does anyone have any suggestions?
    Team Lead | Project Lead | Systems Designer and Programmer | Graphical Artist | and Scene Designer of Legacy Online Entertainment's Rise of Guardian's


  4. Location
    Rochester NY
    Posts
    651
    Anyone at all? (offtopic sheesh this forum moves quick)
    Team Lead | Project Lead | Systems Designer and Programmer | Graphical Artist | and Scene Designer of Legacy Online Entertainment's Rise of Guardian's


  5. Location
    Rochester NY
    Posts
    651
    Team Lead | Project Lead | Systems Designer and Programmer | Graphical Artist | and Scene Designer of Legacy Online Entertainment's Rise of Guardian's


  6. Location
    Land of the Dead
    Posts
    7
    Just my 2 cents.

    Your agent mesh need not contain the navmesh agent.

    You can create a dummy invisible object and attach the navmesh agent to it. Then take your real actor/object/GO and make it a child of this navmeshagent (or constraint it to the dummy object that contains the navmeshagent in any manner you like using code.)

    Now, you can use localrotations to align the object with the normal of the topology as it is independent of the dummy.

    So lets say you have a soldier. Make a sphere and add navmeshagent component. Disable the meshrenderer of the sphere. Make this sphere the parent of the soldier. Now when the sphere moves, the soldier will move too. Control the localrotation of soldier as necessary using code. Use baseoffset if necessary to align the two.

    Havent tried it myself. let me know if it works.
    Last edited by SalvadorLimones; 05-21-2012 at 11:13 PM.
    Viva Le Revolution!!!


  7. Location
    Rochester NY
    Posts
    651
    Haha that sounds like it will work perfectly, no idea why i didnt think of just parenting the model and controlling just the models rotation... Probably because my brain is fried from work and working on so many different game systems at once haha. Thanks a ton
    Team Lead | Project Lead | Systems Designer and Programmer | Graphical Artist | and Scene Designer of Legacy Online Entertainment's Rise of Guardian's


  8. Location
    Rochester NY
    Posts
    651
    Quote Originally Posted by SalvadorLimones View Post
    Just my 2 cents.

    Your agent mesh need not contain the navmesh agent.

    You can create a dummy invisible object and attach the navmesh agent to it. Then take your real actor/object/GO and make it a child of this navmeshagent (or constraint it to the dummy object that contains the navmeshagent in any manner you like using code.)

    Now, you can use localrotations to align the object with the normal of the topology as it is independent of the dummy.

    So lets say you have a soldier. Make a sphere and add navmeshagent component. Disable the meshrenderer of the sphere. Make this sphere the parent of the soldier. Now when the sphere moves, the soldier will move too. Control the localrotation of soldier as necessary using code. Use baseoffset if necessary to align the two.

    Havent tried it myself. let me know if it works.
    i did try this and i am able to align the model with the surface however i cannot get the character to look in the same direction as the steering target when the nav agent is walking, only the parent object obviously is doing that. Attempted to rotate to the surface normals and rotate towards its steering target but am having no luck, the model just faces one direction. Any ideas?
    Team Lead | Project Lead | Systems Designer and Programmer | Graphical Artist | and Scene Designer of Legacy Online Entertainment's Rise of Guardian's

  9. Unity Developer

    Location
    Unity HQ - Copenhangen / Denmark
    Posts
    42
    So you basically would like to rotate twice - once for the up-vector and once for the heading (move direction). Is that right ?

    In that case I suggest you script it on your NavMeshAgent.. something along the lines of :

    Code:  
    1. // TerrainMover.cs
    2. using UnityEngine;
    3. using System.Collections;
    4.  
    5. public class TerrainMover : MonoBehaviour {
    6.   public Transform target;
    7.   public Terrain terrain;
    8.   private NavMeshAgent agent;
    9.   private Quaternion lookRotation;
    10.  
    11.   void Start () {
    12.     agent = GetComponent<NavMeshAgent>();  //< cache NavMeshAgent component
    13.     agent.updateRotation = false;          //< let us control the rotation explicitly
    14.     lookRotation = transform.rotation;     //< set original rotation
    15.   }
    16.  
    17.   Vector3 GetTerrainNormal () {
    18.     Vector3 terrainLocalPos = transform.position - terrain.transform.position;
    19.     Vector2 normalizedPos = new Vector2(terrainLocalPos.x / terrain.terrainData.size.x,
    20.                                         terrainLocalPos.z / terrain.terrainData.size.y);
    21.     return terrain.terrainData.GetInterpolatedNormal(normalizedPos.x, normalizedPos.y);
    22.   }
    23.  
    24.   void Update () {
    25.     agent.destination = target.position; //< update agent destination
    26.     Vector3 normal = GetTerrainNormal();
    27.     Vector3 direction = agent.steeringTarget - transform.position;
    28.     direction.y = 0.0f;
    29.     if(direction.magnitude > 0.1f && normal.magnitude > 0.1f) {
    30.       lookRotation = qNorm * qLook;
    31.     }
    32.     // soften the orientation
    33.     transform.rotation = Quaternion.Slerp(transform.rotation, lookRotation, Time.deltaTime/0.2f);
    34.   }
    35. }

    Make sure to place on NavMeshAgent and assign public properties (terrain, target) - there's no null-ref handling !..

    Cheers..
    /Jakob
    Last edited by Jakob@Unity; 06-19-2012 at 02:45 AM. Reason: bugfixed example code


  10. Location
    France
    Posts
    101
    Thank you for this excellent piece of code.

    After tested it on my project, I was forced to change terrain.terrainData.size.y to z to get the normal correctly.

    Quote Originally Posted by Jakob@Unity View Post
    Code:  
    1.    // NOTE: Replaced terrain.terrainData.size.y by z
    2.     Vector2 normalizedPos = new Vector2(terrainLocalPos.x / terrain.terrainData.size.x,
    3.                                         terrainLocalPos.z / terrain.terrainData.size.z);
    Unity free plugins: Import animations list - GridGraph RVO obstacle for A* Pathfinding
    Done (small): Acid Island Runner - Work in Progress: Acid Islands 3D Shooter


  11. Posts
    17

    A different approach

    I know it is a little bit old but I just happened to have the same problem and reached a different solution. I dont use terrains so I had to look for something different. Another problem was that I did not want to use the normal of the geometry under my objects, I wanted a smooth transition between the current orientation and the target orientation. So in the end I decided to use the LookAt function. This way, no matter what geometry I am moving on it just works.

    1-. In my Object script I put these variables:
    Code:  
    1.         public bool OverrideRotation = false;
    2.         public float OrientationSpeed = 10f;
    3.         Vector3 lastPosition;
    4.         Vector3 position;
    5.         Vector3 direction;

    2- Then, in the awake method:

    Code:  
    1.                 if (OverrideRotation) {
    2.                         navAgent.updateRotation = false;
    3.                         lastPosition = myTransform.position;
    4.                 }

    3- And last, if OverrideRotation is set to true, I start the coroutine that manages the orientation:

    Code:  
    1.         IEnumerator updateRotation ()
    2.         {
    3.                 while (true) {
    4.                         Vector3 position = myTransform.position;
    5.                         direction = (position - lastPosition).normalized;
    6.  
    7.                         myTransform.LookAt (position + (Vector3.Lerp (myTransform.forward, direction, Time.deltaTime * OrientationSpeed)), Vector3.up);
    8.  
    9.                         lastPosition = position;
    10.  
    11.                         yield return Yields.Frame;
    12.                 }
    13.         }

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •