Tank shell not rotating correctly on collision

Hello,

I have been trying to figure this out for a few hours and am stuck on how to get my tank shell to ricochet off walls correctly. This is what I want to happen:

This is what actually happens:

Here is my code for firing the shell:

using UnityEngine;
using System.Collections;
public class Player_Shell_Fire : MonoBehaviour
{
    public float bulletSpeed;
    private Rigidbody2D _rb2D;

    private void Start()
    {
        _rb2D = GetComponent<Rigidbody2D>();
    }

    private void OnTriggerEnter2D(Collider2D target)
    {
        _rb2D.velocity = transform.up * bulletSpeed;

        if (target.gameObject.tag == "Enemy")
        {
            Destroy(this.gameObject); // Destroy Shell
            Destroy(target.gameObject); // Destroy Enemy
        }
    }

    private void OnCollisionEnter2D(Collision2D other)
    {
        if (other.transform.CompareTag("Wall"))
        {
            CollisionWithWall(other);
        }
    }

    private void CollisionWithWall(Collision2D other)
    {
        // For Reflecting The Bullet
        Vector3 reflectedPosition = Vector3.Reflect(transform.up, other.contacts[0].normal);
        _rb2D.velocity = (reflectedPosition).normalized * bulletSpeed;

        // For Rotatating The Bullet Towards its velocity
        Vector3 dir = _rb2D.velocity;
        float angle = Mathf.Atan2(dir.y, dir.x) * Mathf.Rad2Deg;
        _rb2D.MoveRotation(angle);
    }
}

Here is my Heavy_Shell prefab:

I am using a Physics2D Material so the bounce is fine, just the rotation after the collision is wrong. I have a small circle collider at the tip of the shell.

Any assistance you can give me would be greatly appreciated because I have no idea how to sort this out.

Many Thanks,

John

Hi John
Do you want to have a smooth interpolation rotating the bullet over time?
Otherwise, you should use Rigidbody.Rotation instead of Rigidbody.MoveRotation. But I do not know, if either of them works with an angle as parameter. You should consider using quaternions.

Hi,

Thank you for your reply. This can just be instant rotation to the correct angle, rather than smooth over time. Do you know of any examples I can look at for quaternions, I am not really sure how this would help or how to test? I tried changing to _rb2D.Rotation, but this does not exist.

Many Thanks,

John

Ecuse me. It’s with a lower case “r” (Unity - Scripting API: Rigidbody2D.rotation).
I just noticed that you are working on a 2D game. You’re right using angles in 2D.
So this should do it:
_rb2D.rotation += angle;

Hi,

Thank you for the fast response. I made the change and this is what happens now:


As you can see the bullet reverses, but stays in a horizontal position whilst travelling along a diagonal path.

I also tried by moving the wall to the other side and firing and the bullet does not flip and travels backwards along the path:


I am really at a loss with this. In my mind it should be easy, but in reality I really underestimated this task.

Many Thanks,

John

I guess one option would be to use a round shell, although I feel like this is cheating and I know there must be a way to do this properly. Am open to any ideas / tutorials about how to do this.

Many Thanks,

John

Generally Mathf.Atan2() can be used to determine a compass heading in radians, based on X and Y deltas, in this case your motion.

Mathf.Rad2Deg is a constant you can multiply by to get that heading in degrees.

Finally you can apply the rotation to the sprite object.

Putting it all together:

  • get the velocity from the RB2D
  • calculate the heading with Atan2
  • convert it to degrees with the constant above
  • rotate the tank shell to face appropriately.

Note: this presumes the original art is oriented so that heading aligns with rotation. If that is not the case, either rotate the art or make a prefab with a sub-object that is rotated so the heading aligns with rotation.