Search Unity

  1. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Modify the width and height of RectTransform

Discussion in 'UGUI & TextMesh Pro' started by lzt120, Sep 27, 2014.

  1. lzt120

    lzt120

    Joined:
    Apr 13, 2010
    Posts:
    93
    How Can I modify the width and height of RectTransform ?
     
    The-It, Ruslank100, ufukrdc and 7 others like this.
  2. Chudziutki

    Chudziutki

    Joined:
    May 16, 2014
    Posts:
    3
    Try this

    RectTransform rt = UICanvas.GetComponent (typeof (RectTransform)) as RectTransform;
    rt.sizeDelta = new Vector2 (100, 100);

    where UICanvas is Canvas from scene.
     
  3. lzt120

    lzt120

    Joined:
    Apr 13, 2010
    Posts:
    93
    Thanks very much.
     
    Raisito and donmetapod like this.
  4. jashan

    jashan

    Joined:
    Mar 9, 2007
    Posts:
    3,307
    A somewhat nicer way to write this (assuming that canvas is a variable with that Canvas from the scene):

    Code (csharp):
    1. RectTransform rt = canvas.GetComponent<RectTransform>();
    2. rt.sizeDelta = new Vector2(100, 100);
     
  5. IgorAherne

    IgorAherne

    Joined:
    May 15, 2013
    Posts:
    392
    if anyone like me is wondering what the is sizeDelta, here is explanation with pictures.
    Was browsing interwebs, trying to understand what the documentation actually means.
     
  6. Jayno

    Jayno

    Joined:
    Feb 20, 2013
    Posts:
    5
    @Chudziutki thank you
     
  7. lemonLimeBitta

    lemonLimeBitta

    Joined:
    Aug 28, 2014
    Posts:
    4
    Sorry to necropost a bit here,
    Can anyone explain to me why I can't change the rect transforms height directly?

    In @jashan 's example,

    1. Code (CSharp):
      1. RectTransform rt = canvas.GetComponent<RectTransform>();
      2. rt.sizeDelta = new Vector2(100, 100);
      Why can't I do something like:
      Code (CSharp):
      1. RectTransform rt = canvas.GetComponent<RectTransform>();
      2. rt.rect.height= 100;
      or even this doesn't work
      Code (CSharp):
      1. RectTransform rt = canvas.GetComponent<RectTransform>();
      2. rt.sizeDelta.y =  100;
     
  8. gg_michael

    gg_michael

    Joined:
    Sep 24, 2012
    Posts:
    73
    That's just not how the properties work. Similarly to how you can't directly set a single axis of a Vector3, you have to set the whole thing at once. But you can reference the current value for whatever you don't want to change. So instead of:

    Code (CSharp):
    1. RectTransform rt = canvas.GetComponent<RectTransform>();
    2. rt.sizeDelta.y =  100;
    It would be:

    Code (CSharp):
    1. RectTransform rt = canvas.GetComponent<RectTransform>();
    2. rt.sizeDelta = new Vector2 (rt.sizeDelta.x, 100);
     
  9. IgorAherne

    IgorAherne

    Joined:
    May 15, 2013
    Posts:
    392
    gonna also try now

    myRecttransf.SetSizeWithCurrentAnchors() ;
    followed by
    myRecttransf.ForceUpdateRectTransforms();

    Need something like this because re-parenting back and forth, and adjusting the recttransform several times during a frame messes up any adjustments done previously, during this frame. Hopefully forceUpdateRectTranasforms will fix these things

    Edit: Well, decided to go with a hybrid:
    Code (CSharp):
    1. // places rect transform to have the same dimensions as 'other', even if they don't have same parent.
    2.     // Relatively non-expensive.
    3.     // NOTICE - also modifies scale of your rectTransf to match the scale of other
    4.     public static void MatchOther(this RectTransform rt,  RectTransform other){
    5.         Vector2 myPrevPivot = rt.pivot;
    6.         myPrevPivot = other.pivot;
    7.         rt.position =  other.position;
    8.  
    9.         rt.localScale = other.localScale;
    10.          
    11.         rt.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal,  other.rect.width);
    12.         rt.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical,  other.rect.height);
    13.         //rectTransf.ForceUpdateRectTransforms(); - needed before we adjust pivot a second time?
    14.         rt.pivot = myPrevPivot;
    15.     }
     
    Last edited: Sep 11, 2019
  10. a436t4ataf

    a436t4ataf

    Joined:
    May 19, 2013
    Posts:
    1,914
    So, despite the 16 likes, this is 100% incorrect and should NOT be used:

    ...that will only work in the random situation where your anchors are all at a single point (and it's only lucky that it works). It will fail in most situations.

    As per IgorAherne's posts, as far as I can tell, setting size should only be done using:

    RectTransform.SetSizeWithCurrentAnchors

    NB: the Unity docs are shamefully bad here. They literally don't say what the correct way is to set size, and only tell you that the normally, default, correct way won't work because it's blocked (Unity made the rect read-only).

    EDIT: as of 2018/2019, there's also a minor bug in Unity's implementation of this method. Latest 2018.x version was spamming my console with internal Unity errors. Logged the bug, and had an email this week from Unity saying it'll be fixed soon.
     
    Last edited: Feb 23, 2019
  11. magnitocorp

    magnitocorp

    Joined:
    Dec 5, 2018
    Posts:
    1
    Get the rect of that RectTransform,
    Rect rectContainer = Other.rect;
    rectContainer.height = 'the size you want';
     
  12. a436t4ataf

    a436t4ataf

    Joined:
    May 19, 2013
    Posts:
    1,914
    LOL. Now the definitely, absolutely, incorrect answer has 21 likes. People just don't read. Lazy developers = developers who won't be shipping games.

    EDIT 2020: Over 30 likes. It would be much better if @Chudziutki would come back and edit their answer - at least delete the incorrect info that is breaking people's projects every day :).

    @magnitocorp - you are 100% incorrect. That will achieve literally nothing. There is no way you tried that code - it could never work. We all make mistakes, that's fine, but ... if you're going to give advice, at least TRY IT YOURSELF first and check your understanding before handing out ideas :).
     
    Last edited: Jun 5, 2020
  13. elKarkayu

    elKarkayu

    Joined:
    Mar 23, 2017
    Posts:
    18
    thanks for your replay a436t4ataf!!
     
  14. naviln

    naviln

    Joined:
    Oct 18, 2016
    Posts:
    32
    Legend, thanks so much for sharing the extension method!!
     
  15. nukadelic

    nukadelic

    Joined:
    Aug 5, 2017
    Posts:
    73
    Keep in mind the scale, here I'm getting 50% of the screen size in canvas units :

    Code (CSharp):
    1.  
    2. var sizeDeltaY = 0.5f * Screen.height / canvas.scaleFactor
    3. m_RectTransform.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, sizeDeltaY );
    4.  
     
    Last edited: Mar 15, 2020
    Lorrak and a436t4ataf like this.
  16. MaxxVelocity

    MaxxVelocity

    Joined:
    Sep 29, 2019
    Posts:
    12
    I realize I'm late to the party here, but...

    That's exactly how "properties" work. What we have here is a bunch of bugs in Unity that expect the developers to know what the workaround is to assume properties in Unity don't work like they would in general. Having a "setter" explicitly declared, that does not set the value of it's corresponding property, isn't something anyone should ever have to deal with.

    We need some process for fixing the multitude of bugs in the Unity libraries without waiting for the official devs to get around to it. This is a dumpster fire.
     
    cathygames1, cwBAH, halley and 2 others like this.
  17. jashan

    jashan

    Joined:
    Mar 9, 2007
    Posts:
    3,307
    Yes and no. Yes, it's how properties work, and no, this is not a bug in Unity but how C# has been designed. The important thing that apparently has been missing here in this thread is that Vector3 is a struct, so it's "by value" and not "by reference". This difference is really important to understand when working with Unity.

    When you have a property that returns a reference-type (i.e. an object that is an instance of a class, like e.g. a child of MonoBehaviour), you can make changes to the returned instance and because it's just a reference, those changes will actually be done on the original object.

    With "by-value" types (i.e. an object that is an instance of a struct), on the other hand, what you get is a "copy" of the original object, so when you make any changes, those will not be applied on the original object but just on the copy. Fortunately, the C# compiler knows about this and gives you a compile-time error - otherwise, you'd have to deal with very hard to debug runtime errors.

    Unity did work around this with Shuriken (or was it PostProcessing ... or both?), by keeping references to the original objects in most of the types there ... but it's actually quite confusing because it's not standard behavior but quite a hack.

    One reason I believe Unity is using structs a lot is that they are usually kept on the stack instead of the heap, so it's basically a performance optimization at the expense of some convenience. There's more to it but here's some actual profiling ... from 2015, so some of those findings may actually be outdated but the general idea still stands.
     
  18. KiryaRizhiy

    KiryaRizhiy

    Joined:
    Apr 13, 2019
    Posts:
    3
    Igor, spasibo, bratan!
     
  19. wolfomat

    wolfomat

    Joined:
    Oct 19, 2014
    Posts:
    24
    so, i am trying to perform this, but none of this works.
    i try to rescale an image place on a canvas.
    What i am calling:
    Code (CSharp):
    1.  rectTransform.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, 2);
    2.             rectTransform.ForceUpdateRectTransforms();
    but the size won't change?

    Turned out i've searched for the wrong element. it's now doing something ;)
     
    Last edited: Oct 17, 2020
  20. MarkMaa

    MarkMaa

    Joined:
    Jan 20, 2020
    Posts:
    36
    Thanks, this is really the right way to set the size
     
  21. Mr_yilanci

    Mr_yilanci

    Joined:
    Nov 11, 2019
    Posts:
    7
    Thanks brothers
     
  22. james580

    james580

    Joined:
    Aug 9, 2017
    Posts:
    19
    As others have said, if you try setting through sizeDelta it'll only work if the anchors are at the same point. To correctly set the size regardless of anchor position you need to use rt.SetSizeWithCurrentAnchors(). Here's a simple extension class I made that you can use to easily set the size, or just the width or height. So you can now just call something like "myRT.SetSize(new Vector2(100, 100))" or "myRT.SetWidth(150)" and it will correctly set your rt size.

    Code (CSharp):
    1.  
    2. public static class RectTransformExtensions {
    3.     public static Vector2 GetSize(this RectTransform source) => source.rect.size;
    4.     public static float GetWidth(this RectTransform source) => source.rect.size.x;
    5.     public static float GetHeight(this RectTransform source) => source.rect.size.y;
    6.  
    7.     /// <summary>
    8.     /// Sets the sources RT size to the same as the toCopy's RT size.
    9.     /// </summary>
    10.     public static void SetSize(this RectTransform source, RectTransform toCopy) {
    11.         source.SetSize(toCopy.GetSize());
    12.     }
    13.  
    14.     /// <summary>
    15.     /// Sets the sources RT size to the same as the newSize.
    16.     /// </summary>
    17.     public static void SetSize(this RectTransform source, Vector2 newSize) {
    18.         source.SetSize(newSize.x, newSize.y);
    19.     }
    20.  
    21.     /// <summary>
    22.     /// Sets the sources RT size to the new width and height.
    23.     /// </summary>
    24.     public static void SetSize(this RectTransform source, float width, float height) {
    25.         source.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, width);
    26.         source.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, height);
    27.     }
    28.  
    29.     public static void SetWidth(this RectTransform source, float width) {
    30.         source.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, width);
    31.     }
    32.  
    33.     public static void SetHeight(this RectTransform source, float height) {
    34.         source.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, height);
    35.     }
    36. }
    37.  
     
    Last edited: Mar 9, 2022
  23. shung_unity898

    shung_unity898

    Joined:
    Feb 3, 2022
    Posts:
    1
    When I worked with sizedelta, the width and height values I wanted did not come out normally.

    However, when I use SetSizeWithCurrentAnchors according to the written method, the value I want is normally entered. thank you!
     
  24. RageByte

    RageByte

    Joined:
    Jul 2, 2017
    Posts:
    33
    This still doesn't work...
     
    DavidZobrist likes this.
  25. a436t4ataf

    a436t4ataf

    Joined:
    May 19, 2013
    Posts:
    1,914
    I use this intensively on some very complex situations, it works in all versions of Unity from 2018 onwards.

    There are two caveats I know of, both of which don't change the face 'this works' -- but might cause you to misunderstand what you're seeing.

    1. Scale -- if you change your scale (e.g. at canvas level) then 'size' means different things. Unity does not warn you that you've done this, you have to check your Canvas object and the relevant components that could be added to it.

    2. set anchors -- setting the anchors changes the meaning of size. That's why the method is name '...WithCurrentAnchors()'. But setting the anchors also changes some other internal data for Unity that is poorly explained (I don't think Unity ever documented this properly). So if you're changing pivot + anchors + size, you have to call the 'set pivot' first, and the 'set size' call *last* -- any other order corrupts Unity. (or possibly anchors first, pivots second). This is normal for other windowing APIs, but Unity just chose to 'assume everyone knows' instead of documenting it.
     
  26. AmitTiwari4Unity

    AmitTiwari4Unity

    Joined:
    Aug 26, 2021
    Posts:
    7
    rectTransform.sizeDelta = new Vector2(50, 50);

    where rectTransform will be reference of gameobject with rectTransform component on it.
     
  27. a436t4ataf

    a436t4ataf

    Joined:
    May 19, 2013
    Posts:
    1,914
    Please delete your post. You didn't bother to read the thread you replied to, and you've posted something that has been repeatedly shown to be 100% incorrect. It adds nothing to the conversation.
     
    CunningFox146 likes this.