Home > database >  How to stop enemy AI from vibrating when tracking y component
How to stop enemy AI from vibrating when tracking y component

Time:04-25

When my AI tracks my balls y component and moves to the same y component, it starts to vibrate as it gets closer, even if the y component is exactly the same, flicking between going up 7 and down -7. The code for it looks like this

#region Inspector Variables
     [SerializeField] private float moveSpeed;
     [SerializeField] private Vector2 ballPos;
     [SerializeField] private GameObject ballRef;
     #endregion
     #region Private Variable
     private float yInput;
     #endregion
     #region Components
     Rigidbody2D rb;
     #endregion
     private void Start()
     {
         rb = GetComponent<Rigidbody2D>();
     } //Onstartup executes
 
     private void FixedUpdate()
     {
         UpdateBallPos();
         MoveAI();
     }
 
 
     #region Methods
     private void MoveAI()
     {
         if (ballPos.y > transform.position.y)
         {
             rb.velocity = new Vector2(0, 1 * moveSpeed);
         }
         else if (ballPos.y == transform.position.y)
         {
             rb.velocity = new Vector2(0, 0);
             Debug.Log("resting pos");
         }
         else
         {
             rb.velocity = new Vector2(0, -1 * moveSpeed);
         }
     }
 
     private void UpdateBallPos()
     {
         ballPos = new Vector2(ballRef.transform.position.x, ballRef.transform.position.y);
     }
     #endregion

ballRef is linked to the ball that my game tracks during FixedUpdate

When the y coordinates for both start to become similar then my AI starts to bug out and start vibrating. It still tracks accurately but I'm not sure if there is a way to resolve my vibrating.

CodePudding user response:

This issue occurs as you are calculating based on precise movements/positions.

But positions are updated after every frame, which results in positioning of objects to be somewhat less-accurate when doing checks to see if they are on a point.

ImageProblemSolution

A very simple solution is just to add offsets to allow margin of error like so:

     const float errorMargin = 7f;
     
     private void MoveAI()
     {
         float yDiff = ballPos.y - transform.position.y;

         if (yDiff >= errorMargin)
         {
             rb.velocity = new Vector2(0, 1 * moveSpeed);
         }
         else if (yDiff <= errorMargin)
         {
             rb.velocity = new Vector2(0, -1 * moveSpeed);
         }
         else
         {
             rb.velocity = new Vector2(0, 0);
             Debug.Log("resting pos");

             // Additionally, you can do this too:
             transform.position = new Vector2(transform.position.x, ballPos.y);
             // Ensures that it stays perfectly aligned during rest.
         }
     }

CodePudding user response:

I'd probably do smoothing and clamping something like this...

private void MoveAI()
{
   var distance = ballPos.y - transform.position.y;
   var absDistance = Mathf.abs(distance);
   if(absDistance < 1) {
       // Too close to need to move, stop immediately
       rb.velocity = 0;
       return;
   }

   // Figure out a move speed that's likely not going to overshoot (this might need
   // a multiplier added)
   var maxMoveSpeed = Mathf.min(absDistance, moveSpeed);

   // Figure out new velocity based on sign of distance (i.e. which direction to move)
   // and the max move speed
   var newVelocity = new Vector2(0, maxMoveSpeed * (distance < 0 ? -1 : 1));

   // Linearly interpolate between the current velocity and the computed desired velocity.
   // The 0.4 smoothing factor can be changed between 0..1.
   rb.velocity = Vector2.Lerp(rb.velocity, newVelocity, 0.4);
}
  • Related