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

Feature Request Minor version OR_NEWER compilation

Discussion in 'Scripting' started by DevDunk, Jun 6, 2023.

  1. DevDunk

    DevDunk

    Joined:
    Feb 13, 2020
    Posts:
    4,362
    I am working on an asset and want to use SetLocalPositionAndRotation, which was added in 2021.3.11.
    There currently is no way to do this.
    You can use #if UNITY_2021_3_OR_NEWER, but not #if UNITY_2021_3_11_OR_NEWER
    #if UNITY_2021_3_11 does work, but only if that's the exact Unity version

    This makes support for unity assets that want to use the more performant method hell, unless you lock out a big part of the user base who does update unity to the latest 2021 lts
     
  2. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,563
    You can "not" the thing too, yanno... :)

    Code (csharp):
    1. #if !UNITY_2021_3_OR_NEWER
    Or you can
    #else
    it

    EDIT: reading closer... I think perhaps you mean deciding based on the minor version number??? I think maybe you can still get it with a compound statement, checking the major, then the minor ...
     
  3. DevDunk

    DevDunk

    Joined:
    Feb 13, 2020
    Posts:
    4,362
    That would mean I have to check if the version is 2021.3 or newer, and then manually exclude 10 other unity versions (2021.3.0 - 2021.3.10). Possible, but far from ideal.
    Assets like XR Management can use 4.3.1 or newer, so don't understand why Unity releases cannot
     
  4. orionsyndrome

    orionsyndrome

    Joined:
    May 4, 2014
    Posts:
    3,043
    According to these docs, Unity exposes punctual UNITY_X, UNITY_X_Y and UNITY_X_Y_Z along with the ongoing UNITY_X_Y_OR_NEWER

    This means you can pack your conditional as a #define and test against that
    Code (csharp):
    1. #if UNITY_X_Y_OR_NEWER && !(UNITY_X_Y_Z || UNITY_X_Y_Z || ....)
    2. #define VERSION_PASS
    3. #endif
    where each subsequent UNITY_X_Y_Z check uses Z from the same X_Y that are below 11

    then
    Code (csharp):
    1. #if VERSION_PASS
    It's not ideal, but it's better than nothing!
     
    Last edited: Jun 6, 2023
  5. orionsyndrome

    orionsyndrome

    Joined:
    May 4, 2014
    Posts:
    3,043
    Wow took me quite a while to confirm that this is actually legal.
    Yes, confirmed, you can sandwich a
    #define
    inside the conditional block, and it works as expected.

    Granted, it's pretty dumb that OR_NEWER symbols are not in the major.minor.patch format.
    Now you really have to name everything before 11, otherwise the next patch would invalidate a scheme that relied on any kind of negation.

    So here's a generator for dotnetfiddle.net
    Code (csharp):
    1. using System;
    2. using System.Text;
    3. using System.Collections.Generic;
    4.                
    5. public class Program {
    6.  
    7.     public static void Main() {
    8.    
    9.         var sb = new StringBuilder();
    10.         var bas = "UNITY_2021_3";
    11.         sb.Append($"{bas}_OR_NEWER");
    12.         sb.Append(" && !(");
    13.         for(int i = 0; i < 11; i++) {
    14.             if(i > 0) sb.Append(" || ");
    15.             sb.Append($"{bas}_{i}");
    16.         }
    17.         sb.Append(")");
    18.         Console.WriteLine(sb.ToString());
    19.    
    20.     }
    21.  
    22. }
    Edit:
    Obviously it should be
    ||
    inside the parens, fixed
     
    Last edited: Jun 6, 2023
    Kurt-Dekker likes this.
  6. DevDunk

    DevDunk

    Joined:
    Feb 13, 2020
    Posts:
    4,362
    Thanks! Did not use a manual define outside of project settings before. (thinking of this, maybe an editor tool would work as well to set the defines).

    #define only works on the script it is in, right? So all scripts would need it placed?
     
  7. orionsyndrome

    orionsyndrome

    Joined:
    May 4, 2014
    Posts:
    3,043
    That's a good question. Well, shoot.
    Followed by this
    Here

    This is interesting because you can make MY_PACKAGE_UNITY_VERSION_OK as a compile-wide symbol and then conditionally #undef that in one of the files.

    But to tweak DefineConstants you have to edit the 'scripting define symbols' somewhere in the Player settings, or edit the project files. So I'm not really sure how you're supposed to conveniently deliver this information via .unitypackage.
     
    Last edited: Jun 6, 2023
  8. orionsyndrome

    orionsyndrome

    Joined:
    May 4, 2014
    Posts:
    3,043
    You know what? You can define that critical code in one place, that is actually conditionally compiled, and then proceed to call this instead of whatever you were calling prior to that. Turn it into a static library.

    If it's not a top-secret maybe you can show that piece of code that got fixed/improved in 2021_3_11 so I can think of a way to isolate it.
     
  9. orionsyndrome

    orionsyndrome

    Joined:
    May 4, 2014
    Posts:
    3,043
    Or you know, you can even be more creative shrewd than that
    Code (csharp):
    1. #if UNITY_X_Y_OR_NEWER && !(UNITY_X_Y_Z || UNITY_X_Y_Z || ....)
    2. #define VERSION_PASS
    3. #endif
    4.  
    5. static public class VersionCompatibility {
    6.  
    7.   static public bool Check() {
    8. #if VERSION_PASS
    9.     return true;
    10. #else
    11.     return false;
    12. #endif
    13.   }
    14.  
    15. }
    This moves it to runtime check, so this wouldn't work if this was an API change, but still let's you maneuver for runtime decisions.
     
    DevDunk likes this.
  10. DevDunk

    DevDunk

    Joined:
    Feb 13, 2020
    Posts:
    4,362
    I might make a static compatibility checker for my personal assets! Great idea. This way I can also remove 2022.1 and 2022.2 etc from the list. Massive statement but that's okay haha.

    I came across this with a PR for WebXR exporter, where I wanted to integrate SetLocalPositionAndRotation to improve performance.
     
    orionsyndrome likes this.
  11. orionsyndrome

    orionsyndrome

    Joined:
    May 4, 2014
    Posts:
    3,043
    Considering that you've received a personal 'thank you' now you have no other choice haha

    In that case you can then do this
    Code (csharp):
    1. #if UNITY_X_Y_OR_NEWER && !(UNITY_X_Y_Z || UNITY_X_Y_Z || ....)
    2. #define VERSION_PASS
    3. #endif
    4.  
    5. using UnityEngine;
    6. using System.Runtime.CompilerServices;
    7.  
    8. static public class TransformExtensions {
    9.  
    10.   [MethodImpl(MethodImplOptions.AggressiveInlining)]
    11.   static public void SetLocalPositionAndRotation(this Transform xf, Vector3 position, Quaternion rotation) {
    12. #if VERSION_PASS
    13.     xf.SetLocalPositionAndRotation(position, rotation);
    14. #else
    15.     xf.localPosition = position;
    16.     xf.localRotation = rotation;
    17. #endif
    18.   }
    19.  
    20. }
    Now I'm not sure entirely because of name collision, maybe you can circumvent that with
    new
    tucked in there, I forgot how exactly extensions work, probably not considering their excruciatingly conservative design.

    Anyways, just an idea, try some variation of that.
     
    DevDunk likes this.
  12. orionsyndrome

    orionsyndrome

    Joined:
    May 4, 2014
    Posts:
    3,043
    Nah, I figured out the best way to do this actually, plain ol' reverse compatibility.
    Code (csharp):
    1. #if !(UNITY_2021_3_OR_NEWER && !(UNITY_2021_3_0 && UNITY_2021_3_1 && UNITY_2021_3_2 && UNITY_2021_3_3 && UNITY_2021_3_4 && UNITY_2021_3_5 && UNITY_2021_3_6 && UNITY_2021_3_7 && UNITY_2021_3_8 && UNITY_2021_3_9 && UNITY_2021_3_10))
    2. using UnityEngine;
    3. using System.Runtime.CompilerServices;
    4.  
    5. static public class TransformExtensions_Pre_2021_3_11 {
    6.  
    7.   [MethodImpl(MethodImplOptions.AggressiveInlining)]
    8.   static public void SetLocalPositionAndRotation(this Transform xf, Vector3 position, Quaternion rotation) {
    9.     xf.localPosition = position;
    10.     xf.localRotation = rotation;
    11.   }
    12.  
    13. }
    14. #endif
    Your actual production code just plows with SetLocalPositionAndRotation, minds its own business, no care in the world.
     
    Last edited: Jun 6, 2023
  13. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,563
    Aaah... having to doubt that really makes you wish for... (quote from another post)

    "Geeve me baaack my #define maaaacrooooos!!!"
     
    orionsyndrome likes this.
  14. orionsyndrome

    orionsyndrome

    Joined:
    May 4, 2014
    Posts:
    3,043
    @Kurt-Dekker haha, while checking this out I came across the following Note
    That's actually the most official explanation I've ever seen. But there you go, the word "notorious" ;)
     
    Kurt-Dekker likes this.
  15. Spy-Master

    Spy-Master

    Joined:
    Aug 4, 2022
    Posts:
    274
  16. DevDunk

    DevDunk

    Joined:
    Feb 13, 2020
    Posts:
    4,362
  17. Spy-Master

    Spy-Master

    Joined:
    Aug 4, 2022
    Posts:
    274
    You can always use the existing UNITY_2022_2 etc. for that.
     
    Yuchen_Chang likes this.