Search Unity

  1. Unity 2017.2 beta is now available for download.
    Dismiss Notice
  2. Unity 2017.1 is now released.
    Dismiss Notice
  3. Introducing the Unity Essentials Packs! Find out more.
    Dismiss Notice
  4. Check out all the fixes for 5.6 on the patch releases page.
    Dismiss Notice
  5. Help us improve the editor usability and artist workflows. Join our discussion to provide your feedback.
    Dismiss Notice

Setting top and bottom on a RectTransform

Discussion in 'Unity UI & 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?
     
  2. Senshi

    Senshi

    Joined:
    Oct 3, 2010
    Posts:
    510
    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

    Unity Technologies

    Joined:
    Nov 28, 2007
    Posts:
    1,193
    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.
     
  4. Senshi

    Senshi

    Joined:
    Oct 3, 2010
    Posts:
    510
    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
     
    Anisoropos and Senshi like this.
  6. elpuerco63

    elpuerco63

    Joined:
    Jun 26, 2014
    Posts:
    223
    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:
    510
    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:
    223
    Hi, after further searching I go a reply pointing me towards vertical layouts and that has fixed it all for me, thanks ;-)
     
  9. grabbly

    grabbly

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

    SubZeroGaming

    Joined:
    Mar 4, 2013
    Posts:
    1,009
    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
    rakkarage likes this.
  13. deLord

    deLord

    Joined:
    Oct 11, 2014
    Posts:
    199
    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()?
     
  14. runevision

    runevision

    Unity Technologies

    Joined:
    Nov 28, 2007
    Posts:
    1,193
    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. _Daniel_

    _Daniel_

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

    SubZeroGaming

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

    runevision

    Unity Technologies

    Joined:
    Nov 28, 2007
    Posts:
    1,193
    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.
     
    _Daniel_ likes this.
  18. SubZeroGaming

    SubZeroGaming

    Joined:
    Mar 4, 2013
    Posts:
    1,009
    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:
    3
    // [ 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
     
    PizzaProgram likes this.
  20. SubZeroGaming

    SubZeroGaming

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

    Just make a struct.
     
  21. Lord-Megabite

    Lord-Megabite

    Joined:
    Feb 21, 2015
    Posts:
    3
    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:
    1,659
    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:
    15
    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

    Unity Technologies

    Joined:
    Nov 28, 2007
    Posts:
    1,193
    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:
    15
    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.
     
  26. mwillson

    mwillson

    Joined:
    Jul 1, 2015
    Posts:
    3
    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:
    679
  28. rainboww

    rainboww

    Joined:
    Jan 5, 2017
    Posts:
    22
    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.
     
    PizzaProgram likes 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:
    429
    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. }
     
    deltamish likes this.
  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: