Trouble scaling text

So I have this setup where i determine caret position from code since i use my own input field, i use just text field. So let me just explain problem

Canvas: 1902x1080
CMD container: has shell and input text
when you type, characters are added to input text,
because its horizontal layout items are from left to right
Caret posititon is determined by shell text positon (0,0) and then add shell.width  text.width (of rect transform) to x position

I have other system of force update canvas and text generator and generating position by text vertices

both of these methods work fine so for example at 1920x1080 resolution:

Shell postion: 0, -25
Shell width: 208
Input position: 208, -25
Input width: 221
Caret position: 429, -36

This works perfectly fine with TextGenerator and width calculation method

but if i change resolution to same aspect like 1280x720 or different aspect 800x600, Everything is destroyed, i tried using canvas scaler to multiply or take base resolution and divide it by current but nothing works

Here are data for 800x600:

Shell position: 0, -25
Shell width: 199.5
Input position: 436.28, -25
Input width: 212
Caret position: -19.68

Okay i would understand that there is some big problem with my code if just the caret didnt work, but even input text position is wrong (shell cant be since it is at 0 position), shouldnt horizontal layout do the work?

I tried using my own calculator so each update game calculates position of shell text and size, then use that to position input at end of shell and get width for caret to use, but that messes up even 1920x1080 resolution

best that i got so far is using TextGenerator and then form those vertices using reference resolution/current resolution which is about 2.4 multiuplier for 800x600 but it is off for small amount which is good until about 20 chracters when gap is noticable

Any help?

I cannot help you with your specific problem, but it made me think of a totally different way to get a caret.

Here was my thinking:

  1. lay a second UI.Text (or TMPRo) object over the one you’re using
  2. make sure all its settings match (size, etc.)
  3. have a script that copies changes in text from the first to the second UI.Text:
    -----> copy only as many characters as the caret
    -----> wrap the copy with HTML clear color tags
    -----> append the caret text

It took me about 15 minutes to set up. You’re welcome to tinker with it too… the entire package is enclosed, a single scene and a single script, and amazingly, it pretty much works. There’s an edge case for end of line wraps but you can avoid that if you’re doing your own text editing I presume.

It amused me how quickly Unity lets you set stuff up like this. I love Unity3D!

No guarantee it will behave on other encodings than simple ASCII. But… the price is right!

PS: the text fields are slightly skewed to align the carets… might have to play with that.

5913632–631592–CursorCaret.unitypackage (5.63 KB)

I dont have problem with setting up custom caret, my caret works fine, i do it by getting where caret is, display text until caret calculate position of caret at end of ext then display whole text. works fine.

my problem is scaling to resolution for some reason it, horizontal layout doesnt scale it automatically

//Get before and after text
        string inputTextCaret = UIDB.t_Input.text;          //Gets what is inputed in cmd, stored so it can be returned later

        //Set only text before caret to text field
        if(GetCaretPosition() > inputTextCaret.Length) {
            SetCaretPosition(inputTextCaret.Length);
        }
        string preText = inputTextCaret.Substring(0, GetCaretPosition());
        UIDB.t_Input.text = preText + "A";          //We add 1 character to move the caret 1 position to right

        //Caret position
        Canvas.ForceUpdateCanvases();          //Forces update of canvas and it's text so caret can be updated properly
        TextGenerator gen = UIDB.t_Input.cachedTextGenerator;          //Get TextGenerator from input
        if (gen.verts.Count > 0)          //Calculate position of caret
        {
            Vector3 v = gen.verts[gen.verts.Count - 1].position;
            v.x *= 1 / UIDB.mainCanvas.scaleFactor; //<----WORKS
            v.x *= (UIDB.mainCanvas.GetComponent<CanvasScaler>().referenceResolution.x / Screen.width + UIDB.mainCanvas.GetComponent<CanvasScaler>().referenceResolution.y / Screen.height) / 2;
            //v.x *= UIDB.mainCanvas.GetComponent<CanvasScaler>().referenceResolution.x / Screen.width;
            DebugUtility.Log("scale factor: " + UIDB.mainCanvas.GetComponent<CanvasScaler>().scaleFactor);
            DebugUtility.Log("scaling of canvas: " + UIDB.mainCanvas.scaleFactor);
            DebugUtility.Log("wanted: " + (Screen.width / UIDB.mainCanvas.GetComponent<CanvasScaler>().referenceResolution.x + Screen.height / UIDB.mainCanvas.GetComponent<CanvasScaler>().referenceResolution.y) / 2);
            DebugUtility.Log("my scaling: " + (UIDB.mainCanvas.GetComponent<CanvasScaler>().referenceResolution.x / Screen.width + UIDB.mainCanvas.GetComponent<CanvasScaler>().referenceResolution.y / Screen.height) / 2);

            v.y = 0 - ((RectTransform)UIDB.t_Input.transform).rect.height / 2 - ((RectTransform)UIDB.o_Caret.transform).rect.height / 2;
            v = UIDB.t_Input.transform.TransformPoint(v);


           
            UIDB.o_Caret.transform.position = v;          //Add offset so we position caret correctly
            //UIDB.mainCanvas.scaleFactor
        }
       

        //Set text in canvas AFTER caret
        UIDB.t_Input.text = inputTextCaret;

Okay so i got it to work, was quite stupid, so i calculated my own scale as scaler should do it screen width / ref res + screen height / ref height and all that / 2. Thing is i got 0.486111 and it should be 0.481125123 so i was always a bit off. i just used scale of canvas and did 1 / scale without doing my math even tho, i dont know why scaler is not right since it has some of its own math