Search Unity

  1. Unity 6 Preview is now available. To find out what's new, have a look at our Unity 6 Preview blog post.
    Dismiss Notice
  2. Unity is excited to announce that we will be collaborating with TheXPlace for a summer game jam from June 13 - June 19. Learn more.
    Dismiss Notice
  3. Dismiss Notice

Question How can I set the remote config environment ID from a build script?

Discussion in 'Unity Remote Config' started by neviovalsa, Apr 10, 2024.

  1. neviovalsa

    neviovalsa

    Joined:
    Jun 24, 2019
    Posts:
    54
    I have a build script and before calling

    BuildPipeline.BuildPlayer()


    I wanna be able to set which Remote COnfig environemnt will be used.
    Where can I set that?
     
  2. CodeSmile

    CodeSmile

    Joined:
    Apr 10, 2014
    Posts:
    6,974
  3. GabKBelmonte

    GabKBelmonte

    Unity Technologies

    Joined:
    Dec 14, 2021
    Posts:
    151
    CodeSmile is right, but I want to bring highlight to
    Code (CSharp):
    1. https://docs.unity.com/ugs/en-us/manual/overview/manual/environments-api#Build_and_runtime
    .

    If you set the environment in-code like this, this will be used.

    Code (CSharp):
    1. var options = new InitializationOptions()
    2.                 .SetEnvironmentName(environment);
    3. await UnityServices.InitializeAsync(options);
    If not, we will use what you select in the dropdown.
    upload_2024-4-10_14-55-52.png
    If not, we will use "production".

    I hope this clears things up.
     
    CodeSmile likes this.
  4. neviovalsa

    neviovalsa

    Joined:
    Jun 24, 2019
    Posts:
    54
    Thank you that's helpful.

    I guess my question wasn't valid then, there isn't really a way to set the environment at build time (as it will always default to "production" for production builds).

    I'll have to save the different environment name for each build somewhere and then pass it in initialization options.

    In this case, would it be considered bad practice to store the environment name as plain text? In something like a text file or scriptable object?
     
  5. GabKBelmonte

    GabKBelmonte

    Unity Technologies

    Joined:
    Dec 14, 2021
    Posts:
    151
    I see, in that case, the API that CodeSmile is exactly what you need. It basically gives you programmatic access to the dropdown ; you're modifying the dropdown through code.

    You can modify the environment right before you build it.
    (I believe you may need to call "RefreshAsync" first)
    However, if you can tell me what your usecase is, it could prove insightful for further development!

    Cheers!
     
    Last edited: Apr 10, 2024
    CodeSmile and neviovalsa like this.
  6. neviovalsa

    neviovalsa

    Joined:
    Jun 24, 2019
    Posts:
    54
    My use case(simplified here) is that I want to deploy the game to steam in it's full and demo versions separately, where the demo version simply hides some menu options and restricts access to certain levels.

    I was hoping to deploy the same build on both simply pointing at different remote configs, and guide activation/deactivation of features from those environments.

    I understand that it might not be the safest approach as someone could tinker with the game and access the full game from the demo version, but I'm not really concerned.
     
  7. GabKBelmonte

    GabKBelmonte

    Unity Technologies

    Joined:
    Dec 14, 2021
    Posts:
    151
    Awesome, the above will help you set the correct environments for each version, so you can keep analytics and all the information separate (if thats what you want).

    However, if you use preprocessors you can also prevent the extra code from being made available, this will make it impossible for anyone to access that code by hacking the game code.

    Preprocessor code complete eliminated from the final binary. It wont

    They can be enabled, disabled via the project settings > player > script define symbols

    upload_2024-4-10_17-13-27.png

    I would be surprised if there's not something equivalent for assets, though I'm not familiar with that.

    Remote Config would be more of the capacity to turn on/off features dynamically, like enabling a xmas event, that kind of thing. You can use it the way you want though, up to you!

    Cheers
     
  8. neviovalsa

    neviovalsa

    Joined:
    Jun 24, 2019
    Posts:
    54
    Hi sorry I put this aside for a few days.

    So I've tried using the EnvironmentsApi as suggested, and I'm getting a weird error (possibly unrelated to the Services.Core api?).

    Basically I'm not able to use `using Unity.Services.Core.Editor.Environments;`
    The code deosn't compile saying the Unity.Services.Core.Editor namespace doesn't exists, while in fact it does exist (I even get intellisense)

    Here's a build test script I was testing:

    Code (CSharp):
    1. using System;
    2. using System.Diagnostics;
    3. using System.Linq;
    4. using Unity.Services.Core.Editor.Environments;
    5. using UnityEditor;
    6. using UnityEngine;
    7.  
    8. public class EditorTest
    9. {
    10.         [MenuItem("MyTools/Windows Build With Postprocess")]
    11.         public static async void BuildGame()
    12.         {
    13.             // Get filename.
    14.             var path = EditorUtility.SaveFolderPanel("Choose Location of Built Game", "", "");
    15.             string[] levels =
    16.             {
    17.                 "my-scene-name1", "my-scene-name2"
    18.             };
    19.  
    20.             await EnvironmentsApi.Instance.RefreshAsync();
    21.             EnvironmentInfo info = new();
    22.             var env = EnvironmentsApi.Instance.Environments.First(x => x.Id.ToString() == "my-environment-id");
    23.             if (env == null)
    24.             {
    25.                 throw new Exception("Error finding the environment");
    26.              
    27.             }
    28.             EnvironmentsApi.Instance.SetActiveEnvironment(env);
    29.          
    30.             // Build player.
    31.             BuildPipeline.BuildPlayer(levels, path + "/BuiltGame.exe", BuildTarget.StandaloneWindows,
    32.                 BuildOptions.None);
    33.  
    34.             // Run the game (Process class from System.Diagnostics).
    35.             var proc = new Process();
    36.             proc.StartInfo.FileName = path + "/BuiltGame.exe";
    37.             proc.Start();
    38.         }
    39.     }
    • This script is inside an Editor folder.
    • I've tried deleting all csproj files, and regenerating project files
    • I've tried creating a new blank Unity project and go the same problem
    • I've tried switching between Visual Studio and Rider

     
  9. GabKBelmonte

    GabKBelmonte

    Unity Technologies

    Joined:
    Dec 14, 2021
    Posts:
    151
    Hello!

    The assembly is not automatically referenced (not sure why we made that choice, but it's generally safer to be explicit in my experience).
    1. do you have an asmdef?
    2. the asmdef must reference "Unity.Services.Core.Environments.Editor"

    let me know if that works for you
     
  10. neviovalsa

    neviovalsa

    Joined:
    Jun 24, 2019
    Posts:
    54
    Thanks again :)
    Creating an asmdef for the editor scripts did the trick and I was able to access the EnvironemntsApi
    (definitely a wake up call to learn more about asmdef, so thanks for that as well)

    Still, the problems remains as the EnvironmentsApi can only really change the environment for the editor.

    That said, I don't know why I was so stuck on setting the environment at build time, I ended up implementing it so that I save the env name in a scriptable object and use that at runtime.
     
  11. GabKBelmonte

    GabKBelmonte

    Unity Technologies

    Joined:
    Dec 14, 2021
    Posts:
    151
    are you setting the environment in code? i.e. do you have

    Code (CSharp):
    1. .SetEnvironmentName("something")
    somewhere?

    Recall that the dropdown is secondary to code.
    Code > Dropdown > Prod

    the dropdown will only set the runtime environment if its not set explicitly in code
     
  12. neviovalsa

    neviovalsa

    Joined:
    Jun 24, 2019
    Posts:
    54
    Yes I made sure to remove any environement set explicitily in code.

    Note that the dropdown in proj settings only sets the editor environment, so it does make sense that modififying that wouldn't work for a build upload_2024-4-18_12-46-33.png

    So to clarify, calling ` EnvironmentsApi.Instance.SetActiveEnvironment(env);` in my build script would succesfully modify my value in the Proj Settings -> Services -> Environments dropdown , but the build produced by ` BuildPipeline.BuildPlayer(...)` is not using that same environment
     
  13. GabKBelmonte

    GabKBelmonte

    Unity Technologies

    Joined:
    Dec 14, 2021
    Posts:
    151
    That sounds like a bug, does it work in debug runtime (ie without building player?)


    Ill raise it up to the team. what version of everything are you using?
    Core package, unity version, and com.unity.services.deployment

    Sorry about that
     
  14. arnaud_gout

    arnaud_gout

    Unity Technologies

    Joined:
    Sep 17, 2021
    Posts:
    27
    Hey neviovalsa, I will be assisting you on that one.
    I created a small repro project with thew following versions:
    * Unity Editor 2022.3
    * Deployment 1.3.0
    * Remote config 4.0.0
    I had 2 environment that both had the same remote config key configured (and published), with different values.
    I used your code, but had to change a few things in order to have it work, especially the removal of `if (env == null) {...}` given that the function First throws if no element satisfies the predicate.
    I was able to confirm the environment selection works as expected using a very simple snippet, regardless which environment is selected in the project settings.
    Here's the snippet in question:

    Code (CSharp):
    1. using System.Threading.Tasks;
    2. using TMPro;
    3. using Unity.Services.Authentication;
    4. using Unity.Services.Core;
    5. using UnityEngine;
    6. using Unity.Services.RemoteConfig;
    7.  
    8. public class RuntimeTest : MonoBehaviour
    9. {
    10.     // attach this to a text mesh pro text component
    11.     public TextMeshProUGUI text;
    12.  
    13.     public struct userAttributes {
    14.     }
    15.  
    16.     public struct appAttributes {
    17.     }
    18.  
    19.     async Task InitializeRemoteConfigAsync()
    20.     {
    21.             // initialize handlers for unity game services
    22.             await UnityServices.InitializeAsync();
    23.  
    24.             // remote config requires authentication for managing environment information
    25.             if (!AuthenticationService.Instance.IsSignedIn)
    26.             {
    27.                 await AuthenticationService.Instance.SignInAnonymouslyAsync();
    28.             }
    29.     }
    30.  
    31.         // Create a function to set your variables to their keyed values:
    32.     void ApplyRemoteConfig (ConfigResponse configResponse) {
    33.         var env = RemoteConfigService.Instance.appConfig.GetString("test_key_env");
    34.         Debug.Log($"Environment is {RemoteConfigService.Instance.appConfig.GetString("test_key_env")}");
    35.         text.text = env;
    36.     }
    37.  
    38.     async Task Awake () {
    39.  
    40.         // initialize Unity's authentication and core services
    41.         await InitializeRemoteConfigAsync();
    42.  
    43.         // Add a listener to apply settings when successfully retrieved:
    44.         RemoteConfigService.Instance.FetchCompleted += ApplyRemoteConfig;
    45.  
    46.         // Fetch configuration settings from the remote service, they must be called with the attributes structs (empty or with custom attributes) to initiate the WebRequest.
    47.         await RemoteConfigService.Instance.FetchConfigsAsync(new userAttributes(), new appAttributes());
    48.     }
    49. }
    50.  
    After this, the next step to investigate this is for you to provide the exact versions of the editor and packages you are using as Gabriel mentioned (editor, remote config package, deployment package), and also make sure you published the remote config values, because this is a common mistake we all do ;)