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.
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);
}