How to make accuracy variable for gun spread be proportional to crosshair size

So I have a gun script for my FPS game which uses this code when the player shoots:

  Vector2 accuracy = new Vector2(Random.Range(-spread, spread), Random.Range(-spread, spread));
  Vector3 direction = cam.transform.forward + new Vector3(accuracy.x, accuracy.y, 0);
   if (Physics.Raycast(cam.transform.position, direction, out rayHit, range))
       Debug.Log("hitsomething");

And I want the spread variable to be proportional to the crosshair size variable used here:

if (isMoving) {
    currentSize = Mathf.Lerp(currentSize, maxSize, Time.deltaTime * speed);
} else {
    currentSize = Mathf.Lerp(currentSize, restingSize, Time.deltaTime * speed);
}
reticle.sizeDelta = new Vector2(currentSize, currentSize);

which uses currentSize to lerp the crosshair size. However if I set the spread variable in the gun script to be the currentsize variable the gun would be extremely inaccurate because the gun spread is measured in game units and the crosshair canvas is measured in screen size in pixels. Does anyone know the proportions to convert this spread variable to crosshair size?

The crosshair should just be a visual representation of the current expected spread, not the source of that information. Both the cross hair and the gun’s actual spread should be working off the same information.

Ok, but in FPS games, the bullet will go anywhere inside of the crosshair and the crosshair changes due to bloom, aiming, etc.
If I set the currentSize crosshair variable to the spread variable of the gun script, and for example, the spread in the gun script is 5 game units, then the crosshair size will be 5 pixels wide.
So I am trying to make it so that the accuracy in game units is converted to screen pixel size which is how unity’s canvas is scaled.

While this is a good solution, I agree with spiney199’s post that I should have a spread variable in my gun script and work backwards to create the crosshair size. However, I just don’t know how to scale the pixels to the Vector2 created by Random.Range

I would imagine you can take some points in world space and convert those to screen space with the methods Unity provides, such as: Unity - Scripting API: Camera.WorldToScreenPoint

Just need to calculate those points.

This worked, I turned the raycast hit point into a screen point, and then created the crosshair size from the X value of the screen point with Mathf.Abs. Thank you for your help!

So I have implemented this into my script but it does not seem to be working. I use this code:

  Vector3 raydirection = cam.transform.forward + new Vector3(spread, spread, 0);

  Physics.Raycast(cam.transform.position, raydirection, out rayHit, range, mask);
  Debug.DrawRay(cam.transform.position, raydirection * range, Color.green);
  target = cam.transform.position + raydirection * range;
  Vector3 screenPos = cam.WorldToScreenPoint(target);
 
  Debug.Log(screenPos);
  reticlescript.currentSize = Mathf.Abs(screenPos.x);

And in the crosshair script, the Reticle.SizeDelta is set to currentSize variable. However, if I set my spread variable to any number, and the range to any number, the crosshair seems to stay very small, and screenPos variable is returning back small numbers such as (-0.03, 0.01, 2.89) even though the debug shows the ray very much not ending 0.03 pixels away from the screen center. The target variable is also returning the point at the end of the ray correctly. I have tried making the rays range small and setting the mask to nothing but even when the raycast doesn’t hit anything, the crosshair stays very small unless I look at a few select places in the sky where the crosshair expands. I have no idea why this is.
Nevermind I have realized that screen space is not canvas space and have done some conversions. However, without any changes to the screenPos calculations, the screenPos x is returning in the millions.