- Home /
NPC shakes / vibrate / jitter after pushed by a player
Hi, can someone help me how to solve the problem is that the npc shakes after pushed by player?
Scenario: The NPC reaches the designated point and then turns in the designated direction to be able to perform further actions. Unfortunately, when the player pushes the NPC, a NPC starts to shake.
Below I am attaching a video of the described problem.
Below I am attaching the code responsible for the NPC movement:
public class Npc : MonoBehaviour
{
[SerializeField] Rigidbody2D rb;
[SerializeField] float speed = 3f;
[SerializeField] Transform circle;
[SerializeField] Collider2D circleCollider;
private void FixedUpdate()
{
if ( !circleCollider.bounds.Contains(transform.position) )
{
Vector2 target = (Vector2)circle.position - rb.position;
float angle = Mathf.Atan2(target.y, target.x) * Mathf.Rad2Deg;
rb.rotation = angle;
rb.MovePosition(rb.position + target.normalized * speed * Time.deltaTime);
}
else
{
rb.rotation = 90f;
}
Debug.Log("contain: " + circleCollider.bounds.Contains(transform.position));
}
}
Answer by kylecat6330 · Jan 27 at 02:42 AM
When the player pushes the NPC it gains velocity and it continues moving in the direction is was pushed. Once it is pushed out of the circle rb.MovePosition() sends it back into the circle. However the velocity is still the same and it just moves back out of the circle and the cycle repeats. Every time the NPC enters and exits the circle its rotation is changed making it shake.
You can fix this by giving the NPC rigidbody some linear drag. That will make velocity decrease over time. You could also just set the velocity to zero whenever it is pushed out of the circle by putting in "rb.velocity = new Vector2(0, 0);", but that will probably mean that the player won't be able to push the NPC at all.
Thank you for your explanation. It really helped me to solve this problem. Below is the code containing the unwanted vibration reduction.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Npc : MonoBehaviour
{
[SerializeField] Rigidbody2D rb;
[SerializeField] float speed = 3f;
[SerializeField] Transform circle;
[SerializeField] Collider2D circleCollider;
bool state = false;
float timeBetweenStateChanging = 0;
private void FixedUpdate()
{
if ( !circleCollider.bounds.Contains(transform.position) )
{
state = true;
Vector2 target = (Vector2)circle.position - rb.position;
float angle = Mathf.Atan2(target.y, target.x) * Mathf.Rad2Deg;
rb.rotation = angle;
rb.MovePosition(rb.position + target.normalized * speed * Time.deltaTime);
}
else
{
state = false;
rb.rotation = 90f;
}
// If state if changing to often (unwanted NPC vibrations) reduce the velocity of NPC to prevent unwanted NPC vibrations
if (state)
{
timeBetweenStateChanging += Time.deltaTime;
}
else
{
if ((timeBetweenStateChanging > 0) && (timeBetweenStateChanging < 0.1f))
{
rb.velocity = new Vector2(0, 0);
}
timeBetweenStateChanging = 0;
}
}
}