Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

How to Scale child like it was part of parent?

Discussion in 'UGUI & TextMesh Pro' started by rpuls, Nov 10, 2019.

  1. rpuls

    rpuls

    Joined:
    Feb 3, 2017
    Posts:
    101
    I have been struggling with this exact problem multiple times, and I have never found a really good solution. In short, I have a GameObject which is an UI Image, this GameObject have multiple child objects, which are all of same type, when modifying the size (not scale!) of the parent, I would like the child object to be sized along, as if they were pixels on the parent image. How do I do that?

    This behavior is easily done If the parent is just scaled, if i stretch it in width by increasing scale y, the children will be stretched as well. If i then increase scale x equal amount I am back to original aspect ratio of both parent and its children, everything is just bigger now.

    My problem is that my parent width and height is based on very complicated UI aspect ratio fitters and custom scripts. So I cannot "just use scale".

    Case example:
    I have a yellow square 400x400, with a child, red square 100x100. red square is in pos x -100 y -100

    If i increase yellow squares height to 500, the red squares height will be unchanged, while its desired height would be 120.

    As you can see here, the red is still a square while the parent is a rectangle, i.e. the child does not scale like it was pixels in the parent image.

    It should have looked like this:


    Now, some of you might be quick and say "just use anchors". but that doesn't solve the problem. I can anchor the child to stretch the full width and height of parent, i then offset 50 pixel bottom and left, 250 pixels top and right. It now looks the same. If I increase the parents width the red square will also increase in width, but the offset is not increasing, as they are fixed values, breaking the composition.

    example when increase parent width to 600

    how it should look:


    Again, I keep running in to this problem over and over again, in various setups. I hope that someone here has a dirty trick up the sleeve to fix this problem.
     
    Acoustic125 and synthc like this.
  2. MSplitz-PsychoK

    MSplitz-PsychoK

    Joined:
    May 16, 2015
    Posts:
    1,278
    Select the child object that you want to scale, click the image in the upper-left of your inspector (the image with the squares and the red or blue lines above the word "Anchors"), then select the bottom-right option with the 4 blue arrows. That will set your child's rect to automatically keep the same relative width/height and position to your parent when the parent's rect changes.
     
  3. Antistone

    Antistone

    Joined:
    Feb 22, 2014
    Posts:
    2,833
    Actually, that preset causes the child to maintain the same absolute distance from each corner of the parent, not the same ratio.

    For instance, suppose you have a 200x200 parent, and a 100x100 child right in the center, so that there is a gap of 50 between the child and the outer edge of the parent on all sides. If the child uses this preset (anchors of 0,0 to 1,1), then when you stretch the parent to be 2000x2000, the child will become 1900x1900, maintaining the same gap of 50 units on every side--and in the process, it will change from being 50% of the height/width of the parent to being 95% of the height/width of the parent.




    If you want children to scale "like they were pixels" of the parent, then you need to set the child's anchors to exactly match the child's corners, so that they're right on top of each other in the scene view. Continuing my example of a 200x200 parent with a 100x100 child in the center, you'd set the child's anchors to min 0.25 and max 0.75.

    There is no preset for this in the inspector, and it's hard to get an exact match because anchors snap to a fine-but-noticeable invisible grid. Your best option is probably to put the anchors where you want the corners to be, then set the child's positional coordinates all to zero (moving the child to match the anchors instead of the other way around).

    Also, since this requires different anchors for every child, you can't copy/paste; you need to separately and explicitly set the anchors for each child one-at-a-time.
     
  4. rpuls

    rpuls

    Joined:
    Feb 3, 2017
    Posts:
    101
    Thanks for your input! That makes sense. I actually tried doing something that seems somewhat similar, by create a script for the child that would take in 4 float values and a parent. I then used each value as x, y, w, h and multiplied x and w with parent width, y and h with parent height. allowing me to use the values as "percent of parent"s width and height. But this was also impossible to get exactly right by manually changing the values but i did get it quite close.

    Another thing that I have done in other cases, was to export each child item as a png with the same resolution as the parent, positioned and scaled correctly and left everything around it transparent. I could then anchor each child to strect withd and height of parent this would position it correctly in all scales and sizes. But this approach is also not very desireable, as first of all it is a ton of work to export each child individually, but also the png files cannot be used to do the same on parents of another dimension.

    But it sounds like there is no trivial way of solving this. I might consider looking in to writing a more complex script
     
  5. hippocoder

    hippocoder

    Digital Ape Moderator

    Joined:
    Apr 11, 2010
    Posts:
    29,723
    You can use yourTransform.TransformPoint / vector etc or similar call to scale or rotate something as if it were a child, without doing the whole parenting stuff.
     
  6. rpuls

    rpuls

    Joined:
    Feb 3, 2017
    Posts:
    101
    Not sure I quite follow here. So my all parent elements in this case, are in a horizontal layout group. they must be aligned side by side and scroll horizontally. I think I have to have all the text, buttons, icons etc as children on those parent element for them to be placed in/on the parent image and not next to them side by side as if they were just another item in the layout group.

    Or maybe I am misunderstanding something here. Could you clarify what you mean with an example ?
     
  7. Stardog

    Stardog

    Joined:
    Jun 28, 2010
    Posts:
    1,886
    You could use horizontal/vertical groups and have the 'offset' be an empty element with a small Flexible Width.
     
  8. Hosnkobf

    Hosnkobf

    Joined:
    Aug 23, 2016
    Posts:
    1,076
    Better UI contains a tool which adjusts the anchors correctly with a single click.
     
  9. rpuls

    rpuls

    Joined:
    Feb 3, 2017
    Posts:
    101
    This proposal is exactly what I mean when I say "I have never found a good solution".. this sounds like a weird hack, and I don't even think it will help my case...

    So there is a single click action that does what exactly? adjust the anchors "correctly" but is it aware of what I am trying to achieve ? I would like to see that in action before spending 60€ and a lot of hours reading their documentation and experimenting. Could you elaborate a little or give an example where this asset does what I need done?
     
  10. Hosnkobf

    Hosnkobf

    Joined:
    Aug 23, 2016
    Posts:
    1,076
    It does this one action you almost always need to do (what you describe in the first post) and which unity cannot do: snapping the anchors to the border of the rect transform.
    It is a little piece of Better UI but probably the most used, that is why I have made a whole video for this feature:

    The video above is from an older version.
    In this video you can see how it works with the current version:


    Please note that it might not work as expected for rotated canvases or UI objects in world space.
     
  11. rpuls

    rpuls

    Joined:
    Feb 3, 2017
    Posts:
    101
    Okay thanks for the details! So far good new as I do not use rotated canvas or world space in this case. I might very well end up getting this asset then, as I mention in first post, this is a problem I run into in almost all my projects.

    Do you by any chance know if there is a trial version of this asset or a demo? Would still like to have 100% confirmation that it will solve my problem before purchasing. I have left out some details when boiling down this example, that potentially could change the situation. Otherwise I can probably find someone who owns the asset, send a boiled down version of my project have the person click the magic button and send it back and then I can try all supported screen formats to see if it looks correct on all if them. If that is the case, then this plugin is exactly what I need.
     
  12. Hosnkobf

    Hosnkobf

    Joined:
    Aug 23, 2016
    Posts:
    1,076
    I actually would like to make a free version of the asset but there is a lot of work which would need to be done to prevent people using the free version for commercial projects. So, hopefully in the future there is a free version.

    However, I will send you the Beta of the previous version via PM for evaluation.
     
  13. Yucatron

    Yucatron

    Joined:
    Dec 8, 2019
    Posts:
    2
    Hello!, maybe is late know but to send automatically the anchors to the corner you can use a tool called uGUI..

    You can find it here, is a editor script https://forum.unity.com/threads/scr...49.568112429.1601439109-1633937339.1575256747
     
  14. FaerieFire

    FaerieFire

    Joined:
    Oct 3, 2019
    Posts:
    2
    Sorry for the notification. I just want to let you know that I love you and this helped me a tonne.
     
  15. _watcher_

    _watcher_

    Joined:
    Nov 7, 2014
    Posts:
    259
    This works perfectly, except in cases like 'incoming object from outside of parent image [eg asteroid]'). Im pasting an example screen. Any ideas how to make this work and 'scale the incoming object from outside of parent image scale with parent image'?
    upload_2023-9-18_12-58-25.png
     
  16. Hosnkobf

    Hosnkobf

    Joined:
    Aug 23, 2016
    Posts:
    1,076
    Also animate the anchored position rather than local position / size delta.

    PS: My asset Better UI makes such simple animations easy to set up and trigger (as long as you only want to animate between two transforms) with the Location Animations component.
     
  17. Antistone

    Antistone

    Joined:
    Feb 22, 2014
    Posts:
    2,833
    Yeah, it's kinda dumb that Unity won't let you set anchors outside of the parent.

    OK, a few options here.

    1. I heard a rumor that you CAN set the anchors outside of the parent if you do it via script or via animation curves. (Have not personally confirmed.) If you are animating your thing anyway then this might not be much extra work.

    2. You can set the anchors to be the correct SIZE but the wrong POSITION, and then modify the child's position relative to its anchors (RectTransform.anchoredPosition) to get it into the right place. This might mean that the math for setting its position will need to somehow involve the parent's dimensions (and update when the parent changes, even if the child hasn't changed).

    3. You can somehow restructure your object hierarchy to include an object that is big enough to cover the entire area where asteroids might be, and then anchor them to that.

    a. For example, you could make it so that your space background is actually a child of some much bigger object, and then make your asteroids be children of that larger parent (and therefore siblings of the current background object) rather than children of the background object.

    b. Or you could create an invisible child of your space background object set to stretch to the size of the background (anchors at the 4 corners) but with a local scale of something like 2.0, so that this invisible child actually stretches from the equivalent of anchors -.5 to +1.5, and then make the asteroids children of that (but make them half as big, to cancel out the scaling factor of 2 that they'll inherit from the invisible object).

    c. Or you could just take the space background object itself and make it larger. This might involve modifying the image asset to include a border region (which doesn't necessarily have to be visible to the player) and/or using a mask to prevent it from being visible outside of its current area.

    4. You could restructure your game system so that your space background object doesn't need to change dimensions, and then you won't need to worry about the asteroids' anchors in the first place. (Note that you can still change the size of the space background using its scaling factor; that's different from its dimensions and will automatically scale all children by the same amount regardless of how their anchors are set.)
     
  18. _watcher_

    _watcher_

    Joined:
    Nov 7, 2014
    Posts:
    259
    Thanks a LOT for your time and the options you came up with and gave to possibly amend this issue. Some of them i never thought of (1, 2), some of them i considered variations of myself (3-x).

    Originally, i actually wanted to just use scene GOs/Transforms, but then i realized that the UI can be made to scale all its children with the main bg and thought 'why create my custom boxing system, when i can just use AspectRatioFitter on the Background item, and be done with it (love using whats already available). But it shouldnt be difficult to create custom boxing with for ex a Collider2D (or a custom Rect with CustomEditor for visual cue in the scene view) to stretch as big as the size of BG (act as the boxed item's size), but allow for objects from outside this C2D to 'come in'. Transform children already scale automatically with their parent. Also, The C2D would then be boxed to ENVELOPE the Camera viewport. So this could work also, albeit its not a CanvasUI solution, but a displaylist Transform one. But some of your detailed suggestions are great to start with, so i'd start with that!!