Search Unity

Nav Mesh/Animation Issues positioning error

Discussion in 'Scripting' started by Foestar, Mar 29, 2015.

  1. Foestar

    Foestar

    Joined:
    Aug 12, 2013
    Posts:
    350
    Okay, so originally I had my player model inside an empty object called Player and wasn't sure why I had done so other than I was having problems. So I removed empty object and just made the Human Model my nav mesh agent because I noticed I was having an issue where my model inside would get off centered and make his rotations awkward.

    So long story short, I have my player model, it plays an idle animation when it has no path and plays the run when it does. Start it, it works fine. He's idle, no more rotational errors. However, start moving and it debugs as he's moving and following his path. Then when he reaches it, it acts like he's switching on and off for no reason as if he's getting a path and losing it again and again. So he starts rotating. It seems like he's off on his destination and trying to correct it.
     
  2. relic1882

    relic1882

    Joined:
    Mar 11, 2015
    Posts:
    45
    I did some research when I was new to using NavMeshAgents recently and I came across some bits and modified them slightly for my needs.

    I use this block to get a random direction for my NPC, but the main thing for me was using NavMesh.SamplePosition. That way your agent gets a possible destination without path routing problems. If not, I recalculate.

    Code (CSharp):
    1.     void GetWalkingDestination()
    2.     {
    3.         if (ReachedDestination())   //check if character reached random destination
    4.         {
    5.             Vector3 randomDirection = Random.insideUnitSphere * walkRadius; //recalculate random destination
    6.             randomDirection += transform.position;      //set new random destination
    7.             NavMeshHit hit;
    8.             NavMesh.SamplePosition(randomDirection, out hit, walkRadius, 1);
    9.             Vector3 endPosition = hit.position;
    10.             transform.LookAt(endPosition);       //make character look the direction of destination        
    11.             agent.SetDestination(endPosition);        
    12.         }
    13.     }
    I use this block to make sure my NPC reaches the destination. If they are forced to stop before they reach it, it returns true and I use that Boolean in the other block of code I posted above. So if they can't reach where they're going, they find a new one. If your guy can't reach a destination or is trying to reset it, you can probably use NavMeshAgent.ResetPath() so he doesn't try to go again until a new destination is set with agent.SetDestination();

    Code (CSharp):
    1.  //function to check if navigation mesh agent has reached its destination
    2.     bool ReachedDestination()
    3.     {
    4.          // Check if we've reached the destination
    5.         if (!agent.pathPending)         //if path is still being made, return false
    6.              {
    7.              if (agent.remainingDistance <= agent.stoppingDistance)      
    8.                  {
    9.                     //if agent cannot reach path and is not moving anymore, return true to continue
    10.                    if (!agent.hasPath || agent.velocity.sqrMagnitude == 0f)
    11.                       {
    12.                           return true;
    13.                             // Done
    14.                          }
    15.                  }
    16.              }
    17.         return false;
    18.  
    19.     }
    I'm just ballparking a rough answer for you. Other guys on this forum will probably be asking to see your code though.
     
  3. Foestar

    Foestar

    Joined:
    Aug 12, 2013
    Posts:
    350
    Yeah, mine was basic and done in Java back when I first started this project. I started by setting an agent, checking for the path location, then checking whether he is on the path or not for the movement.
    Code (JavaScript):
    1. private var agent: NavMeshAgent;
    2. var PlayerModel : GameObject;
    3. var anim : Animator;
    4.  
    5. function Start () {
    6.     agent = PlayerModel.GetComponent.<NavMeshAgent>();
    7.     anim = GetComponent.<Animator>();
    8. }
    9.    
    10. function Update () {
    11.     var hit: RaycastHit;  
    12.     if (Input.GetMouseButtonDown(0)) {
    13.         var ray = Camera.main.ScreenPointToRay(Input.mousePosition);
    14.        
    15.         if (Physics.Raycast(ray, hit)) {
    16.             agent.SetDestination(hit.point);
    17.         }
    18.     }
    19.    
    20.     if (agent.hasPath){
    21.         Debug.Log("MOVING");
    22.         anim.SetInteger("MoveState", 1);
    23.     }else{
    24.         anim.SetInteger("MoveState", 0);
    25.         Debug.Log("STOPED");
    26.     }
    27. }
    I have to say it's interesting to see your code because I didn't know you could check pending paths that way. It works fine until he gets close to the destination. Then it acts like he's torn between whether the agent has hit the point. I'm starting to think it has something to do with my animation for the model slightly off putting the x,y,z coords and that's what's messing up the ending of the paths.
     
  4. Foestar

    Foestar

    Joined:
    Aug 12, 2013
    Posts:
    350
    Okay, so I figured it out. Finally got some time to sit down and work with it and found that my character model itself as an agent is rather taxing on the coordinates for the agents destination and pathing.

    For some reason the slight movements in my character's idle animations at the end are off putting my pathing for the agent and making it so he tries to auto correct which is why he does the spin animations conflict in the video. I fixed this by putting him in an empty object as a placeholder and made that the agent. This way he stays right dead smack in the center and I root his position there to avoid any awkward rotations while the placeholder controls the movement.