Search Unity

Official UI Toolkit migration guide

Discussion in 'UI Toolkit' started by benoitd_unity, Jul 9, 2021.

  1. antoine-unity

    antoine-unity

    Unity Technologies

    Joined:
    Sep 10, 2015
    Posts:
    780
    Yes, this is the guide that @uMathieu was talking about.
     
  2. JuliaP_Unity

    JuliaP_Unity

    Unity Technologies

    Joined:
    Mar 26, 2020
    Posts:
    700
  3. joseGuate97

    joseGuate97

    Joined:
    Mar 1, 2018
    Posts:
    57
    JuliaP_Unity likes this.
  4. shiki_2022

    shiki_2022

    Joined:
    Aug 21, 2020
    Posts:
    11
    This solve my problem.Unity2020.3.22f1,UI Tookit 1.0.0-preview.18
     
  5. Magnilum

    Magnilum

    Joined:
    Jul 1, 2019
    Posts:
    241
    Hi @benoitd_unity and the Unity team,

    There is a issue between the Unity 2021 and the 2022 especially in the UI Builder since some VisualElements like Vector3Field, FloatField, IntegerField and some other has been moved from UnityEditor to UnityEngine namespace.

    How can we ensure the good functioning of our UI Document between those two versions?

    Thank you in advance
     
  6. antoine-unity

    antoine-unity

    Unity Technologies

    Joined:
    Sep 10, 2015
    Posts:
    780
    In C#, you will need to make a conditional import of the type depending on the Unity Version. For example:

    Code (csharp):
    1.  
    2. #if UNITY_2022_OR_NEWER
    3. using FloatField=UnityEngine.UIElements.FloatField
    4. #else
    5. using FloatField=UnityEditor.UIElements.FloatField
    6. #endif
    7.  
    See this page for more information: https://docs.unity3d.com/Manual/PlatformDependentCompilation.html

    For UXML files, you should be able to leave your UXML to use the UnityEditor namespace, they will import correctly in 2022.
    If you use the UI Builder in 2022, you may need to manually change the namespace back to the UnityEditor as the UI Builder does not try to maintain backwards compatible UXML namespaces.
     
  7. Magnilum

    Magnilum

    Joined:
    Jul 1, 2019
    Posts:
    241
    Thank you a lot for your answer!

    In C#, it is not the problem, since I import both libraries:

    Code (CSharp):
    1. using UnityEngine;
    2. using UnityEngine.UIElements;
    3. using UnityEditor;
    4. using UnityEditor.UIElements;
    And the script manages itself to use the correct one.

    In the UXML, since I am using the last version of Unity to develop my tool (Unity 2022), it means that I have to develop on the 2021 to not have this issue anymore?

    There are no other solutions?
     
  8. antoine-unity

    antoine-unity

    Unity Technologies

    Joined:
    Sep 10, 2015
    Posts:
    780
    There is no solution provided out of the box by Unity. One thing you could do is to automate the task of making the UXML files compatible with Unity 2021. Since UXML files are just XML, you can load them with the standard C# library, traverse the nodes and load the C# type from the fully qualified name. If it doesn't exist in UnityEngine, you can try it in UnityEditor and save back the UXML with modified namespaces.
     
  9. Magnilum

    Magnilum

    Joined:
    Jul 1, 2019
    Posts:
    241
    So making the UXML in Unity 2021 and load it in Unity 2022 won't work too?

     
  10. antoine-unity

    antoine-unity

    Unity Technologies

    Joined:
    Sep 10, 2015
    Posts:
    780
    No this will work, I was answering the question "There are no other solutions?".
     
    Magnilum likes this.
  11. Magnilum

    Magnilum

    Joined:
    Jul 1, 2019
    Posts:
    241
    Do you think that it can work for 2020 and 2019?
     
  12. antoine-unity

    antoine-unity

    Unity Technologies

    Joined:
    Sep 10, 2015
    Posts:
    780
    Yes, I think Unity 2022 is the first time we moved types into different namespaces, so this should work.
    That being said you'll need to make sure your UI generally works on those versions, there were several behaviours changed along the way, not to mention new features introduced.

    I think it is possible to maintain UI working across these versions, but challenging. Make sure to have good test procedures, automated if possible.
     
  13. Magnilum

    Magnilum

    Joined:
    Jul 1, 2019
    Posts:
    241
    Thank you for your answer:

    So I am going to move the tool from 2022 to 2021 to make UXML compatible between all the version.
     
  14. andrianovyaroslav27

    andrianovyaroslav27

    Joined:
    Sep 19, 2021
    Posts:
    8
    For all the people who have no idea how XML works (that's me) and how to do all that stuff, proposed by Unity staff, all you need to do is change every occurrence of ui:FloatField to uie:FloatField in the UXML document. As simple as that.
     
  15. Magnilum

    Magnilum

    Joined:
    Jul 1, 2019
    Posts:
    241
    That is what I did and it works.

    We have 2 options:
    - making all the UI document in 2021 and they will be compatible with the 2022 version but it means going back in Unity's version and miss some updates
    - doing everything in 2022 and make a script which reads all the UI Documents and apply the correction by changing the namespace of the docs

    I chose the second option since I did not want to develop on the 2021 version of Unity.

    Here is the script which is named CustomMenu.cs and which is placed in an "Editor" folder.

    Code (CSharp):
    1. [MenuItem("Assets/Commands/PrefabTools/Update UXML to 2021", priority = 2)]
    2.         public static void UpdateAllUXMLto2021()
    3.         {
    4.             string folderPath = Application.dataPath + "/"; // this path points at the Assets folder, this means that all the UI Documents will be changed, feel free to change this variable to select only one folder
    5.             Recursive(folderPath); // it looks in all the child folders and check if a UI Document is present and modifies it
    6.             Debug.Log("<color=green>All the UI documents from the Prefab Tools package have been uptated with success.</color>");
    7.         }
    8.  
    9.         static void Recursive(string path)
    10.         {
    11.             string[] folders = AssetDatabase.GetSubFolders(path);
    12.             foreach (var folder in folders)
    13.             {
    14.                 DirectoryInfo dir = new DirectoryInfo(folder);
    15.                 FileInfo[] info = dir.GetFiles("*.uxml");
    16.                 foreach (FileInfo f in info)
    17.                     UpdateUXML(f);
    18.                 Recursive(folder);
    19.             }
    20.         }
    21.  
    22.         static void UpdateUXML(FileInfo file)
    23.         {
    24.             string[] triggers = new string[] {
    25.                 "ui:EnumField",
    26.                 "ui:IntegerField",
    27.                 "ui:FloatField",
    28.                 "ui:LongField",
    29.                 "ui:DoubleField",
    30.                 "ui:Hash128Field",
    31.                 "ui:Vector2Field",
    32.                 "ui:Vector3Field",
    33.                 "ui:Vector4Field",
    34.                 "ui:RectField",
    35.                 "ui:BoundsField",
    36.                 "ui:Vector2IntField",
    37.                 "ui:Vector3IntField",
    38.                 "ui:RectIntField",
    39.                 "ui:BoundsIntField"
    40.             };
    41.  
    42.             string[] warnings = new string[] {
    43.                 "UnsignedIntegerField",
    44.                 "UnsignedLongField"
    45.             };
    46.  
    47.             string[] lines = File.ReadAllLines(file.FullName);
    48.             string line;
    49.             for (int i = 0; i < lines.Length; i++)
    50.             {
    51.                 line = lines[i];
    52.                 foreach (var warning in warnings)
    53.                     if (line.Contains(warning))
    54.                         Debug.LogWarning($"(line {i+1}) {file.Name} contains {warning}, not supported in Unity2021.");
    55.  
    56.                 foreach (var trigger in triggers)
    57.                     if (line.Contains(trigger))
    58.                     {
    59.                         lines[i] = line.Replace("ui", "uie");
    60.                         break;
    61.                     }
    62.             }
    63.  
    64.             string saveFolderRelativePath = Application.dataPath + "/Save UI";
    65.             string saveFolderAbsolutePath = Application.dataPath + saveFolderRelativePath.Substring("Assets".Length);
    66.  
    67.             // Before changing the UI Document, they are saved in the "Save UI" folder, be sure to create it as a child of the "Assets" folder
    68.             File.Copy(file.FullName, $"{saveFolderAbsolutePath}/save_{file.Name}", true);
    69.             File.WriteAllLines(file.FullName, lines);
    70.         }