How do I copy RectTransform?

How do I copy RectTransform?
I have some UI objects that I want to reposition in the same precise position as other UI objects, copying their position and anchorage. In other words, I want to copy the RectTransform component! But if I try to do
A.GetComponent() = B.GetComponent();
clearly doesn’t work.
I also tried to copy every single property but I got disastrous results. And countless other failed attempts.

My Unity version is 2019.4.4f1

the Editor
On the transform component in the Inspector, go to the three vertical dots and click Copy Component. Do the same for the component you want to copy onto and click Paste Component Values.

By Script

someComponent.transform.localPosition = otherComponent.transform.localPosition;

someComponent.transform.position = otherComponent.transform.position;

(someComponent.transform as RectTransform).anchoredPosition = (otherComponent.transform as RectTransform).anchoredPosition

Which one? It depends. If you want two things which share a common parent transform to be in the same position and anchor settings, .localPosition should work. If you want two things with different parent transforms to be in the same world position, the .position may work, given same-anchoring. The most reliable is likely going to be anchoredPosition with the same anchor settings and a common parent. If you have a special or complicated case, you may need to do some math yourself or reorganize the hierarchy or anchor settings so it’s easier.

Note
In general, you can more easily copy component properties than copy components, especially for built-in special components like transform. If you wanted to copy a normal component - just some MonoBehaviour you wrote yourself - then you could probably usevar copy = Object.Instantiate(theThingToCopy); or a variation thereof.

A.GetComponent<RectTransform>() = B.GetComponent<RectTransform>();
The above isn’t going to work for C# reasons: GetComponent returns a reference to the RectTransform on A. Assigning a new reference here won’t work because you don’t have myObject.SomeThingy = someOtherThingy. That would be assignment, replacing one reference for another on myObject. Unity doesn’t expose components on a GameObject as properties like this by design, so there is no myObject.SomeComponent = someOtherComponent replacement. You aren’t allowed to detach myObject component and have it just floating freely except right after instantiating one. To be useful, it must be added to a GameObject. Once added, they can only be destroyed.

@xtdiwd Just as a note, the 2D forum isn’t related to UI features although there are always super helpful devs here (as above). You can find discussions on UI issues here.

@Lo-renzo
I tried the 3 scripts and none of them worked: sometimes some objects are correctly positioned and others are not, other times all the objects go in absurd positions.
I have a source RectTransform array and another target RectTransform array. “Source” lists elements from a canvas that I use only to store positions and anchors, “Destination” contains the objects from the active canvas in which I want to reposition the objects.

I abandoned the idea of math because the results were wrong every time.

I also tried
someComponent.gameobject.transform.localPosition = otherComponent.gameobject.transform.localPosition;
with the same results!

@MelvMay
Sorry, I didn’t find the right thread. Can you move the thread to the right section (and save the URL)?

No need to move it. I just wanted you to know about the UI forum for the future. :slight_smile:

You probably need to mind the parent transform. Likewise, you need to be careful that you have the same anchor settings. If you need more help, you should provide screenshots of what you’re trying to do because I don’t have a clear notion of what’s going on in your transform hierarchy.


Red and Blue are anchored at their corner.
The other objects are anchored at the center.
The CanvasScaler is reversed if vertically.

I want in CanvasWork, the only active in the game, to copy the placement and anchor of the elements from CanvasH or CanvasW as needed. In my problem point I have already found the RectTransforms of the source and target objects in separate arrays.

I detected a problem. While trying another way.
When I try to write values (copied by manual and anchored in a corner) via SetInsetAndSizeFromParentEdge, I notice that when I read them I get different values in localPosition, position, rect or anchoredPosition, which are still different in the editor. But not the written values.
Also, SetInsetAndSizeFromParentEdge does not allow you to anchor in middle or center!

Between the two images, it looks like your mirroring it, is that right? Button2 is on the right-left, then Button2 is on the top-right. You won’t be able to copy properties and if you’re changing the orientation like that. Lets say Button2 is anchored to the upper-right so its position relative to its anchor is (-x,-y). In contrast, if Button2 is anchored upper-left, its anchor position is (+x, -y) from the anchor. I don’t know how your anchors are set, though, I’m just guessing what you’re trying to accomplish, which looks like rearranging your UI for different screen orientations.

Yes, my idea is to have one arrangement when the device is in portrait and another for when it is in landscape.
The 2 Buttons are anchored to middle-center in the Panel, the anchor doesn’t change. It’s the anchor of the Red and Blue circles that changes.
Are you telling me I want to do something impossible?

You’re probably going to find it difficult that way because let’s say it’s middle center and you want to button Button2 in the top-right… that may be (+400,+300) or something while in Portrait, but in Landscape the top-left position might be (-600, +200). These are totally made up numbers (IDK your resolutions) just to illustrate the point: middle-center is unlikely to give you even positioning for what you want. In many cases, it’s easiest to pick a corner for a button and use anchor settings so that as resolution changes it stays in that corner.

Assuming your UI isn’t doing anything too fancy, I’d re-approach it by having a component called ReorientationSettings has two Modes - Landscape and Portrait - which knows the Anchor and Position for both orientations. While testing in the editor, I’d have an editor script to crawl the canvas hierarchy and flip on the Mode for all things with this component, and set up a shortcut for it so I could quickly toggle between the two while tweaking it. You could even set up an Inspector script the component with two buttons: “Copy to Landscape” and “Copy to Portrait” to set and serialize its settings from however you’ve adjusted it on the Inspector’s RectTransform component.

This would mean one Canvas, not two, and no duplicate buttons. This lowers the number of objects you have. The maintenance burden is setting up ReorientationSettings for everything, but you may find you need orientation-specific positions anyway.

That way, Button2 can be set to be relative to top-left corner in Landscape, and top-right corner in Portrait, which allows you to use anchored position to their fullest extent and at their most intuitive.

I’m not sure I understand: I have to create a ReorientationSettings script?

Yes. If you have both a Portrait and Landscape mode and you’re flipping a button from the left-hand side of the screen to the right-hand side, then it’s probably your best bet.

If that sounds like too much work, then maybe you can get away with keeping Button2 in the top-right corner in both orienations? That would be easy to accomplish when using the correct up-right anchor setting.

It’s really the flipping of Button2 that makes me suggest you may need a special component, ReorientationSettings, to store the different settings in different screen orientations.

My problem is that I have no idea about how to write via code the values so that they match those read in the editor.
If I write the same values that I see in the editor, the objects go in different positions.

If you take Button2 and assign a top-left anchor then give it position (+50, -50) it should be in the top-left corner, a bit in from the edge.
If you take Button2 and assign a top-right anchor then give it position (-50, -50) it should be int he top-right corner, a bit in from the edge.

This will be true if assigned from within the Inspector or by Code. If that is not true, there has to be some other explanation. This could possibly be because the parent transforms (or grandparent, great-grandparent etc) are
(a) not exactly mirrored - position/rotation/scale is different, or
(b) the rect sizes are not the same.

Try to reproduce this simple test case to ensure that it works.