We are mostly happy with CanvasScaler to help us handle different form factors and resolutions. But when we have elements such as horizontal lines separating elements in a scrollable list, and we want those separators to be exactly 1 pixel tall on the device (regardless of its resolution), this gets tricky. Our “1 pixel height” set on a RectTransform might be less than a pixel on some devices at runtime, leading to lines that blink in and out of existence due to partial pixel coverage as the user scrolls.
This is only one example of the problem. The general problem and my overall question is:
“How can we specify exact pixel sizes for some elements in a scene, while still enjoying the benefits of CanvasScaler for everything else in our scene?”
Does anybody have a good strategy for that yet?
Thanks!
I’m playing around with our own hacky components to basically “reverse canvas scaling” on a few individual components like the lines mentioned in my post above, but this feels awfully silly and also isn’t perfect - due to floating point imprecision this still doesn’t make our lines exactly 1 pixel tall, so we still see some aliasing at runtime (though not as much - this solution is very close):
public class ExactPixelHeight : MonoBehaviour
{
[SerializeField]
private float pixelHeight = 1.0f;
IEnumerator Start()
{
yield return null;
var scaler = GetComponentInParent<CanvasScaler>();
float scale = (scaler.referenceResolution.y / Screen.height + scaler.referenceResolution.x / Screen.width) / 2.0f;
var rectXform = GetComponent<RectTransform>();
rectXform.sizeDelta = new Vector2(rectXform.sizeDelta.x, rectXform.sizeDelta.y * scale);
}
}