I am working on a 2D top down project in Unity2D. Hoping to familiarize myself with the Unity physics engine I decided to give the player object physics based movement by applying force to the character. One of the features I was hoping to implement into this movement was a ricochet effect where they player will bounce off of walls on collision.
Currently my script uses Vector2.Reflect to calculate this:
private Rigidbody2D playerRB;
public float playerSpeed = 0.01f;
public float playerBounce = 10f;
// Start is called before the first frame update
void Start()
{
// Fetch components from object.
playerRB = GetComponent<Rigidbody2D>();
}
void FixedUpdate()
{
// Process player input
Vector3 playerInput = new Vector3(Input.GetAxis("Horizontal"), Input.GetAxis("Vertical"), 0);
playerRB.AddForce(playerInput * playerSpeed);
}
void OnCollisionEnter2D(Collision2D collision)
{
Debug.Log("Collision Detected");
Vector2 bounceDirection = Vector2.Reflect(playerRB.velocity.normalized, collision.contacts[0].normal).normalized;
playerRB.AddForce(bounceDirection * playerBounce, ForceMode2D.Impulse);
}
Unfortunately, my current script is not producing the desired result. When I collide with the wall, nothing happens, the player object doesn't seem to recieve any opposing forces. I suspect the issue could be related to the player object being a square and potentially having multiple collision points against a flat surface. Is there a better way for me to implement this? Would raycasting be a better solution?
The problem is because the collision has already occurred.
Caching the velocity in FixedUpdate fixes the issue.
private Vector2 velocity;
void Start()
{
playerRB = GetComponent<Rigidbody2D>();
}
void FixedUpdate()
{
Vector3 playerInput = new Vector3(Input.GetAxis("Horizontal"), Input.GetAxis("Vertical"), 0);
playerRB.AddForce(playerInput * playerSpeed);
velocity = playerRB.velocity;
}
void OnCollisionEnter2D(Collision2D collision)
{
reflection = Vector2.Reflect(velocity, collision.contacts[0].normal);
playerRB.AddForce(reflection * playerBounce, ForceMode2D.Impulse);
}