Search Unity

The "Jitters" upon object collision and NavMeshAgent.destination

Discussion in 'Scripting' started by OneProGoober, Oct 19, 2017.

  1. OneProGoober

    OneProGoober

    Joined:
    May 11, 2016
    Posts:
    50
    Hey guys, Not sure how to work around this problem:

    The idea behind my barrier:

    When i place a barrier on the ground (I've temporarily just implemented it so it's placed under the player whenever I drop any item - hence the reason dropping a health potion spawn the barrier) I want the player to be able to walk around in it until they "leave". When they leave, the player is taken out of a list and no longer allowed to stand in the barrier. All other players who aren't standing on the spot it's instantiated never are able to walk in it.
    Here's the barrier mechanics implementation: https://gyazo.com/9dc64240851ee620544751869fbc77c7

    So I've actually got a great implementation except for one thing... When I try to move to a location that the barrier would block, I get the jitters because it can not longer move there. I want it to get stuck on the barrier, with no rerouting. Example of the jitters: https://gyazo.com/b4c9ebb2f2f772a42853f12d0bf0b308

    So I've tried a lot of different things but they just don't seem to work. I have to keep a special case in mind: When I run into an edge on the barrier, I need to figure out the direction it came from and only edit the x or the z value.
    For example, the player and the barrier collide just on the corner here: https://gyazo.com/dd2bae636012f3d7bb098b777f373c4a
    -The barrier collider is 1x1x1
    -The player collider is 1x1x1

    *I can't just stop the player and then set the destination to the player.transform.position because it's already "partially inside" the barrier because it OnTriggerEnter is executed*

    Here's the code that I'm using. The portion that deals with setting the agent transform is in the StopPlayer function:
    Code (CSharp):
    1. using System.Collections.Generic;
    2. using UnityEngine;
    3. using UnityEngine.AI;
    4.  
    5. public class Barrier : MonoBehaviour
    6. {
    7.     private List<GameObject> playersInbarrierAtStart;
    8.  
    9.     void Start()
    10.     {
    11.         playersInbarrierAtStart = new List<GameObject>();
    12.  
    13.         //Take either x or z, doesn't matter since both are the same size.
    14.         float colliderWidthAndLength = gameObject.GetComponent<Collider>().bounds.size.x;
    15.         float colliderHeight = gameObject.GetComponent<Collider>().bounds.size.y;
    16.  
    17.         Vector3 colliderHalfExtents = new Vector3(colliderWidthAndLength, colliderHeight, colliderWidthAndLength);
    18.  
    19.         Collider[] collidersInsideBox = Physics.OverlapBox(transform.position, colliderHalfExtents, Quaternion.identity);
    20.        
    21.         for (int index = 0; index < collidersInsideBox.Length; index++)
    22.         {
    23.             Collider Co = collidersInsideBox[index];
    24.             //we only want to add each player once (there are two colliders per player)
    25.             if (Co.gameObject.tag == "Player" && !Co.isTrigger)
    26.             {
    27.                 //Found a player, add it to the list.
    28.                 Debug.Log("(Start)Added: " + collidersInsideBox[index].gameObject);
    29.                 playersInbarrierAtStart.Add(collidersInsideBox[index].gameObject);
    30.                 Debug.Log(playersInbarrierAtStart.Count);
    31.             }
    32.         }
    33.     }
    34.  
    35.     private void OnTriggerEnter(Collider other)
    36.     {
    37.         GameObject gameObjectInsideBarrier = other.gameObject;
    38.         StopPlayer(other);
    39.  
    40.         //player wasn't standing in spot barrier was instantiated at, toggle isKinematic.
    41.         if (gameObjectInsideBarrier.tag == "Player")
    42.         {
    43.             bool playerRBKinematic = gameObjectInsideBarrier.GetComponent<Rigidbody>().isKinematic;
    44.             if (!playersInbarrierAtStart.Contains(other.gameObject) && playerRBKinematic)
    45.             {
    46.                 Debug.Log("(Enter) isKinematic set to false: " + gameObjectInsideBarrier);
    47.                 gameObjectInsideBarrier.GetComponent<Rigidbody>().isKinematic = false;
    48.             }
    49.         }
    50.     }
    51.  
    52.     private void OnTriggerExit(Collider other)
    53.     {
    54.         Rigidbody otherRB = other.gameObject.GetComponent<Rigidbody>();
    55.         if (other.gameObject.tag == "Player" && !otherRB.isKinematic)
    56.         {
    57.             Debug.Log("Set to true");
    58.             otherRB.isKinematic = true;
    59.         }
    60.  
    61.  
    62.         for(int index = 0; index < playersInbarrierAtStart.Count; index++)
    63.         {
    64.             Debug.Log(index);
    65.             if(playersInbarrierAtStart.Contains(other.gameObject))
    66.             {
    67.                 Debug.Log("Removed: " + other.gameObject + " Count: "+ playersInbarrierAtStart.Count);
    68.                 playersInbarrierAtStart.Remove(other.gameObject);
    69.                 Debug.Log(" Count: " + playersInbarrierAtStart.Count);
    70.             }
    71.         }
    72.     }
    73.  
    74.     private void StopPlayer(Collider player)
    75.     {
    76.         NavMeshAgent playerAgent = player.gameObject.GetComponent<NavMeshAgent>();  //.isStopped = true;
    77.  
    78.         playerAgent.isStopped = true;
    79.         Vector3 dir = (gameObject.transform.position - player.transform.position).normalized;
    80.         Vector3 offset = new Vector3(Mathf.Round(dir.x + .3f), 0, Mathf.Round(dir.z + .3f));
    81.         //I know the offset isn't correct, just was playing around with different values to try and make it work.
    82.  
    83.         Debug.Log(player.gameObject.transform.position + offset);
    84.         playerAgent.destination = player.gameObject.transform.position + offset;//player.gameObject.transform.position + offset;
    85.         playerAgent.isStopped = false;
    86.         //Vector3 barricadeCenter = gameObject.GetComponent<Collider>().bounds.center;
    87.         //Vector3 finalDestination = barricadeCenter;
    88.  
    89.         //float xOffset = barricadeCenter.x - player.transform.position.x;
    90.         //float zOffset = barricadeCenter.z - player.transform.position.z;
    91.  
    92.         ///**Take the smaller value.
    93.         // * We only want to set either x or z, not both.
    94.         // * We set the smaller value since we can get stuck on the corner of the barrier
    95.         // * */
    96.         //if (Mathf.Abs(xOffset) < Mathf.Abs(zOffset))
    97.         //{
    98.         //    finalDestination.z = barricadeCenter.z - zOffset - .01f;
    99.         //}
    100.         //else
    101.         //{
    102.         //    finalDestination.x = barricadeCenter.x - xOffset -.01f;
    103.         //}
    104.  
    105.         //playerAgent.destination = finalDestination;
    106.         //Debug.Log(finalDestination);
    107.  
    108.     }
    109. }
    110.  
     
  2. OneProGoober

    OneProGoober

    Joined:
    May 11, 2016
    Posts:
    50
  3. MadeFromPolygons

    MadeFromPolygons

    Joined:
    Oct 5, 2013
    Posts:
    3,978
    try posting in navigation forum.

    also you should not be setting destination like that. use SetDestination instead, and cache that dont do it each frame