RectTransform's Y anchored position is sometimes incorrectly set to 0 on scene load

Affects Unity version 2022.3.4f1

There seems to be a race condition somewhere in the deserialization code; so far we have only noticed it on UI objects, specifically the RectTransform.

A very simple empty scene with an anchored UI object is enough to trigger it. In the built version of the project (using all default settings) the Y coordinate of the RectTransform’s anchored position is often (but not always) incorrectly set to 0 when loading the scene.

However, having another application open in the background (for example, the Unity Editor or even something unrelated like VirtualBox) can somehow prevent the issue from happening.

Sometimes even saving the project and reopening it in the Unity Editor results in the Y coordinate being incorrectly set to 0 upon loading the scene.

When building a 32-bit version of the application, the bug affects the X coordinate instead of Y.

To reproduce:

  1. Create a new URP project (e.g. URP 3D Template)

  2. In the default scene, add UI > Canvas with the default settings. Setting the Canvas Scaler component to “Scale With Screen Size” seems to make the issue more likely to trigger, but it is not required.

  3. Add a child object (e.g. UI > Image) to the canvas

  4. Set the anchor of the image to top right

  5. Set the position to -100, -100

  6. Save the project and build using default settings

  7. (Important) Close the editor and make sure no other applications are running in the background

  8. Run the built application

  • OR -
  1. Reopen the project

The Y position of the image is sometimes reset to 0. Depending on the machine one or the other will trigger it.

Note that this seems to be non-deterministic and is often affected by what applications are running in the background, or even rebooting the machine can suddenly trigger it when it didn’t happen before.

We have managed to reproduce it on several machines so it is unlikely to be a hardware issue.

An example repro project is attached.

9187379–1280246–GUITest2.zip (205 KB)

I am able to reproduce the bug on my desktop as described in the OP.

Setting Canvas Scaler to Scale With Screen Size is not necessary, the bug is still there with Constant Pixel Size scaling.

On my laptop the effect is even worse: the entire GUI/Canvas is not visible in a 64-bit Windows build of the project (either by wrong positioning/scaling or not loaded properly, I could not figure out). I can consistently reproduce the effect if I run the build with VirtualBox running something big like Ubuntu Server in the background. Once I turn off VirtualBox and restart the game build, everything works normally.

Laptop specs (entire Canvas disappears): AMD Ryzen 5 4500U, 8GB RAM, Radeon Graphics iGPU
Desktop specs (anchoredPosition.y gets zeroed): AMD Ryzen 5 7600, 32 GB RAM, Radeon RX 6650 XT GPU

I can’t test it on an Intel CPU. Maybe it’s an AMD-related issue?


I think I figured a temporary workaround using a delayed SetActive on the canvas:

  1. Deactivate (uncheck) the entire Canvas object in the scene.

  2. Add the following script to a different game object, that is active from the start.

using UnityEngine;

public class DelayGameObject : MonoBehaviour {
    public GameObject Target;
    public float Delay = 0.2f;

    void Update() {
        if (!Target.activeSelf) {
            if (Delay > 0)
                Delay -= Time.deltaTime;
            else
                Target.SetActive(true);
        }
    }
}
  1. In the editor, assign Canvas to the Target field.

Note that the delay of 0 (i.e., activating on the first update) doesn’t seem to be enough, just reduces the chance of the bug. Delay = 0.1 works on all my machines every time.

It happened today on my computer as well. Whenever I open a project the UI elements are repositioned to 0 in Y-Axis.
Don’t know what is causing it…

I have an i5-12450H and NVIDIA GTX 1650…

I showed the bug to my colleague and he just reloaded the scene and all of the elements went back to their saved positions, he suggested that the editor is not loading the position of Y on loading the project so just reloading the scene without changing anything makes the objects return to their saved positions.

I also have the same bug. in inspector, all y values of ui objects seem to be 0. But when I move an object, git shows that its original value is not actually 0. Seems like a scene loading bug.

We have the same issue in builds showing up randomly.

One trick that gets us 100% reproducibility is building a development build.

I guess this is also a similar thing that caused our UI not load properly when we use shrink/expand Canvas scalers.

Both issues (wrong y pos and UI being positions at float maxvalues) shows up only when using overlay canvas.
Using screen space canvas does not have these issues.

Repro on 2022.3.4f1.
Cant repro on 2022.3.7f1!!

Fix confirmed by Unity in 2022.3.5f1.

Bug report: IN-52633 - UI Y position set to 0 in build

Thanks, I have been trying to solve this problem whole day and finally found this report.

Unity 2022.3.4f1 has still this issue. UI getting repositioned to 0 in Y-Axis.

I’ve encountered this bug in 6000.024f1

Found it also on 6000.2.6f2 (took a long time to find this thread, i thought i was going mad).

I was running into this with a TextMeshPro element, on one of them in a complex piece of UI the Y position would get set to 0 on instantiation, ruining the layout. I noticed that disabling the UI and re-enabling it fixed it, which led to to an annoying solution.

If you render the canvas for 2 frames (not 1 frame – it has to be 2+) and then disable and reenable it it fixes its layout. This is pretty jarring for the user as 2 frames is enough time to really notice the layout jerk around. To get around that you can add a canvas group to the canvas and set the alpha to 0 for 2 frames and then set it back and it’ll be in the right layout. Fucking annoying that we have to do this, I’ve wasted hours.

Some pseudocode for anyone it might help. If this is UI that doesn’t need to be visible right away (like a popup) then you can remove the canvas.gameObject.SetActive(true); in the Update. Basically prep the UI while invisible to get the layout bugs out and then hide it for when it’s needed.

public class MyUI : MonoBehavior {
  [SerializeField] private Canvas canvas;
  [SerializeField] private CanvasGroup canvasGroup;

  private int hideFrameCount = -1;
  private bool hasHidden = false;

  private void Start()
  {
    canvasGroup.alpha = 0;
    hideFrameCount = 2;
  }
 
  private void Update()
  {
    if (hideFrameCount == 0 && !hasHidden)
    {
      canvasGroup.alpha = 1f;
      canvas.gameObject.SetActive(false);
      canvas.gameObject.SetActive(true);
      hasHidden = true;
    }
    
    if(hideFrameCount > 0)
    {
      hideFrameCount--;
    }
  }
}