Search Unity

Feature Request Standardize Project and User Settings

Discussion in 'Editor & General Support' started by Ziflin, Feb 22, 2021.

  1. Ziflin

    Ziflin

    Joined:
    Mar 12, 2013
    Posts:
    132
    It would be great if someone from Unity could please comment on any plans for improvements to User & Project Settings standardization. Perhaps I've missed something, but here's my take on types of settings that we need (and issues with the current "solutions"):

    User Settings (Editor Only)
    • These are per-user settings that are only needed in the editor.
    • Should ideally be ScriptableObject-derived and stored in /UserSettings/
      • Storing them in /Assets is not desired for those of us working on multiplayer games that need to use symbolic links to /Assets to quickly test multiplayer games. This would also require users adding another folder to be ignored by version control.
      • Currently AssetDatabase.CreateAsset()fails to create/load in /UserSettings/.
    • EditorPrefs - Only useful for minor settings and suffers the same problem for multiplayer testing. Requires more work to use than a ScriptableObjects.
    • Json - Serialization is not as advanced as ScriptableObjects without additional libraries. Another format should not be required.
    • Ideally Unity would provide a UserSettings.Get<T>() accessor to return the settings instance.

    Project Settings (Editor and Runtime)
    • Project-wide settings that can be accessed by editor plug-ins or at runtime.
    • Again, would ideally be ScriptableObject-derived and stored in /ProjectSettings/. Editor-only settings could be stored in an Editor/ sub-directory and excluded from builds.
    • Ideally Unity would provide a ProjectSettings.Get<T>() accessor to return the settings instance. Runtime settings should be loaded when the player starts and be accessible at runtime.
      • Currently, to have runtime-accessible project-wide settings requires placing them in a Resources/ sub-directory and calling Resources.Load() to load them.

    SettingsProvider Improvements

    • Add a [Settings] attribute or base classes so that the editor's settings UI can do everything without us needing to write a custom SettingsProvider unless custom UI is required.
      • This means that exposing new settings would only require writing a very minimal class with just the settings as fields.
    • At the very least provide a static SettingsProvider.DrawDefaultInspector(so) call similar to the one in the Editor class to avoid having to write individual PropertyField() calls.

    I'm sure I've missed a few things, but it's currently a bit frustrating that there still isn't a simple/standard way to implement settings for these use cases.
     
    Qriva, OBiwer, ArthurAulicino and 5 others like this.
  2. david-wtf

    david-wtf

    Joined:
    Sep 30, 2021
    Posts:
    25
    +1 for this. I just discovered that `AssetDatabase.CreateAsset()` denies creating a scriptable object instance inside `UserSettings`. This is unfortunate, and requires us to to add yet another folder to .gitignore, as mentioned by the original creator of this thread.
     
  3. You really should use ScriptableSingleton if you want to have editor settings-like things. You even have the choice to store them automatically inside the Assets or outside per user.
     
  4. david-wtf

    david-wtf

    Joined:
    Sep 30, 2021
    Posts:
    25
    @Lurking-Ninja what is the benefit of using a ScriptableSingleton over a regular ScriptableObject with persistence? It seems it take over the persistence part, but that's about it, right? But in any case, I assume scriptable singletons also don't allow writing to `UserSettings`, or do they?
     
  5. John_Leorid

    John_Leorid

    Joined:
    Nov 5, 2012
    Posts:
    650
    They do, just read the docs page carefully
    https://docs.unity3d.com/2020.1/Documentation/ScriptReference/ScriptableSingleton_1.html

    Especially FilePathAttribute:
    https://docs.unity3d.com/2020.1/Doc...PathAttribute.Location.PreferencesFolder.html
     
    david-wtf and Lurking-Ninja like this.
  6. John_Leorid

    John_Leorid

    Joined:
    Nov 5, 2012
    Posts:
    650
    Yea and Settings Per User Per Project pls.
    So I can write things like a favorite explorer for GameObjects in a scene, which is obviously only relevant inside ONE specific project, but also only relevant for one user.
     
    david-wtf likes this.
  7. Prodigga

    Prodigga

    Joined:
    Apr 13, 2011
    Posts:
    1,123
    Just for completeness, this seems to work:

    Code (CSharp):
    1. [FilePath("UserSettings/MyTestSettings.asset", FilePathAttribute.Location.ProjectFolder)]
    2. internal class MyTestSettings : ScriptableSingleton<MyTestSettings>
    3. {
    4.     [SerializeField] private int _changeCount;
    5.     [SerializeField] private string _someValue;
    6.  
    7.     public string SomeValue
    8.     {
    9.         get => _someValue;
    10.         set
    11.         {
    12.             _someValue = value;
    13.             _changeCount++;
    14.             Save(true);
    15.         }
    16.     }
    17.  
    18.     public int ChangeCount => _changeCount;
    19.  
    20.     [MenuItem("Test/Poke My Test Settings")]
    21.     public static void Poker()
    22.     {
    23.         MyTestSettings.instance.SomeValue = $"Hello world..! I've been poked {MyTestSettings.instance.ChangeCount}x times!";
    24.     }
    25. }
    Creates an .asset in UserSettings, works as expected. Use `Test -> Poke My Test Settings` option to (generate) and modify the test settings asset. Navigate the UserSettings folder to see it changing.
     
    Grumpy-Dot and aurelioprovedo like this.
  8. Mako-Infused

    Mako-Infused

    Joined:
    Nov 20, 2014
    Posts:
    2
    @Prodigga while your solution works, it doesn't appear to completely satisfy the original requirements laid out by @Ziflin. Unless I'm misunderstanding, this part says:
    Project-wide settings that can be accessed by editor plug-ins or at runtime.
    .

    Currently ScriptableSingleton<> is only usable under the UnityEditor namespace, as such it will fail to compile if we included it in the build, so therefore it's use during runtime isn't viable.
     
  9. Ziflin

    Ziflin

    Joined:
    Mar 12, 2013
    Posts:
    132
    @Mako-Infused Yeah, this was the same issue that I've run into regarding it only being useful in the editor. Unless I've missed an update, there's still no way for us to save ScriptableObjects to ProjectSettings/ for use at runtime, though clearly Unity does with several of their project settings such as the ones for Physics and Time.

    The article I wrote (Custom Runtime and Editor Settings in Unity) describes what we're still using.

    Also, with the code from @Prodigga above which uses a property set/get, you cannot easily expose the settings to a SettingsProvider without making custom settings UI.
     
    Last edited: Jun 28, 2022
    Prodigga likes this.
  10. tgaldi

    tgaldi

    Joined:
    Oct 28, 2015
    Posts:
    102
    Last edited: Jan 3, 2023
  11. Wolfos

    Wolfos

    Joined:
    Mar 17, 2011
    Posts:
    951
    I would definitely love to have something that is set at edit time and readable at runtime. Just a simple API like PlayerPrefs would be fine.
     
  12. spiney199

    spiney199

    Joined:
    Feb 11, 2021
    Posts:
    7,859
    Wolfos likes this.