How to convert from world space to canvas space in unity?

I have a gun that shoots raycasts, and when the raycast hits an enemy, I want to spawn a damage popup that display a number. I have a code that converts form world space to canvas space. in this case, world space is the position of the hitpoint of the raycast, and canvas space should be the position of the damage popup text.

Here is the code:
Survivor.io mod download latest version
void positionSelf()
{
Vector2 ViewportPosition = cam.WorldToViewportPoint(position);
Vector2 ScreenPosition = new Vector2(
((ViewportPosition.xcanvasRectTransform.sizeDelta.x)-(canvasRectTransform.sizeDelta.x0.5f)),
((ViewportPosition.ycanvasRectTransform.sizeDelta.y)-(canvasRectTransform.sizeDelta.y0.5f)));
myRectTransform.localPosition = new Vector2(ScreenPosition.x,ScreenPosition.y);
}

I call this method in the OnGUI() update, and it works fine. When I move my camera left or right, the damage popup stays aligned to the target that the raycast hit. However, if I move my camera up or down, the popup also moves up and down with it and is not aligned to the target. I tried using position and anchoredPosition, but it didn’t work.

My canvas is set to screen space overlay, and it is set to scale with the screen size. The UI is rendered in another camera, which also renders the weapons. I tried setting the cam variable to both cameras, but the problem still occurred.

Can anyone help me with this issue? Any help would be appreciated.

OnGUI is used for the editor, namely the immediate mode GUI system. You should not build your actual game around it.

GUI events are very specific thing in Unity, but I can see how a newcomer can be mislead. This has nothing to do with the UI package you normally use in modern Unity workflows, that’s been introduced since Unity 5.

In fact I started working with Unity 3.xx and one of the first tasks I did for the studio that hired me was to write a GUI system exactly in order to move away from the IMGUI, which is essentially horrible.