Unity click UI to display 3D explosion effects

        When I changed the project feedback of "The Eighteen Palms of the Dragon" yesterday, the manager asked me to display the explosion effect when I clicked on the handprint in the project. I tossed for a long time yesterday and did not get it right, so I first got feedback on other projects. I have time after I finished the feedback today. Let's study this function.

        Yesterday, I simply wrote some code for testing, and added an Image and a Sphere. The purpose is to drag the Image to move in the Scene scene. In the Game scene, you can see that the black ball Sphere can be in the same position as the white Image. position, as shown in the figure:

This is the Anchor of the white Image

Among them, ImageObj is a white Image, and SphereObj is a black ball.

The resolution of my project is 1920*1080. After testing, the screen coordinates are fine. At the beginning, when the Image is at the center of the screen, (960,540) is printed out. However, the world coordinate worldPos has not changed when the Image is moved, which is always equal to the world coordinate of the camera. It left me speechless, so I ignored this yesterday and changed to other feedback.

        Today I decided to start with the principle first, so I went to the Internet to find information. There is a paragraph in a blog that explained the truth and made me understand. First of all, the rendering range of the camera to the game world is a frustum, which is a three-dimensional trapezoid. If you don’t understand it, just look at the camera information of unity on Baidu.

        On the screen, the position of a certain pixel point relative to the screen rectangle can correspond to the position of a point in the game world relative to a certain section. The key lies in which section this point is on. how far!

In the ScreenToWorldPoint method, the parameter is a three-dimensional coordinate, but in fact, the screen coordinate can only be a two-dimensional coordinate. The role of the z coordinate in the parameter is to indicate the distance from the above plane to the camera.

That is, given a coordinate (X, Y, Z),

First intercept a plane P perpendicular to the Z axis of the camera with a distance of Z, so that no matter how X and Y change, the returned point can only be on this plane;

Then, X and Y represent pixel coordinates. According to the position of (X, Y) relative to the screen, the position of the point in the game world relative to the section P is obtained, and we also convert the screen coordinates into world coordinates.

        In short, we need to assign a value to the z coordinate of the screen coordinates before converting.

        So I added 2 lines of code, as shown in the figure:

 

Camera uiCamera = GameObject.Find("UICamera").GetComponent<Camera>();//UI相机
        Vector3 ptScreen = RectTransformUtility.WorldToScreenPoint(uiCamera, ImageObj.transform.position);
        Debug.Log("ptScreen = " + ptScreen);
        ptScreen.z = 0;
        ptScreen.z = Mathf.Abs(Camera.main.transform.position.z - SphereObj.transform.position.z);
        Vector3 worldPos = Camera.main.ScreenToWorldPoint(ptScreen);
        Debug.Log("worldPos = " + worldPos);
        SphereObj.transform.position = worldPos;

        After the test, the display is normal, no matter where the Image is, the ball and the Image are together in the Game view.

 Finally, just write that piece of code into a function and modify it appropriately to use it in the project.

/// <summary>
    /// 获取让目标物体跟UI物体看起来在一起的世界坐标
    /// </summary>
    /// <param name="uiObj">UI物体</param>
    /// <param name="targetObj">目标物体</param>
    /// <returns></returns>
    public Vector3 GetUIToWordPos(GameObject uiObj, GameObject targetObj)
    {
        Camera uiCamera = GameObject.Find("UICamera").GetComponent<Camera>();//UI相机
        Vector3 ptScreen = RectTransformUtility.WorldToScreenPoint(uiCamera, uiObj.transform.position);
        Debug.Log("ptScreen = " + ptScreen);
        ptScreen.z = 0;
        ptScreen.z = Mathf.Abs(Camera.main.transform.position.z - targetObj.transform.position.z);
        Vector3 ptWorld = Camera.main.ScreenToWorldPoint(ptScreen);
        return ptWorld;
    }
void ShowClickEffect()
    {
        GameObject obj = Instantiate(m_BoomPrefab, new Vector3(0, 0, 1), m_BoomPrefab.transform.rotation);
        Vector3 pos = GetUIToWordPos(HandObj, obj);
        obj.transform.position = pos;
        Destroy(obj, 0.5f);
    }

You can set the position generated in the Instantiate() function by yourself. The x coordinate of my camera is 0. If the explosion particles are too big, you can adjust the generated position farther or make the particles smaller.

 This is a screenshot of the final successful effect.

 

Guess you like

Origin blog.csdn.net/qq_34256136/article/details/128004991