The problem I find with using Canvas Scaler is that I can’t seem to know the positions of corners in a RectTransform element. Let’s say I have an image and I want to find an upper left corner. But first I atleast need to know how much the Canvas Scaler actually scales the image, because image.rect returns unscaled rect of the image.
This code works when Canvas Scaler → Scale with Screen Size has a match value of 1 or 0
in other cases it misses just enough to piss me off, usually the return value is bigger than the actual scale
return ((Screen.width / scaler.referenceResolution.x) * (1 - scaler.matchWidthOrHeight) +
(Screen.height / scaler.referenceResolution.y) * (scaler.matchWidthOrHeight));
I am also pissed of that there is no way to grab something like scaler.scale or scaler.scaleFactor since it’s not used within “Scale with Screen Size” mode could easily return the actual scale… bus since it doesn’t can anyone work out the math behind Matching in Scale with Screen Size mode?
P.S. And MAYBE the easy solution to this is just to check the source code of the Canvas Scaler, I am not sure how to do that either
EDIT: I found this: c# - Retrieving the amount of scaling from the Canvas Scaler (Unity) - Stack Overflow
Talks about same problem, gives no solution. Suggests workaround, but rectTransform.localScale is not changed by the Canvas Scaler, nor any other value that I know of
For anyone reading this - the solution for the Scale With Screen Size is to query the Canvas itself for the scaleFactor and not the CanvasScaler
I’ve learned that after looking at the UGUI sources. It’s quite counter-intuitive but that how it works.
As usual with time I have found a way to extract the current scaleFactor of Canvas Scaler. In theory and if this message is marked as an answer then it worked.
So I will anchor an empty RectTransform to one of the corners of a disabled image. This RectTransform will be able to indicate the position that certain corner and by getting a ratio between the unscaled corner position I get from rectTransform.rect I will get the actual scale. Man… countless times I had to workaround Unity stuff. But I guess I learn something every time.
public RectTransform scaleTemplateImage, scaleCheckPosition;
private static float _scaleFactor;
void Update() {
_scaleFactor = Mathf.Abs(scaleCheckPosition.position.x - scaleTemplateImage.position.x)/
Mathf.Abs(scaleTemplateImage.rect.width/2);
}
public static float scaleFactor {
get {return _scaleFactor;}
}
Yep it worked, here is the code. ScaleTemplateImage is a blank image and ScaleCheckPosition is another image anchored to upper right corner and positioned at Vector3.zero (pivot = anchor).
I had the same issue when working with Scale with Screen Size and the scaleFactor on the CanvasScaler was always 1 no matter the size changes, which didn’t help at all when trying to set points on specific positions on the canvas.
I found that the localScale of the Canvas transform had the correct scale, which you can use to scale the positions.
Something like this:
var canvasScalerTransform = FindObjectOfType<CanvasScaler>().gameObject.transform;
var unscaledPosition = new Vector3(5, 1);
var scaledPosition = Vector3.Scale(unscaledPosition, canvasScalerTransform.localScale);