countering the offset of the position of an ui element

When I assing the position ot the element, it is not set exactly on the position it’s supposed to be in, but its getting offset everytime. How to calculate the exact position of the element in UI? I’ve tried world space and local space and nothing worked.

In the ui examples you can see the different offsets, even though the code is the same and their coordinates are also the same. When I click the left most slot button, the overlaying UI is on top of it, while when clicking on the right most button its next to it. Why is it like that and how to fix it, so that the ui is always next to the button regardless of the buttons’ position?

UI examples 8871717--1211325--ui1.png 8871717--1211316--ui2.png 8871717--1211319--ui3.png
code

public void BuildingSlotClicked()
    {
        buildingChooserUI.SetActive(!buildingChooserUI.activeInHierarchy);
        if (buildingChooserUI.activeInHierarchy)
        {
            RectTransform rt = GetComponent<RectTransform>();
            print(rt.localPosition);
            RectTransform rtBuildingChooser = buildingChooserUI.GetComponent<RectTransform>();
            rtBuildingChooser.localPosition = rt.localPosition; // + new Vector3(rt.sizeDelta.x * rt.localScale.x, 0);
            print(rtBuildingChooser.localPosition);
        }
    }

8871717--1211325--ui1.png
8871717--1211325--ui1.png

Use anchoredPosition instead of localPosition. For example:

public RectTransform rectObject;

public void ClickMe (RectTransform rectTransform) {

    rectObject.anchoredPosition = rectTransform.anchoredPosition;

}

I tried setting the anchored position and it didn’t work, but I’ve found out that setting the pivot together with local position does the job.
Now it looks like his.
pivot 8876439--1212417--pivot1.png 8876439--1212420--pivot2.png
pivot code

public void BuildingSlotClicked()
    {
        buildingChooserUI.SetActive(!buildingChooserUI.activeInHierarchy);
        if (buildingChooserUI.activeInHierarchy)
        {
            RectTransform rt = GetComponent<RectTransform>();
            RectTransform rtBuildingChooser = buildingChooserUI.GetComponent<RectTransform>();
            //rtBuildingChooser.anchoredPosition = rt.anchoredPosition; // + new Vector3(rt.sizeDelta.x * rt.localScale.x, 0);
            rtBuildingChooser.pivot = rt.pivot;
            rtBuildingChooser.localPosition = rt.localPosition;
            buildingChooserUI.GetComponentInChildren<BuildFarmButtonUI>().GetComponent<Button>().onClick.RemoveAllListeners();
            buildingChooserUI.GetComponentInChildren<BuildFarmButtonUI>().GetComponent<Button>().onClick.AddListener(BuildFarm);
        }
    }

Which looks fine, whichever slot I click the overlaying UI is directly above it. Now I just need to offset it to the left or right, so that you can see which slot you selected.
But when trying to offset it by increasing its X coordinate, it seems that it interprates the number differently based on its current position.

It’s supposed to be offset by 80 every time but when selecting the right most slot its offset only by a tiny amount, while the left most is offset by a lot.
offset positions 8876439--1212438--offset1.png 8876439--1212441--offset2.png 8876439--1212444--offset3.png
offset code

public void BuildingSlotClicked()
    {
        buildingChooserUI.SetActive(!buildingChooserUI.activeInHierarchy);
        if (buildingChooserUI.activeInHierarchy)
        {
            RectTransform rt = GetComponent<RectTransform>();
            RectTransform rtBuildingChooser = buildingChooserUI.GetComponent<RectTransform>();
            //rtBuildingChooser.anchoredPosition = rt.anchoredPosition; // + new Vector3(rt.sizeDelta.x * rt.localScale.x, 0);
            rtBuildingChooser.pivot = rt.pivot;
            rtBuildingChooser.localPosition = rt.localPosition + new Vector3(80f, 0);
            buildingChooserUI.GetComponentInChildren<BuildFarmButtonUI>().GetComponent<Button>().onClick.RemoveAllListeners();
            buildingChooserUI.GetComponentInChildren<BuildFarmButtonUI>().GetComponent<Button>().onClick.AddListener(BuildFarm);
        }
    }

so nobody knows how the ui really works, eh?

As a matter of fact, almost nobody knows these things by heart, unless it’s really fresh for them. GUI is always secondary by nature.

We all tend to solve such issues on the go, and I frankly can’t remember any of it, even though I’m perfectly adept at using it, and moreover I’ve made my own GUI solutions in the past (very similar to Unity’s own solution which wasn’t free at the time).

If you asked me how exactly my GUI system worked, or some particular feature of it, I couldn’t tell you much except from the very broad concepts, because I find the details irrelevant. As a long time developer, working with many techs and languages, I’m willing to encumber my brain and memory only with serious tasks that demand my full concentration. Learning some external API letter by letter, is as futile as counting sand grains on a beach.

With time, you get to own a great repository of your own past solutions and projects, and there is absolutely no need to remember each and every little thing and line of code, you just remember what’s been solved and faintly how (with some well-placed comments to get you to speed).

In order to help you, many people, myself included, would have to fire up Unity, recreate your setup and work it through. Because it’s about GUI that’s usually very boring, and besides I really don’t have the time to do it, and this is mostly because I find all kinds of GUI problems easily solvable and imagine them as trivial. This is not to say that your problem is trivial, frankly I can’t tell, it’s just that you should experiment more, and try to understand the system a bit better.

So based on your title “countering the offset of the position of an ui element” I can only say one thing: yes, it is perfectly doable, we all have to do this at some point in our projects. Is it so critical that books have been written about it? No.

That said,
“so nobody knows how the ui really works, eh?”
is a critically invalid and equally sarcastic conclusion that will lead you nowhere.

2 Likes

I totally agree with orion here.

GUI is both slightly nuanced and cryptic, but also mundane enough, that having this info at the ready is honestly… not common.

Maybe there’s someone around that solely does GUI, or is currently in the mess of GUI… but to be honest, the odds are low that your thread is going to be picked up by them. Most of us regular posters here are more general programmers across entire swaths of the system rather than the nitty gritty of one specific system.

My personal taste on GUI is I honestly don’t get the specifics of it. Instead I just do layout visually… bag them up as prefabs… and I don’t really modify/position them via code. Or if I do really have to… I play with it and tweak it in an adhoc way to make it work. Set it. And forget it.

1 Like

I don’t know the details of your project and wouldn’t have time to dig deep into it if I did, due to having my own work taking up my time. But I did just go back and examine my previous response because I was fairly certain it would work for the situation you described. I made a test project with 3 buttons and a ui image, dragged the image into the script’s rectObject field, and each of the buttons into their respective rectTransform fields. Upon clicking each button the ui image centers itself at (0,0) on each of them. You mentioned you wanted an offset of 80x from each button, so I added a vector2 to the anchoredPosition and that works as well. Hopefully the following does the job for you. If not, something else is likely interfering and I suggest attempting to isolate the issue in an empty project.

public RectTransform rectObject;
public void ClickMe (RectTransform rectTransform) {

    Vector2 offset = new Vector3 (80, 0);
    rectObject.anchoredPosition = rectTransform.anchoredPosition + offset;
}