Search Unity

  1. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Unity 2021.2: Dedicated Server target and stripping optimizations now live! Please share feedback!

Discussion in 'Multiplayer' started by UnityGio, Jul 20, 2021.

Thread Status:
Not open for further replies.
  1. unity_5B43D1FCB57EFE0F47FF

    unity_5B43D1FCB57EFE0F47FF

    Joined:
    Jan 4, 2022
    Posts:
    3
    We are writing this to get more detail on Unity’s Dedicated Server Build target.


    We have used a dedicated server build target with linux platform for one of the multiplayer game. It’s contains the server specific logic without any assets. We have deployed the generated server build on AWS server in linux machine. We are launching the server build from an external app in the same machine with -batch mode.


    But, each game instance is taking around 12% of memory of the AWS t3-large instance after launching. Here our concern is with the memory it’s takes.

    1. Is it normal or we are missing something here?
    2. We need to run multiple server build instances in parallel in the AWS, As many as possible. With decent Amazon EC2 instance like AWS t3-large we could go upto 8 Instances.(i.e. only 8 games can be played at a Time)

    Kindly give your inputs on how to run max number of instances in parallel in the AWS.
     
  2. VRGroupRWTH

    VRGroupRWTH

    Joined:
    Oct 23, 2021
    Posts:
    10
    Hello,

    We're having an issue using Unity's WebRTC Plugin alongside a Dedicated Server build. The application just segfaults, and I assume this is due to some symbols being stripped for the native plugin interface? We reported the issue here: https://github.com/Unity-Technologies/com.unity.webrtc/issues/791, but maybe you have suggestions how we can circumvent this?
     
  3. yuriy000

    yuriy000

    Joined:
    Oct 14, 2021
    Posts:
    7
    Is there any way for us to exclude certain assembly definitions from a dedicated server target? There is included/excluded "platforms" but no such option for "standalone build subtargets".

    We have lots of assemblies which implement rendering-related functionality, which we want to keep out of the server build. It is not only wasting resources but some of the assemblies will simply fail/segfault on the dedicated server build.

    We can use the 'Linux' platforms but this seems to also impact Linux desktop client builds?
     
  4. simon-lemay-unity

    simon-lemay-unity

    Unity Technologies

    Joined:
    Jul 19, 2021
    Posts:
    416
    I think you should be able to use a define constraint on
    UNITY_SERVER
    .
     
    yuriy000 likes this.
  5. sachaamm

    sachaamm

    Joined:
    Apr 11, 2016
    Posts:
    30
    Unity ( 2021.3.11f1 ) makes long building time and recompiles shaders while switching platform ( back and forth from Standalone Windows to Linux Dedicated Server ), around 30 minutes per Build because the editor is compiling all variants shaders from the project, which contains graphical assets dependencies. Usually editor caches shaders for the same building platform but because i switch between these 2 differents building platform shader cache is erased, causing very long deployment time.
    this is pretty annoying because:
    - I don't understand why Dedicated Server needs to compile shaders, dedicated server is basically a console application
    - I don't understand how to simply remove all shaders from build. I ordered Shader Control from the Asset Store, but again it seems to work only with Windows Standalone, it's working to exclude shaders, but when Im reincluding shaders for Standalone Build all shaders are recompiled, so I can't switch easily between Platforms
    - This is time consuming for me while iterating between platform for Build Deployment to the Cloud
    Why there are only one Shader Cache in Library folder ? Have you thought about Caching Shader per Platform ?
    It's not a problem to wait 30 minutes to get all your project shaders built (the shader compiling variants is already too long), but when this proccess is repeated each time you change platform settings, the editor is just not suitable for any more consequent project involving many graphics assets.
    I finally duplicated my project folder to ServerDedicated Platform, to avoid these trouble while switching platforms
     
    Last edited: Mar 21, 2023
  6. cristianm_unity

    cristianm_unity

    Unity Technologies

    Joined:
    Oct 16, 2018
    Posts:
    248
    Hi @sachaamm !

    You are right, Dedicated Server does not need shaders. As we have mentioned before, we are working in improving this but for now I recommend you use the Shader Variant Stripping feature:

    Code (CSharp):
    1. class ShadersStripping : IPreprocessShaders
    2. {
    3.     public int callbackOrder => 0;
    4.  
    5.     public void OnProcessShader(Shader shader, ShaderSnippetData snippet, IList<ShaderCompilerData> data)
    6.     {
    7.     #if !UNITY_SERVER
    8.         return;
    9.     #endif
    10.         data.Clear();
    11.     }
    12. }
    I've personally tested it and it reduces considerably the build time for Dedicated Server.

    Improving iteration time is something we are definitely interested in, so I would love to understand better this case so we can reproduce it and investigate it in detail. I would appreciate if you could provide some extra details about how we can reproduce your scenario: how many shaders do you have in your project? what specific steps can we perform to see this? (e.g. does this happen when you build the project or is it enough to just switch targets?) Is asynchronous shaders compilation active in your project?

    Cheers!
     
    andreyshade likes this.
  7. sachaamm

    sachaamm

    Joined:
    Apr 11, 2016
    Posts:
    30
    Hi @cristianm_unity , thanks for the quick reply, good to know. Unfortunately, the script you provided didn't improved building time, the shader stripping is effective but when building process is done, the editor is collecting all the shaders variants in the project and it still takes a while, i'm a bit exhausted, working 16hours trying to finish my project but i think the multiplayer feature won't be able to release in these conditions...
    upload_2023-3-22_0-28-54.png
    Smoke Lightmap lit shader is containing 159 millions of variants. I'm using Vegetation Studio Pro, Nature Manufacture Assets Smoke & Fire, NatureManufacture Meadow, KriptoFX Water, and other assets...
     
  8. cristianm_unity

    cristianm_unity

    Unity Technologies

    Joined:
    Oct 16, 2018
    Posts:
    248
    Thanks for trying it.

    So if I understand correctly, the problem is that when switching targets (after the build), the editor is recompiling all shaders, which takes a lot of time, is that correct?

    If so, could you please confirm if the Asynchronous Shader Compilation is active? It is supposed to improve workflow in those cases.
     
  9. sachaamm

    sachaamm

    Joined:
    Apr 11, 2016
    Posts:
    30
    Yes Asynchronous Shader Compilation is Enabled

    When I try to compile the shader NM_ParticleSmokeLightMapLit ( Nature Manufacture Smoke & Light Asset )
    I've got this
    upload_2023-3-22_7-41-28.png
    Based on time elapsed, compiling this shader of my project will takes ages, even with RTX 3090. I have to notice also that i was using Addressable, and i was serving Addressable Scenes which were containing game objects with this shader. I don't know if there is a related, if there is a bug related which is creating so many shaders variants. I don't know what a shader variants normal count is. but 19 millions seems to be pretty insane. Currently I removed Addressable to see if it can gets an impact to reduce building time but it doesn't. Perhaps my Library folder is corrupted
     

    Attached Files:

    Last edited: Mar 22, 2023
  10. sachaamm

    sachaamm

    Joined:
    Apr 11, 2016
    Posts:
    30
    Yes. So i duplicated my project in two, one for building Standalone and other to build Dedicated Server to avoid this issue
     
  11. uthon

    uthon

    Joined:
    Nov 23, 2015
    Posts:
    14
    Below is my game build script. Most is irrelevant to you but there are a couple of menu items for switching the build target (look for SetYYYTarget() APIs).

    It doesn't go through the rebuild process that occurs from the Unity Build window, it's pretty instant for me.

    Code (CSharp):
    1. ///////////////////////////////////////////////////////////////////////////
    2. /// Build menu.
    3. ///
    4. /// Creates a "Horseshoe" menu in Unity with options to build the game,
    5. /// switch build targets without building, and automatically manage the
    6. /// build number according to SemVer standards (see <https://semver.org/>).
    7. ///
    8. ///////////////////////////////////////////////////////////////////////////
    9. #if UNITY_EDITOR
    10. using System;
    11. using UnityEditor;
    12. using UnityEditor.Build.Reporting;
    13. using UnityEngine;
    14.  
    15. public class BuildMenu
    16. {
    17.     /// <summary>
    18.     /// Scenes to include in the build.
    19.     /// </summary>
    20.     public static string[] scenes = {
    21.         "Assets/Horseshoe/Game/Scenes/0_MAIN.unity",
    22.         "Assets/Horseshoe/Game/Scenes/1_GAME.unity"
    23.     };
    24.  
    25.     public static string ProductName = PlayerSettings.productName;
    26.  
    27.     ///////////////////////////////////////////////////////////////////////////
    28.     /// Debug build menu handlers.
    29.     ///////////////////////////////////////////////////////////////////////////
    30.  
    31.     /// <summary>
    32.     /// Build all targets.
    33.     /// </summary>
    34.     [MenuItem("Horseshoe/Build Dev Package")]
    35.     public static void BuildAll_DevPackage()
    36.     {
    37.         //BuildLinuxDedicatedServer(true);
    38.         BuildWindowsDedicatedServer(true);
    39.         //BuildAndroidClient(true);
    40.         BuildWindowsClient(true);
    41.  
    42.         //SetWindowsTarget();
    43.  
    44.         DoIncreaseBuild();
    45.     }
    46.  
    47.     /// <summary>
    48.     /// Build all targets.
    49.     /// </summary>
    50.     [MenuItem("Horseshoe/Build/All Targets")]
    51.     public static void BuildAll_All()
    52.     {
    53.         Debug.Log("Bulding all Development targets");
    54.         BuildAll(true);
    55.  
    56.         Debug.Log("Bulding all Release targets");
    57.         BuildAll(false);
    58.  
    59.         DoIncreaseBuild();
    60.     }
    61.  
    62.     /// <summary>
    63.     /// Build all targets.
    64.     /// </summary>
    65.     [MenuItem("Horseshoe/Build/Debug/All Targets")]
    66.     public static void BuildAll_Debug()
    67.     {
    68.         Debug.Log("Bulding all Development targets");
    69.         BuildAll(true);
    70.         DoIncreaseBuild();
    71.     }
    72.  
    73.     /// <summary>
    74.     /// Android Client target.
    75.     /// </summary>
    76.     [MenuItem("Horseshoe/Build/Debug/Android Client")]
    77.     public static void BuildAndroid_Debug()
    78.     {
    79.         BuildAndroidClient(true);
    80.         DoIncreaseBuild();
    81.     }
    82.  
    83.     /// <summary>
    84.     /// Windows Client target.
    85.     /// </summary>
    86.     [MenuItem("Horseshoe/Build/Debug/Windows Client")]
    87.     public static void BuildWindows_Debug()
    88.     {
    89.         BuildWindowsClient(true);
    90.         DoIncreaseBuild();
    91.     }
    92.  
    93.     /// <summary>
    94.     /// Linux Dedicated Server target.
    95.     /// </summary>
    96.     [MenuItem("Horseshoe/Build/Debug/Linux Dedicated Server")]
    97.     public static void BuildLinuxDedicatedServer_Debug()
    98.     {
    99.         BuildLinuxDedicatedServer(true);
    100.         DoIncreaseBuild();
    101.     }
    102.  
    103.     /// <summary>
    104.     /// Windows Dedicated Server target.
    105.     /// </summary>
    106.     [MenuItem("Horseshoe/Build/Debug/Windows Dedicated Server")]
    107.     public static void BuildWindowsDedicatedServer_Debug()
    108.     {
    109.         BuildWindowsDedicatedServer(true);
    110.         DoIncreaseBuild();
    111.     }
    112.  
    113.     ///////////////////////////////////////////////////////////////////////////
    114.     /// Release build menu handlers.
    115.     ///////////////////////////////////////////////////////////////////////////
    116.  
    117.     /// <summary>
    118.     /// Build all targets.
    119.     /// </summary>
    120.     [MenuItem("Horseshoe/Build/Release/All Targets")]
    121.     public static void BuildAll_Release()
    122.     {
    123.         Debug.Log("Bulding all targets");
    124.         BuildAll(false);
    125.         DoIncreaseBuild();
    126.     }
    127.  
    128.     /// <summary>
    129.     /// Android Client target.
    130.     /// </summary>
    131.     [MenuItem("Horseshoe/Build/Release/Android Client")]
    132.     public static void BuildAndroid_Release()
    133.     {
    134.         BuildAndroidClient(false);
    135.         DoIncreaseBuild();
    136.     }
    137.  
    138.     /// <summary>
    139.     /// Windows Client target.
    140.     /// </summary>
    141.     [MenuItem("Horseshoe/Build/Release/Windows Client")]
    142.     public static void BuildWindows_Release()
    143.     {
    144.         BuildWindowsClient(false);
    145.         DoIncreaseBuild();
    146.     }
    147.  
    148.     /// <summary>
    149.     /// Linux Dedicated Server target.
    150.     /// </summary>
    151.     [MenuItem("Horseshoe/Build/Release/Linux Dedicated Server")]
    152.     public static void BuildLinuxDedicatedServer_Release()
    153.     {
    154.         BuildLinuxDedicatedServer(false);
    155.         DoIncreaseBuild();
    156.     }
    157.  
    158.     /// <summary>
    159.     /// Windows Dedicated Server target.
    160.     /// </summary>
    161.     [MenuItem("Horseshoe/Build/Release/Windows Dedicated Server")]
    162.     public static void BuildWindowsDedicatedServer_Release()
    163.     {
    164.         BuildWindowsDedicatedServer(false);
    165.         DoIncreaseBuild();
    166.     }
    167.  
    168.     ///////////////////////////////////////////////////////////////////////////
    169.     /// Build scripts.
    170.     ///////////////////////////////////////////////////////////////////////////
    171.  
    172.     /// <summary>
    173.     /// Build all targets.
    174.     /// </summary>
    175.     public static void BuildAll(bool inDebug)
    176.     {
    177.         Debug.Log("Bulding Android client");
    178.         BuildAndroidClient(inDebug);
    179.  
    180.         Debug.Log("Bulding Windows client");
    181.         BuildWindowsClient(inDebug);
    182.  
    183.         Debug.Log("Bulding Linux dedicated server");
    184.         BuildLinuxDedicatedServer(inDebug);
    185.  
    186.         Debug.Log("Bulding Windows dedicated server");
    187.         BuildWindowsDedicatedServer(inDebug);
    188.     }
    189.  
    190.     /// <summary>
    191.     /// Build the Android client.
    192.     /// </summary>
    193.     /// <param name="inDebug">True to build a Development (Debug) build.</param>
    194.     public static void BuildAndroidClient(bool inDebug)
    195.     {
    196.         BuildOptions opts = BuildOptions.None;
    197.         string loc;
    198.  
    199.         SetAndroidTarget();
    200.  
    201.         if (inDebug)
    202.         {
    203.             Debug.Log($"Building Android client, Debug");
    204.             opts = BuildOptions.Development;
    205.             loc = $"Build/autobuild/Debug/Android/{ProductName}.aab";
    206.         }
    207.         else
    208.         {
    209.             Debug.Log($"Building Android client, Release");
    210.             loc = $"Build/autobuild/Release/Android/{ProductName}.aab";
    211.         }
    212.  
    213.         /* We absolutely do not want to ever store secrets in code (or even add them to
    214.            version control), so instead we'll fetch them from the system environment.
    215.            Don't forget to set these environment variables before invoking the build script! */
    216.         Debug.Log("Reading environment KEY_STORE_PASS");
    217.         PlayerSettings.Android.keystorePass = Environment.GetEnvironmentVariable("KEY_STORE_PASS");
    218.         Debug.Log("Reading environment KEY_ALIAS_PASS");
    219.         PlayerSettings.Android.keyaliasPass = Environment.GetEnvironmentVariable("KEY_ALIAS_PASS");
    220.  
    221.         var buildPlayerOptions = new BuildPlayerOptions()
    222.         {
    223.             scenes = scenes,
    224.             locationPathName = loc,
    225.             target = BuildTarget.Android,
    226.             subtarget = (int)StandaloneBuildSubtarget.Player,
    227.             options = opts
    228.         };
    229.  
    230.         BuildReport report = BuildPipeline.BuildPlayer(buildPlayerOptions);
    231.         PostBuild(report);
    232.     }
    233.  
    234.     /// <summary>
    235.     /// Build the Windows client.
    236.     /// </summary>
    237.     /// <param name="inDebug">True to build a Development (Debug) build.</param>
    238.     public static void BuildWindowsClient(bool inDebug)
    239.     {
    240.         BuildOptions opts = BuildOptions.None;
    241.         string loc;
    242.  
    243.         SetWindowsTarget();
    244.  
    245.         if (inDebug)
    246.         {
    247.             Debug.Log($"Building Windows Client, Debug");
    248.             opts = BuildOptions.Development;
    249.             loc = $"Build/autobuild/Debug/Windows/{ProductName}.exe";
    250.         }
    251.         else
    252.         {
    253.             Debug.Log($"Building Windows Client, Release");
    254.             loc = $"Build/autobuild/Release/Windows/{ProductName}.exe";
    255.         }
    256.  
    257.         var buildPlayerOptions = new BuildPlayerOptions()
    258.         {
    259.             scenes = scenes,
    260.             locationPathName = loc,
    261.             target = BuildTarget.StandaloneWindows64,
    262.             subtarget = (int)StandaloneBuildSubtarget.Player,
    263.             options = opts
    264.         };
    265.  
    266.         BuildReport report = BuildPipeline.BuildPlayer(buildPlayerOptions);
    267.         PostBuild(report);
    268.     }
    269.  
    270.     /// <summary>
    271.     /// Build Linux dedicated server.
    272.     /// </summary>
    273.     /// <param name="inDebug">True to build a Development (Debug) build.</param>
    274.     public static void BuildLinuxDedicatedServer(bool inDebug)
    275.     {
    276.         BuildOptions opts = BuildOptions.None;
    277.         string loc;
    278.  
    279.         SetLinuxDSTarget();
    280.  
    281.         if (inDebug)
    282.         {
    283.             Debug.Log($"Building Linux dedicated server, Debug");
    284.             opts = BuildOptions.Development;
    285.             loc = $"Build/autobuild/Debug/linuxds/{ProductName}.x86_64";
    286.         }
    287.         else
    288.         {
    289.             Debug.Log($"Building Linux dedicated server, Release");
    290.             loc = $"Build/autobuild/Release/linuxds/{ProductName}.x86_64";
    291.         }
    292.  
    293.         var buildPlayerOptions = new BuildPlayerOptions()
    294.         {
    295.             scenes = scenes,
    296.             locationPathName = loc,
    297.             target = BuildTarget.StandaloneLinux64,
    298.             subtarget = (int)StandaloneBuildSubtarget.Server,
    299.             options = opts
    300.         };
    301.  
    302.         BuildReport report = BuildPipeline.BuildPlayer(buildPlayerOptions);
    303.         PostBuild(report);
    304.     }
    305.  
    306.     /// <summary>
    307.     /// Build Windows dedicated server.
    308.     /// </summary>
    309.     /// <param name="inDebug">True to build a Development (Debug) build.</param>
    310.     public static void BuildWindowsDedicatedServer(bool inDebug)
    311.     {
    312.         BuildOptions opts = BuildOptions.None;
    313.         string loc;
    314.  
    315.         SetLinuxDSTarget();
    316.  
    317.         if (inDebug)
    318.         {
    319.             Debug.Log($"Building Windows dedicated server, Debug");
    320.             opts = BuildOptions.Development;
    321.             loc = $"Build/autobuild/Debug/WindowsDS/{ProductName}.exe";
    322.         }
    323.         else
    324.         {
    325.             Debug.Log($"Building Windows dedicated server, Release");
    326.             loc = $"Build/autobuild/Release/WindowsDS/{ProductName}.exe";
    327.         }
    328.  
    329.         var buildPlayerOptions = new BuildPlayerOptions()
    330.         {
    331.             scenes = scenes,
    332.             locationPathName = loc,
    333.             target = BuildTarget.StandaloneWindows,
    334.             subtarget = (int)StandaloneBuildSubtarget.Server,
    335.             options = opts
    336.         };
    337.  
    338.         BuildReport report = BuildPipeline.BuildPlayer(buildPlayerOptions);
    339.         PostBuild(report);
    340.     }
    341.  
    342.     ///////////////////////////////////////////////////////////////////////////
    343.     /// HELPERS
    344.     ///////////////////////////////////////////////////////////////////////////
    345.  
    346.     /// <summary>
    347.     /// Perform post-build steps and print build results.
    348.     /// </summary>
    349.     private static void PostBuild(BuildReport report)
    350.     {
    351.         BuildSummary summary = report.summary;
    352.  
    353.         if (summary.result == BuildResult.Succeeded)
    354.         {
    355.             Debug.Log("Build succeeded");
    356.         }
    357.  
    358.         if (summary.result == BuildResult.Failed)
    359.         {
    360.             Debug.Log("Build failed");
    361.         }
    362.     }
    363.  
    364.     /*
    365.      [MenuItem("Horseshoe/dotd/Build/HTML5 (release)")]
    366.      public static void BuildHTML5()
    367.      {
    368.          Debug.Log("Starting HTML5 build");
    369.          BuildReport report = BuildPipeline.BuildPlayer(
    370.              scenes,
    371.              "Build/HTML5",
    372.              BuildTarget.WebGL,
    373.              BuildOptions.None);
    374.          PostBuild(report);
    375.      }
    376.      */
    377.  
    378.     /*
    379.     [MenuItem("Horseshoe/dotd/Build/iOS (release)")]
    380.     static void BuildiOS()
    381.     {
    382.         Debug.Log("Starting iOS build");
    383.         BuildReport report = BuildPipeline.BuildPlayer(
    384.             scenes,
    385.             "Build/autobuild/iOS",
    386.             BuildTarget.iOS,
    387.             BuildOptions.AcceptExternalModificationsToPlayer);
    388.          PostBuild(report);
    389.     }
    390.     */
    391.  
    392.     /*
    393.     [MenuItem("Horseshoe/dotd/Build/macOS (release)")]
    394.     public static void BuildMacOS()
    395.     {
    396.         Debug.Log("Starting macOS build");
    397.         BuildReport report = BuildPipeline.BuildPlayer(
    398.             scenes,
    399.             "Build/autobuild/macOS/dotd.app",
    400.             BuildTarget.StandaloneOSX,
    401.             BuildOptions.None);
    402.          PostBuild(report);
    403.     }
    404.     */
    405.  
    406.     ///////////////////////////////////////////////////////////////////////////
    407.     /// Version Number menu handlers.
    408.     ///////////////////////////////////////////////////////////////////////////
    409.  
    410.     /// <summary>
    411.     /// Location of the version number segments within the version number array.
    412.     /// </summary>
    413.     public enum Index { Build, Major, Minor, Patch };
    414.  
    415.     /// <summary>
    416.     /// Print the current version number.
    417.     /// </summary>
    418.     [MenuItem("Horseshoe/Version/Print Current Version")]
    419.     public static void PrintVersion()
    420.     {
    421.         Debug.Log(PlayerSettings.bundleVersion);
    422.     }
    423.  
    424.     /// <summary>
    425.     /// Increase the build number.
    426.     /// </summary>
    427.     [MenuItem("Horseshoe/Version/Build/Up")]
    428.     public static void DoIncreaseBuild()
    429.     {
    430.         IncrementBuild(ParseVersion(PlayerSettings.bundleVersion));
    431.         Debug.Log($"Buld number incremented, version number is now {PlayerSettings.bundleVersion}");
    432.     }
    433.  
    434.     /// <summary>
    435.     /// Decrease the build number.
    436.     /// </summary>
    437.     [MenuItem("Horseshoe/Version/Build/Down")]
    438.     public static void DoDecreaseBuild()
    439.     {
    440.         DecrementBuild(ParseVersion(PlayerSettings.bundleVersion));
    441.         Debug.Log($"Buld number decremented, version number is now {PlayerSettings.bundleVersion}");
    442.     }
    443.  
    444.     /// <summary>
    445.     /// Increment the patch number.
    446.     /// </summary>
    447.     [MenuItem("Horseshoe/Version/Patch/Up")]
    448.     public static void DoIncreasePatch()
    449.     {
    450.         IncrementPatch(ParseVersion(PlayerSettings.bundleVersion));
    451.         Debug.Log($"Patch number incremented, version number is now {PlayerSettings.bundleVersion}");
    452.     }
    453.  
    454.     /// <summary>
    455.     /// Decrement the patch number.
    456.     /// </summary>
    457.     [MenuItem("Horseshoe/Version/Patch/Down")]
    458.     public static void DoDecreasePatch()
    459.     {
    460.         DecrementPatch(ParseVersion(PlayerSettings.bundleVersion));
    461.         Debug.Log($"Patch number decremented, version number is now {PlayerSettings.bundleVersion}");
    462.     }
    463.  
    464.     /// <summary>
    465.     /// Increment the minor number.
    466.     /// </summary>
    467.     [MenuItem("Horseshoe/Version/Minor/Up")]
    468.     public static void DoIncreaseMinor()
    469.     {
    470.         IncrementMinor(ParseVersion(PlayerSettings.bundleVersion));
    471.         Debug.Log($"Minor number incremented, version number is now {PlayerSettings.bundleVersion}");
    472.     }
    473.  
    474.     /// <summary>
    475.     /// Decrement the minor number.
    476.     /// </summary>
    477.     [MenuItem("Horseshoe/Version/Minor/Down")]
    478.     public static void DoDecreaseMinor()
    479.     {
    480.         DecrementMinor(ParseVersion(PlayerSettings.bundleVersion));
    481.         Debug.Log($"Minor number decremented, version number is now {PlayerSettings.bundleVersion}");
    482.     }
    483.  
    484.     /// <summary>
    485.     /// Increment the major number.
    486.     /// </summary>
    487.     [MenuItem("Horseshoe/Version/Major/Up")]
    488.     public static void DoIncreaseMajor()
    489.     {
    490.         IncrementMajor(ParseVersion(PlayerSettings.bundleVersion));
    491.         Debug.Log($"Major number incremented, version number is now {PlayerSettings.bundleVersion}");
    492.     }
    493.  
    494.     /// <summary>
    495.     /// Decrement the major number.
    496.     /// </summary>
    497.     [MenuItem("Horseshoe/Version/Major/Down")]
    498.     public static void DoDecreaseMajor()
    499.     {
    500.         DecrementMajor(ParseVersion(PlayerSettings.bundleVersion));
    501.         Debug.Log($"Major number decremented, version number is now {PlayerSettings.bundleVersion}");
    502.     }
    503.  
    504.     /// <summary>
    505.     /// Parse the version text into an array of integers.
    506.     /// </summary>
    507.     /// <param name="versionText">String Semantic Version number.</param>
    508.     /// <returns>Integer array of version number values.</returns>
    509.     private static int[] ParseVersion(string versionText)
    510.     {
    511.         versionText = versionText.Trim();
    512.  
    513.         string[] segments = versionText.Split('+');
    514.  
    515.         string[] versionLines = segments[0].Split('.');
    516.  
    517.         int index = 1;
    518.         int[] version = new int[versionLines.Length + 1];
    519.         foreach (string line in versionLines)
    520.         {
    521.             version[index++] = int.Parse(line);
    522.         }
    523.  
    524.         version[0] = int.Parse(segments[1]);
    525.  
    526.         return version;
    527.     }
    528.  
    529.     /// <summary>
    530.     /// Make a string representation of the version number.
    531.     /// </summary>
    532.     /// <param name="inVersion">Version number array.</param>
    533.     /// <returns>String representation.</returns>
    534.     private static string MakeVersionString(int[] inVersion)
    535.     {
    536.         string stringVersion = $"{inVersion[(int)Index.Major]}.{inVersion[(int)Index.Minor]}.{inVersion[(int)Index.Patch]}+{inVersion[(int)Index.Build]}";
    537.         return stringVersion;
    538.     }
    539.  
    540.     /// <summary>
    541.     /// Increment the buld.
    542.     /// </summary>
    543.     /// <param name="inVersion">Version number array.</param>
    544.     /// <returns>Version number array.</returns>
    545.     private static int[] IncrementBuild(int[] inVersion)
    546.     {
    547.         inVersion[(int)Index.Build]++;
    548.  
    549.         PlayerSettings.bundleVersion = MakeVersionString(inVersion);
    550.  
    551.         return inVersion;
    552.     }
    553.  
    554.     /// <summary>
    555.     /// Decrement the buld.
    556.     /// </summary>
    557.     /// <param name="inVersion">Version number array.</param>
    558.     /// <returns>Version number array.</returns>
    559.     private static int[] DecrementBuild(int[] inVersion)
    560.     {
    561.         inVersion[(int)Index.Build]--;
    562.         if (inVersion[(int)Index.Build] < 0)
    563.         {
    564.             inVersion[(int)Index.Build] = 0;
    565.         }
    566.  
    567.         PlayerSettings.bundleVersion = MakeVersionString(inVersion);
    568.  
    569.         return inVersion;
    570.     }
    571.  
    572.     /// <summary>
    573.     /// Increment the patch.
    574.     /// </summary>
    575.     /// <param name="inVersion">Version number array.</param>
    576.     /// <returns>Version number array.</returns>
    577.     private static int[] IncrementPatch(int[] inVersion)
    578.     {
    579.         inVersion[(int)Index.Patch]++;
    580.  
    581.         PlayerSettings.bundleVersion = MakeVersionString(inVersion);
    582.  
    583.         return inVersion;
    584.     }
    585.  
    586.     /// <summary>
    587.     /// Decrement the patch.
    588.     /// </summary>
    589.     /// <param name="inVersion">Version number array.</param>
    590.     /// <returns>Version number array.</returns>
    591.     private static int[] DecrementPatch(int[] inVersion)
    592.     {
    593.         inVersion[(int)Index.Patch]--;
    594.         if (inVersion[(int)Index.Patch] < 0)
    595.         {
    596.             inVersion[(int)Index.Patch] = 0;
    597.         }
    598.  
    599.         PlayerSettings.bundleVersion = MakeVersionString(inVersion);
    600.  
    601.         return inVersion;
    602.     }
    603.  
    604.     /// <summary>
    605.     /// Increment the minor.
    606.     /// </summary>
    607.     /// <param name="inVersion">Version number array.</param>
    608.     /// <returns>Version number array.</returns>
    609.     private static int[] IncrementMinor(int[] inVersion)
    610.     {
    611.         inVersion[(int)Index.Patch] = 0;
    612.         inVersion[(int)Index.Minor]++;
    613.  
    614.         PlayerSettings.bundleVersion = MakeVersionString(inVersion);
    615.  
    616.         return inVersion;
    617.     }
    618.  
    619.     /// <summary>
    620.     /// Decrement the minor.
    621.     /// </summary>
    622.     /// <param name="inVersion">Version number array.</param>
    623.     /// <returns>Version number array.</returns>
    624.     private static int[] DecrementMinor(int[] inVersion)
    625.     {
    626.         inVersion[(int)Index.Minor]--;
    627.         if (inVersion[(int)Index.Minor] < 0)
    628.         {
    629.             inVersion[(int)Index.Minor] = 0;
    630.         }
    631.  
    632.         PlayerSettings.bundleVersion = MakeVersionString(inVersion);
    633.  
    634.         return inVersion;
    635.     }
    636.  
    637.     /// <summary>
    638.     /// Increment the major.
    639.     /// </summary>
    640.     /// <param name="inVersion">Version number array.</param>
    641.     /// <returns>Version number array.</returns>
    642.     private static int[] IncrementMajor(int[] inVersion)
    643.     {
    644.         inVersion[(int)Index.Patch] = 0;
    645.         inVersion[(int)Index.Minor] = 0;
    646.         inVersion[(int)Index.Major]++;
    647.  
    648.         PlayerSettings.bundleVersion = MakeVersionString(inVersion);
    649.  
    650.         return inVersion;
    651.     }
    652.  
    653.     /// <summary>
    654.     /// Decrement the major.
    655.     /// </summary>
    656.     /// <param name="inVersion">Version number array.</param>
    657.     /// <returns>Version number array.</returns>
    658.     private static int[] DecrementMajor(int[] inVersion)
    659.     {
    660.         inVersion[(int)Index.Major]--;
    661.         if (inVersion[(int)Index.Major] < 0)
    662.         {
    663.             inVersion[(int)Index.Major] = 0;
    664.         }
    665.  
    666.         PlayerSettings.bundleVersion = MakeVersionString(inVersion);
    667.  
    668.         return inVersion;
    669.     }
    670.  
    671.     ///////////////////////////////////////////////////////////////////////////
    672.     /// Build Target menu handlers.
    673.     ///////////////////////////////////////////////////////////////////////////
    674.  
    675.     [MenuItem("Horseshoe/Build Target/Android")]
    676.     public static void SetAndroidTarget()
    677.     {
    678.         EditorUserBuildSettings.standaloneBuildSubtarget = StandaloneBuildSubtarget.Player;
    679.         EditorUserBuildSettings.SwitchActiveBuildTarget(BuildTargetGroup.Android, BuildTarget.Android);
    680.     }
    681.  
    682.     [MenuItem("Horseshoe/Build Target/Windows")]
    683.     public static void SetWindowsTarget()
    684.     {
    685.         EditorUserBuildSettings.standaloneBuildSubtarget = StandaloneBuildSubtarget.Player;
    686.         EditorUserBuildSettings.SwitchActiveBuildTarget(BuildTargetGroup.Standalone, BuildTarget.StandaloneWindows64);
    687.     }
    688.  
    689.     [MenuItem("Horseshoe/Build Target/Linux Dedicated Server")]
    690.     public static void SetLinuxDSTarget()
    691.     {
    692.         EditorUserBuildSettings.standaloneBuildSubtarget = StandaloneBuildSubtarget.Server;
    693.         EditorUserBuildSettings.SwitchActiveBuildTarget(BuildTargetGroup.LinuxHeadlessSimulation, BuildTarget.StandaloneLinux64);
    694.     }
    695.  
    696.     [MenuItem("Horseshoe/Build Target/Windows Dedicated Server")]
    697.     public static void SetWindowsDSTarget()
    698.     {
    699.         EditorUserBuildSettings.standaloneBuildSubtarget = StandaloneBuildSubtarget.Server;
    700.         EditorUserBuildSettings.SwitchActiveBuildTarget(BuildTargetGroup.Standalone, BuildTarget.StandaloneWindows64);
    701.     }
    702. }
    703. #endif
    704.  
     
    sachaamm and cristianm_unity like this.
  12. MrG

    MrG

    Joined:
    Oct 6, 2012
    Posts:
    363
    I do something similar for Mirror Networking projects since the Dedicated Server platform isn't doing nearly enough of what it should.

    I create a separate project, but instead of duplicating the client project, I have specific folders in the client project that I create folder junctions to from the server project, so the server project has no art or anything else it doesn't explicitly need.
     
  13. JohannRw

    JohannRw

    Unity Technologies

    Joined:
    Jan 26, 2022
    Posts:
    13
    wakayama likes this.
Thread Status:
Not open for further replies.