Search Unity

RectTransform.anchoredPosition Relative to its Canvas?

Discussion in 'UGUI & TextMesh Pro' started by McMayhem, Apr 15, 2016.

  1. McMayhem

    McMayhem

    Joined:
    Aug 24, 2011
    Posts:
    443
    I'm trying to get the anchored position of a RectTransform that's nested within several other RectTransforms. Some of the parent RectTransforms use stretching and other things that throw off RectTransform.anchoredPosition which is a problem for me.

    I need to know if there is a function that will return the position of the RectTransform relative to the Canvas it's being drawn on without having to reference all of the parent transforms. Currently the only means for me to achieve this is to go through each of the parent transforms and calculate their relative offsets until I get to the root canvas.

    Is there some super easy way to do this that I'm just missing? And if there isn't, why?

    Note: I'm not using Screen Space - Overlay, I'm using a World Space canvas.
     
    _TheFuture_ likes this.
  2. eses

    eses

    Joined:
    Feb 26, 2013
    Posts:
    2,637
    @McMayhem - Hi, did you already solve this?

    AFAIK anchoredPosition is delta / distance of UI objects rectTransform pivot to anchor corners. So if you have all four anchors in "flower" shape, and move your object right from it 100 pixels, and pivot is in center of your object, your anchoredPosition is 100,0. If you then split the anchor, I think it gets more complicated (some interpolation according to manual).
    So I'm not sure if I can help, as I'm not sure what is needed, the delta itself is already there and it's not a location value, do you actually need pivot location of child/leaf rectTransform down in hierarchy, translated into canvas space?
     
  3. McMayhem

    McMayhem

    Joined:
    Aug 24, 2011
    Posts:
    443
    Hey eses, thanks for replying, I really appreciate the consideration. I might have to explain a bit better what I'm trying to do.

    Essentially, I'm trying to not have to use an EventTrigger on each cell of my inventory, which has 100 cells 10x10. I'm not sure what the performance hit is on EventTriggers, but I know that regardless what event types you supply (PointerEnter/PointerExit/PointerClick) it still listens for all possible event types. That makes me think that the performance would suffer moderately if I were to use EventTriggers for each cell. If I'm wrong on that, please correct me.

    Looks like this:
    UI_1.jpg

    What I want to do instead is to get the position of the mouse and get the position of each inventory cell (this I already have set up in a nice nested for loop.) and then use that information to determine what cell/item the mouse is currently hovering over.


    Now as I said before, I've set up my UI to have several nested RectTransforms, some with stretching (ie anchors are in the for corners of the screen) and others where the anchor is set to the upper left point of the actual UI element in question. The issue I have is that the UI system's positioning resets to (0, 0) whenever it is the child of a RectTransform that has its anchor presets set to stretch.
    UI_2.jpg

    The reason I need this is that the mouse position is always going to be relative to the screen as a whole, whereas any one UI element, depending on how it and its parent are set up will be relative to the parent UI element. so (0, 0) for the UI element will be the upper left corner of the box it's in while the mouse location doesn't reflect that.

    Perhaps someone like @superpig who knows more about the UI system can shed light on how to get the absolute position of a nested UI element given the above information?
     
  4. eses

    eses

    Joined:
    Feb 26, 2013
    Posts:
    2,637
    Hi,

    I'm only learning coding in general, but I've just used a week or so on similar issues. Like you mention, it becomes obvious, that nearly all of the commands in RectTransform class that spit out some positions, are relative to parent, this seems to serve users of UI in inspector but not that much in code side, I think.

    This is what I've done.

    To get corners of some item, under parent or many parents, first get the points and transform them to world space:

    Code (csharp):
    1.  
    2. Vector3[] corners1 = new Vector3[4];
    3. rt.GetWorldCorners(corners1);
    4.  
    Imagine RectTransform corners now just in a virtual plane next to 0,0,0, not related to canvas.

    Then transform these points to your canvas space:

    Code (csharp):
    1.  
    2. for (int i = 0; i < 4; i++)
    3. {
    4. corners1 = canvasRt.InverseTransformPoint(corners1);
    5. }
    6.  
    Now you have the same points back in space of canvas, which can (should in this case) be your literal canvas rectTransform.

    Also, if you need to calculate distances between, say, a item that is child of child of canvas, and compare it's pivot to canvas pivot location in canvas space:

    First transform a pivot point (or any other point) to world space, from it's (parent) space:

    Code (csharp):
    1.  
    2. Vector3 parentPos = parent.pivot;
    3. Vector3 itemPos = item.TransformPoint(item.pivot);
    4.  
    Then, transform item's point to your target / new parent space, which might be a canvas or just some other container:

    Code (csharp):
    1.  
    2. itemPos = parent.InverseTransformPoint(itemPos);
    3.  
    Then you can get their distance or offset in (now) same parent space:

    Code (csharp):
    1.  
    2. return new Vector3((parentPos - itemPos).x, (parentPos - itemPos).y);
    3.  
    I hope I got all correct here!

    I've just done a sort of simplified custom ScrollRect, which calculates all the edge collisions, distances and such using above methods, so I think this works OK. I can do hiding of items when they are out of canvas, limit scrolling of content to parent / canvas edges, calculate distances and automatically move to certain item, add soft elastic movement similar to Unity's rectTransform, Parent viewport can be scaled, stretched, rotated and above mentioned approach / calculations seem to result in OK behaviour despite of this.
    I once checked the Unity RectTransform code, at seems to take completely different approach, I couldn't work out how they did what they did, it seemed too complicated for me to make sense in short time.

    Let me know if this helped or not!
     
    Last edited: Apr 19, 2016