Unity UI extensions mouse drawing: annoying offset between touch position and drawing position
Many people are using Unity UI Extensions (that is a very good and useful piece of software by Simon Jackson). Unfortunately when using UILineRenderer to draw using the finger I'm getting a really annoying offset between where I touch and where the line is drawn. The Input.mousePosition uses screen coordinates (in px) while the UILineRenderer uses world coordinates, to convert from screen to world coords I use the ScreenToWorld method from Camera object but still it seems to work for some phones and not for others. The offset between touched and drawn is 0 when I touch the center of the screen and keep increasing while I move to the edges of the phone.
Anyone found a similar problem? I found this other issue online: Unity UI Extensions issue
Answer by a-dibacco · Dec 10, 2019 at 04:14 PM
I think I found a solution to my problem or, better, an approach to follow when you want to design a 2D game where a Canvas covers completely the phone screen and the camera is rendering exactly the phone screen. With this approach I got rid of many problems I was facing with coordinates conversion.
Here are my advices:
1) Design you interface (buttons and the like) using a screen size (in Game tab) of 1920x1080 or 1080x1920 (landscape or portrait)
2) Set you camera in orthographic mode
with a size of 9.6 (100 pixel per world unit)
3) Add a Canvas to hold your UI
elements with Render mode set to Screen Space - Camera
4) Add a Canvas Scaler script and set a reference resolution of 1080 x 1920 (or opposite for landscape) and set the Screen Match Mode to Expand
With these settings everything is coherent if you use a phone with a resolution of 1080 x 2340 but if you try with another phone resolution (for example 1080x2340) conversion of coordinates will start to become weird. Then I did the following
5) I setup the camera in the Awake method in a script associated with an object of the scene (can be the camera itself) with the following code:
void Awake ()
{
...
Camera.main.orthographic = true;
if (portrait == true)
Camera.main.orthographicSize = (Screen.height*1080/Screen.width)/200.0f;
else
Camera.main.orthographicSize = (Screen.height*1920/Screen.width)/200.0f;
...
}
6) I set up the canvas in the Start method of a script associated with a game object in the scene with the following code:
void Start() {
...
canvas.GetComponent<CanvasScaler>().referenceResolution = new Vector2(1080, Screen.height*1080/Screen.width);
...
}
7) Because I have a background image that has a resolution of 1920x1080 I use also to change its local scale with the following code:
float cameraHeight = Camera.main.orthographicSize * 2;
Vector2 cameraSize = new Vector2(Camera.main.aspect * cameraHeight, cameraHeight);
Vector3 extents = background.GetComponent<SpriteRenderer>().bounds.extents;
background.transform.localScale = new Vector3 (cameraSize.x/(2*extents.x), cameraSize.y/(2*extents.y), 1.0f);
With the previous steps (valid for portrait) now I can draw with my UILineRender and using the ScreenToWorld method with no offset at all.
I hope this can help.
Antonio.
Your answer

Follow this Question
Related Questions
How should create a map for a top-down tile based 2d game? 1 Answer
White (not transparent) background in sprite [graphicsgale] 0 Answers
Simulating 2D depth in a sidescroller 0 Answers
How do I make a game like line zen style 0 Answers
On 2D TOPDOWN RPG on the depth of sprites and players 0 Answers