Search Unity

Setting top and bottom on a RectTransform

Discussion in 'UGUI & TextMesh Pro' started by rickw, Aug 29, 2014.

  1. rickw

    rickw

    Joined:
    Jul 7, 2013
    Posts:
    15
    Hi,

    I'd like to set the top and bottom on a rectatransform belonging to a prefab I'm instantiating...

    So..

    I instantiate the object and set the rect i.e.

    rectTransform.rect.set(top,left,width,height);

    However the instantiated objects top is not the value I've set!

    Any ideas?
     
    DragonCoder and AzureByte like this.
  2. Senshi

    Senshi

    Joined:
    Oct 3, 2010
    Posts:
    557
    You have to use:

    Code (csharp):
    1. rectTransform.offsetMin = new Vector2(rectTransform.offsetMin.x, bottom);
    2. rectTransform.offsetMax = new Vector2(rectTransform.offsetMax.x, top);
    IIRC RectTransform.rect returns a struct copy of rectTransform's, and you are setting the values on that copy only. Tim C. made a post on it one or two days ago.

    Also, I know that while offsetMax.x corresponds to the "right" property, "right" is actually displayed negatively, so you have to set it to opposite what you might expect (i.e.: a right value of 5 becomes maxOffset.x = -5), so I have a feeling it might be the same for top.

    Edit: Confirmed (and corrected) by Runevision below. Edited this post to state true information only.
     
    Last edited: Aug 29, 2014
  3. runevision

    runevision

    Joined:
    Nov 28, 2007
    Posts:
    1,892
    Almost. It's actually top that is the opposite of offsetMax.y. So in both cases, it's offsetMax that's inversed while offsetMin is not.
     
    Tempest_mi, F-N, neilsarkar and 3 others like this.
  4. Senshi

    Senshi

    Joined:
    Oct 3, 2010
    Posts:
    557
    Ah, that makes sense! It seems I mixed up top and bottom entirely in that post. Fixed now, thanks for your input!
     
  5. hodgson_gses

    hodgson_gses

    Joined:
    Nov 20, 2014
    Posts:
    2
    Senshi you have no clue how helpful you've been. I've been searching for 4 hours for this thread XD
     
    Yleisnero, Anisoropos and Senshi like this.
  6. elpuerco63

    elpuerco63

    Joined:
    Jun 26, 2014
    Posts:
    271
    Hi, are you able to give a code snippet example of this? I have been trying and unable to change the top and bottom of my buttons to position on screen.

    Thanks
     
  7. Senshi

    Senshi

    Joined:
    Oct 3, 2010
    Posts:
    557
    Hi, the above code snipper should still work. Keep in mind that there are both a pixel offset position (offsetMin/ Max) and an anchor position relative to the parent size (anchorMin/ Max). Perhaps you accidentally set both (to cancel eachther our) or just the wrong one?
     
  8. elpuerco63

    elpuerco63

    Joined:
    Jun 26, 2014
    Posts:
    271
    Hi, after further searching I go a reply pointing me towards vertical layouts and that has fixed it all for me, thanks ;-)
     
  9. Pokarev

    Pokarev

    Joined:
    Oct 12, 2012
    Posts:
    3
    Thank you! code is working!
     
  10. SubZeroGaming

    SubZeroGaming

    Joined:
    Mar 4, 2013
    Posts:
    1,008
    You can also create a struct for top, left, right, bottom and then a function to convert the offset rect.
     
  11. JPsLucky13

    JPsLucky13

    Joined:
    May 6, 2015
    Posts:
    1
    Thank you so much, this was very helpful!
     
  12. njwm

    njwm

    Joined:
    Apr 30, 2013
    Posts:
    26
  13. deLord

    deLord

    Joined:
    Oct 11, 2014
    Posts:
    306
    Seriously, how sh*t is it that you cannot use newButton.GetComponent<RectTransform>().anchoredPosition.Set() ???? I also have been searching for hours until I found this thread

    If that method is a noop, then please remove it. How can anyone know to use anchoredPos = new Vector() instead of .Set()?
     
    kwcae likes this.
  14. runevision

    runevision

    Joined:
    Nov 28, 2007
    Posts:
    1,892
    It's a limitation in the C# language. It's the same for every property of struct type.

    Since structs are always passed by copy and not as reference, you get a copy of the struct, then you change the copy using the Set method, but the value inside the transform is not affected by this. It's super annoying but not anything we can solve and still be C# language compatible.
     
    SubZeroGaming likes this.
  15. User340

    User340

    Joined:
    Feb 28, 2007
    Posts:
    3,001
    So you could fix it, it just wouldn't be C# anymore, right?
     
  16. SubZeroGaming

    SubZeroGaming

    Joined:
    Mar 4, 2013
    Posts:
    1,008
    Here's your resolution.
     
    PizzaProgram likes this.
  17. runevision

    runevision

    Joined:
    Nov 28, 2007
    Posts:
    1,892
    Sure. It works in javascript (unityscript).

    (Actually I'm not completely sure if calling .Set will work in javascript, but you can definitely do transform.position.x = 5; - another thing you can't do in C# for the same reason.)

    But for C# we are committed to staying compatible with the official C# language, so fixing it there is not something we want to do, despite the annoyance.
     
    User340 likes this.
  18. SubZeroGaming

    SubZeroGaming

    Joined:
    Mar 4, 2013
    Posts:
    1,008
    Smart move. Keep C# completely on it's own. It helps everyone in the long run. Better yet, remove UnityScript and just force everyone to use C#. Problem solved :)
     
  19. Lord-Megabite

    Lord-Megabite

    Joined:
    Feb 21, 2015
    Posts:
    8
    // [ left - bottom ]
    slideArea.gameObject.GetComponent<RectTransform>().offsetMin = new Vector2(10f, 10f);
    // [ right - top ]
    slideArea.gameObject.GetComponent<RectTransform>().offsetMax = new Vector2(-10f, -10f);

    This give you :
    Left = 10
    Top = 10
    Right = 10
    Bottom = 10
     
  20. SubZeroGaming

    SubZeroGaming

    Joined:
    Mar 4, 2013
    Posts:
    1,008
    gross...

    Just make a struct.
     
    mchts likes this.
  21. Lord-Megabite

    Lord-Megabite

    Joined:
    Feb 21, 2015
    Posts:
    8
    Ok, I understand that this is not the best method, but really runs. Can you example a bit what is the mean for creating a struct to solve this problem ? Thanks !
     
  22. leegod

    leegod

    Joined:
    May 5, 2010
    Posts:
    2,476
    This does not work at all...

    Why? I did,

    sysText.rectTransform.offsetMin = new Vector2(0, 0);
    sysText.rectTransform.offsetMax = new Vector2(0, OneLineHeight * many);

    But rect shrink and it become negative value window...

    I just want to make window that enlarge vertically upwards.
     
  23. mabakay

    mabakay

    Joined:
    Jun 10, 2016
    Posts:
    20
    Runevision you for sure did not made Unity from scratch. The division for structs and classes is made in many languages on purpose. As you wrote structs by default are passed by copy and classes by reference. But structs in C# can also be passed by reference when used "ref" keyword.

    The reason why it works in javascript is becouse everything in javascript is an object and is by default passed by reference. In other words this "annoying" method of settings values in Unity's properties has beed chosen by Unity designers and has nothing to do with C# language itself.
     
    Last edited: Jul 13, 2016
  24. runevision

    runevision

    Joined:
    Nov 28, 2007
    Posts:
    1,892
    The ref keyword is something that exists for method arguments, not for properties, which is what we're discussing here.

    Not true for Unity's version of "Javascript" (also called Unityscript by some people) which is what I referred to. It works just like C#, you have class objects and structs, and structs are passed by value. But you *can* use the syntax mentioned in the post by leegod above in Unity's Javascript. It doesn't change the basic properties of classes versus structs, it's just nice syntactic sugar.

    Nope, there was active work done by Unity designers to remove this annoyance in Unity's version of Javascript, while the same was not possible for C#.
     
  25. mabakay

    mabakay

    Joined:
    Jun 10, 2016
    Posts:
    20
    If it has classes and structs it is not a Javascript. User leegod shows us this:

    This also works in C#. If we assign struct to property which is a struct everything will work just fine. Can't see any other of his/her posts in thread.

    Structs are passed by copy (implictly). If you design Vector3 as public struct Vector3 { ... as you (Unity Team) did, then you can't blame language that transform.position.x = 5f doesn't work. "transform.position" in that situation returns copy of property not a reference. If you did it as public class Vector3 { ... the "annoyance" wouldn't exist.
     
    Memphizzz likes this.
  26. mwillson

    mwillson

    Joined:
    Jul 1, 2015
    Posts:
    5
    Not to completely sideline the OP and the actual topic, but kinda since we are talking about it:

    Is Vector2 and Vector3, etc.. being defined as structs(as opposed to classes) and thus, limited in the aforementioned ways, the reason why they are impossible to serialize, vis a vis the System Serialize functions (binary formatter and such)?
     
  27. eses

    eses

    Joined:
    Feb 26, 2013
    Posts:
    2,637
  28. rainboww

    rainboww

    Joined:
    Jan 5, 2017
    Posts:
    125
    It is horrible that the unity devs dont manage to give a proper way to enter a new value and overwrite the struct with a new struct with the new value changed.

    Well i have a rect transform which is streched. I want to manipulate the entry labeled "left" what is the proper way to do this from script? I cannot find the answer in this thread or in the manual.
     
    Ruslank100 and PizzaProgram like this.
  29. PizzaProgram

    PizzaProgram

    Joined:
    Feb 12, 2014
    Posts:
    17
    My opinion is, that the new UI system with RectTransform is great! But it definitely needs:
    -
    some more easy-setup functions and
    - a better tutorial / example to show how to manage everything.
    It took me 2 weeks to read all the forums and find out how to force-rearrange panels in a scroll.

    I think this part is a bit buggy yet (5.5.2f1), because it works perfectly with design-time predefined panel and text arrange system, but as soon as you try to clone from one of those panels (prefabs) and place in the same scroll >> it gets totally messy. Crazy anchor- and width-/height- values. :(

    Summarized, using ALL this functions together helped me to re-arrange panel sizes and positions:
    ...
    Code (CSharp):
    1. // First, you need to resize the Container, to fit for all the panels you are putting into it.
    2. // The Container anchors must be TOP-LEFT ([B]not [/B]the default setting: stretched)
    3. // PN_rect is the prefab-panel we cloned
    4.  
    5.        int MaxLines = MyArray.Length + 1;
    6.        int LineHeight = 24;
    7.        float LineSpace = 1.2f;
    8.        var krec = Container.GetComponent<RectTransform>();
    9.        krec.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical  , MaxLines * LineHeight * LineSpace);
    10.        krec.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, PN_rect.rect.width   );
    11.  
    12.        PN_rect.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, LineHeight);
    13.  
    14. // Than you resize and re-arrange all the clone-panels
    15.        foreach (RectTransform rec in Container.transform) {
    16.             if (rec.gameObject.name != "My original prefab panel") { //exclude the base-panel (typically a headline)
    17.                rec.offsetMin = new Vector2( 0f, -LineHeight); //  ! must be negativ
    18.                rec.offsetMax = new Vector2( 0f, 0f);
    19.                rec.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical  , PN_rect.rect.height);
    20.                rec.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, PN_rect.rect.width );
    21. // at creation\cloning > you add a self-created simle Mono-class ... (see below) and must set Line-Number
    22. // to maintain order and to know which line is which .. if you click on one
    23.                var LnSrc = rec.gameObject.GetComponent<LineNumber_Script>();
    24.                rec.transform.localPosition = new Vector3(
    25.                    PN_rect.localPosition.x, // rec.transform.position.x,
    26.                    -LnSrc.number * LineHeight * LineSpace,
    27.                    rec.transform.position.z
    28.                );
    29.                rec.localScale = Vector3.one;
    30.            }
    31.        }
    32. ...
    33. public class LineNumber_Script : MonoBehaviour {
    34.    public int number {get; set;}
    35. }
    36.    
    37.  
     
  30. Assembler-Maze

    Assembler-Maze

    Joined:
    Jan 6, 2016
    Posts:
    630
    Since I haven't found a complete solution for simply setting 'left' 'top' 'right' 'bottom' on a RectTransform I have made a tiny utility script that can do it for a RectTransform that is set to a 'stretched' alignment. Not only 'top'/'bottom' but 'left'/'right' also, maybe someone will need it:


    Code (CSharp):
    1.  public static void SetRect(RectTransform trs, float left, float top, float right, float bottom)
    2. {
    3.     trs.offsetMin = new Vector2(left, bottom);
    4.     trs.offsetMax = new Vector2(-right, -top);
    5. }
     
  31. ilysha2

    ilysha2

    Joined:
    Apr 21, 2017
    Posts:
    1
    Hi, I want to do this so I can drag the sprite into the unit, but I have a bug: NullReferenceException: Object reference not set to an instance of an object. or other error help me I will throw a picture
     

    Attached Files:

  32. andyz

    andyz

    Joined:
    Jan 5, 2010
    Posts:
    2,276
    [At risk of digging up old topic]
    It is annoying when Unity do not make scripting reflect what is in the inspector - there are good examples above but if you just want to set left/right/top/bottom then extensions will do close enough though you must call a method rather than set a property:

    Code (CSharp):
    1. public static class RectTransformExtensions
    2. {
    3.     public static RectTransform Left( this RectTransform rt, float x )
    4.     {
    5.         rt.offsetMin = new Vector2( x, rt.offsetMin.y );
    6.         return rt;
    7.     }
    8.  
    9.     public static RectTransform Right( this RectTransform rt, float x )
    10.     {
    11.         rt.offsetMax = new Vector2( -x, rt.offsetMax.y );
    12.         return rt;
    13.     }
    14.  
    15.     public static RectTransform Bottom( this RectTransform rt, float y )
    16.     {
    17.         rt.offsetMin = new Vector2( rt.offsetMin.x, y );
    18.         return rt;
    19.     }
    20.  
    21.     public static RectTransform Top( this RectTransform rt, float y )
    22.     {
    23.         rt.offsetMax = new Vector2( rt.offsetMax.x, -y );
    24.         return rt;
    25.     }
    26. }
    27.  
    28. //example use - almost as good as Right = 5 but method used:
    29. rectTransformName.Right( 5 );
     
  33. AcademyOfFetishes

    AcademyOfFetishes

    Joined:
    Nov 16, 2018
    Posts:
    219
    Where can I find a tutorial that explains details like this in depth? Somewhere on the internet must be a tutorial that explains how to position
    RectTransform
    s in code, but I have not been able to find it after MONTHS of searching. It's really hard to know if the information in this thread is even relevant to my scene, because sometimes I find information saying it's all relative to anchors.
     
    Ruslank100 likes this.
  34. ksakins

    ksakins

    Joined:
    Aug 29, 2015
    Posts:
    16
    Old thread, but none of the suggestions here work for me. Pretty frustrating and annoying API to be honest. I'm trying to simply set the top value of the RectTransform using the .offsetMax field. After setting it, behind the scenes Unity is recalculating the RectTransform top and bottom values, thus changing the values I set in code. So very annoying, it should just take what I tell it I want, not try to do things behind the scenes for me.
     
  35. all12jus

    all12jus

    Joined:
    Mar 20, 2013
    Posts:
    1
    You could also do:
    Code (CSharp):
    1. public static class Extensions
    2. {
    3.     public static void SetRect(this RectTransform trs, float left, float top, float right, float bottom)
    4.     {
    5.         trs.offsetMin = new Vector2(left, bottom);
    6.         trs.offsetMax = new Vector2(-right, -top);
    7.     }
    8. }
     
    ltomov likes this.
  36. OleksandrMartysh

    OleksandrMartysh

    Joined:
    Dec 13, 2015
    Posts:
    25
    It is very usefull for me. Thank you very much!
     
  37. j04milan

    j04milan

    Joined:
    Feb 6, 2019
    Posts:
    44
    Is there anyone struggling with this issue? If you want to change left,right,top bottom simply use:
    To change top value for example
    Code (CSharp):
    1. Rectransform yourRT;
    2. YourRT.offsetMax = new Vector2 (yourRT.offsetMax.x, 100f);//100f your new value
     
  38. DankalApps

    DankalApps

    Joined:
    Mar 8, 2023
    Posts:
    17
    It is impossible to work with.
    I have game object inside other game object and I try to make simple padding with this code:
    Code (CSharp):
    1.  
    2. rectTransform.anchorMin = new Vector2(0.2f, 0.2f);
    3. rectTransform.anchorMax = new Vector2(0.8f, 0.8f);
    4. rectTransform.offsetMin = Vector2.zero;  // no matter what I put here
    5. rectTransform.offsetMax = Vector2.zero;  // no matter what I put here
    6.  
    and what I get is always this:
    upload_2023-7-3_19-56-1.png

    No idea where or when this gets changed, or why to -50.

    I have some Content Size Fitters and Layout Groups, but much higher in hierarchy. If anything, they should change parents of this "grandchild".