具有旋转功能的2D完美弹丸反射

时间:2019-04-22 11:26:56

标签: c# unity3d 2d

我正在射击弹丸并将它们从墙壁上弹开-我想要某种虚幻的完美弹跳-物体不会失去速度并且在碰撞时不会开始旋转-仅旋转一次以“匹配”反射方向。

我使用在壁和弹丸上具有0摩擦和1反弹的物理材料,在弹丸0和其质量0,0001上使用重力标尺-尽可能低的量,并且弹丸刚体禁用了旋转。

一切正常,但我无法正确地使弹丸弹跳旋转,我以这种方式旋转碰撞时的变换:

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;

    }

}

当前看起来像这样-在帧enter image description here之后逐帧

我希望它绕着碰撞点如右图所示旋转:

enter image description here

没有运气尝试了这个

transform.RotateAround(contact.point, new Vector3(0f, 0f, 1f), Vector2.Angle(oldVelocity, reflectedVelocity));

1 个答案:

答案 0 :(得分:0)

这是修复原始代码的一种方法:将中心移至接触点,然后在该点旋转并在本地坐标中再移动一次。这是一种尝试,它可能会起作用:

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
}

编辑:这是您如何计算要与RotateAround配合使用的“正确”角度的方法:

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

要么(要么用Vector3.backwards代替Vector3.forwards)。左撇子统一可能会使这件事变得混乱。

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

那就是

Vector3 v1 = oldVelocity;
Vector3 v2 = -reflectedVelocity;