Realization of Unity bullet bounce effect

Still using the scenes and characters that have remained unchanged for thousands of years...

Let's take a look at the approximate effect: 

It is actually quite easy to realize the bullet rebound. The only way to control the rotation of the bullet in the 2D interface is the z-axis. If you want to realize it in 3D, you need to modify the three axes. This time it is for the 2D effect. Maybe later A 3D bounce effect will be added to this page.

When the bullet collides with the object, to make the bullet bounce in the desired direction, it is necessary to obtain the normal vector of the bullet and the object on the contact surface, and then the movement direction of the bullet is axisymmetric with the normal vector, and then modify the return to the bullet The direction of movement is enough. The function for reflection is Vector2.Reflect(). The first parameter received is the incident vector and the other is the normal vector. Since the bullet movement method I use here is transform.Translate, my bullet The rotation is related to the z-axis, so the z-axis must be converted into a 2-dimensional vector. How to obtain the normal vector? The collision body in the collision function has the collision.GetContact(int index).normal method, which returns the normal vector at the index-th collision point. The index is generally 0 by default. The last part is the code showing how to convert the angle system into a two-dimensional vector .

    private void OnCollisionEnter2D(Collision2D collision)
    {
        //将角度制转换为弧度制   
        float Angle_Z = transform.rotation.eulerAngles.z * Mathf.Deg2Rad;

        //拿到旋转向量,以便之后进行反射计算
        Vector2 Direction = new Vector2(Mathf.Cos(Angle_Z), Mathf.Sin(Angle_Z));

        //做反射运算,得到反射后的选择向量
        Vector2 Out_Direction = Vector2.Reflect(Direction, collision.GetContact(0).normal);

        //向旋转向量转为弧度制
        Angle_Z = Mathf.Atan2(Out_Direction.y, Out_Direction.x);

        //重新转换回角度制,并修改子弹角度,达成反射效果
        transform.rotation = Quaternion.Euler(0, 0, Angle_Z * Mathf.Rad2Deg);
    }

If you don’t understand the function of each line of code, you can read the detailed introduction here. Angle_Z is to convert the rotation vector of the object on the 2D interface into a float value to represent the angle, but it must be multiplied by Mathf.Deg2Rad to convert it into radians. The reason for this is Because the value of the Z axis is directly calculated by the trigonometric function, the vector obtained is not the correct direction vector, because the angle calculation standard is the radian value, you can open the calculator of the mobile phone and try whether the sin30 is 0.5, and then you will find that it is a A very small negative number, and sin30π/180 is 0.5, so you can understand why it needs to be converted to radians. Direction uses trigonometric functions to calculate the direction vector, and finally uses Reflect to calculate the reflection vector to obtain the reflection vector, and then converts it back to the angle system.

In addition, if you use a method similar to controlling the player's movement, such as an input axis, an X axis and a Y axis, or similar methods, you can save the trouble of conversion. Of course, I use this movement method for easy implementation. Bullet curve turn tracking, it is much more difficult to control bullet tracking in this way (laughs).

Update the collision bounce in another case. The above usage conditions are limited to the collider with or without the trigger option checked. Otherwise, the collision collision information returned in the OnTrggier method cannot be used to obtain the normal vector using the GetContact method. If you need to obtain the normal vector without using collision, you need to use ray detection, and the collider information returned by ray detection has normal indicating the normal vector obtained by ray detection.

The code is shown below, which is basically the same as the previous method:

//大部分的逻辑是一样的,但是少部分我还是要提一下
    float Angle_Z = transform.rotation.eulerAngles.z * Mathf.Deg2Rad;

    Vector2 Direction = new(Mathf.Cos(Angle_Z), Mathf.Sin(Angle_Z));

//layer是要检测的图层,为LayerMask类型,Distance表示检测的距离,为float类型
//利用射线检测检拿到物理信息
    RaycastHit2D hit = Physics2D.Raycast(transform.position, Direction, Distance, layer);

    Direction = Vector2.Reflect(Direction, hit.normal);

    Angle_Z = Mathf.Atan2(Direction.y, Direction.x);

    transform.rotation = Quaternion.Euler(0, 0, Angle_Z * Mathf.Rad2Deg);

Another reminder, when using ray detection to obtain the collision position, use point instead of coiler, because the position of your collision will never be the center of the object, and the position of this point is likely to be inside the collision body (even if it is only about 0.001 gap) So in more cases, the second method is not RaycastHit2D, but another way to get the object in the entire ray area, RaycastHit2D[] hits = Physics2D.RaycastAll(transform.position, Direction, Distance, layer);.

Icon effect:

Guess you like

Origin blog.csdn.net/WEIWEI6661012/article/details/130096124