0
votes

I am shooting projectiles and boucing them off the walls - I want sort of unreal perfect bounces - the object doesnt lose velocity and doesnt start spinning on collision - only is rotated once to "match" the reflect direction.

I use physics material for that has 0 friction and 1 bounciness on the walls and the projectiles, I use gravity scale on projectile 0 and its mass 0,0001 - the lowest possible amount and the projectiles rigid body has disabled rotation.

Everything is working fine but I can't get the projectile bounce rotation right, I rotate it's transform on collision this way:

public class Laser : MonoBehaviour {

    private new Rigidbody2D rigidbody2D;
    private Vector3 oldVelocity;

    private void Start() {
        rigidbody2D = GetComponent<Rigidbody2D>();
        boxCollider2D = GetComponent<BoxCollider2D>();
    }

    void FixedUpdate () {
        oldVelocity = rigidbody2D.velocity;
        rigidbody2D.freezeRotation = true;
    }

    void OnCollisionEnter2D (Collision2D collision) {
        ContactPoint2D contact = collision.contacts[0];

        Vector3 reflectedVelocity = Vector3.Reflect(oldVelocity, contact.normal);

        rigidbody2D.velocity = reflectedVelocity;

        Quaternion rotation = Quaternion.FromToRotation(oldVelocity, reflectedVelocity);
        transform.rotation = rotation * transform.rotation;

    }

}

Currently looks like this - stepping frame after frame enter image description here

I want it to rotate around the collision point like this on the right:

enter image description here

tried this without luck:

transform.RotateAround(contact.point, new Vector3(0f, 0f, 1f), Vector2.Angle(oldVelocity, reflectedVelocity));
1
What is wrong with RotateAround?derHugo
projectiles are sometimes rotated the wrong way - ie it was supposed to be 90 degress but it it rotated to -90estn
If it is only sometimes the problem might be that Vector2.Angle returns an unsigned angle .. you might want to try Vector2.SignedAngle instead. If it happens infact allways you should invert the angle ;)derHugo
The angle calculation must be wrong still, it seems to beestn
I need to calculate " by how many degress i need to rotate around the point"estn

1 Answers

0
votes

Here's one way to fix your original code: move the center to the contact point, rotate there and move just like that one more time in local coordinates. Here's an attempt at this, it probably would work:

void OnCollisionEnter2D (Collision2D collision) {
    ContactPoint2D contact = collision.contacts[0];

    Vector3 reflectedVelocity = Vector3.Reflect(oldVelocity, contact.normal);

    rigidbody2D.velocity = reflectedVelocity;

    Quaternion rotation = Quaternion.FromToRotation(oldVelocity, reflectedVelocity);

    Vector3 toContact = transform.InverseTransformPoint(contact.normal); // Added
    transform.Translate(toContact); // Added
    transform.rotation = rotation * transform.rotation;
    transform.Translate(toContact); // Added
}

Edit: And here's how you can calculate the "correct" angle to use with RotateAround that you were looking for:

float angle = Mathf.atan2(Vector3.dot(Vector3.Cross(v1, v2), Vector3.forwards), Vector3.Dot(v1, v2)) * Mathf.Rad2Deg;

Either that or this (with Vector3.backwards instead of Vector3.forwards). Unity being left handed can become confusing with this stuff.

float angle = Mathf.atan2(Vector3.dot(Vector3.Cross(v1, v2), Vector3.backwards), Vector3.Dot(v1, v2)) * Mathf.Rad2Deg;

That is with

Vector3 v1 = oldVelocity;
Vector3 v2 = -reflectedVelocity;