{"id":15160848,"url":"https://github.com/zenvin-dev/unitysettingsframework","last_synced_at":"2026-03-08T11:36:56.263Z","repository":{"id":41350930,"uuid":"473768876","full_name":"zenvin-dev/UnitySettingsFramework","owner":"zenvin-dev","description":"This package aims to provide a comprehensible, simple and expandable way of creating in-game settings for any Unity game.","archived":false,"fork":false,"pushed_at":"2024-11-04T20:48:38.000Z","size":446,"stargazers_count":73,"open_issues_count":1,"forks_count":0,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-03-26T23:07:19.046Z","etag":null,"topics":["framework","game-settings","settings","unity","unity3d","upm","upm-package"],"latest_commit_sha":null,"homepage":"","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/zenvin-dev.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-03-24T20:49:32.000Z","updated_at":"2025-02-04T14:46:42.000Z","dependencies_parsed_at":"2023-10-13T09:42:00.456Z","dependency_job_id":"cce16d5b-7f67-4ec6-b57f-7f3fbc76cf4c","html_url":"https://github.com/zenvin-dev/UnitySettingsFramework","commit_stats":null,"previous_names":["zenvin-dev/unitysettingsframework","xzenvin/unitysettingsframework"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zenvin-dev%2FUnitySettingsFramework","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zenvin-dev%2FUnitySettingsFramework/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zenvin-dev%2FUnitySettingsFramework/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zenvin-dev%2FUnitySettingsFramework/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/zenvin-dev","download_url":"https://codeload.github.com/zenvin-dev/UnitySettingsFramework/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248675434,"owners_count":21143763,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["framework","game-settings","settings","unity","unity3d","upm","upm-package"],"created_at":"2024-09-26T23:40:20.403Z","updated_at":"2026-03-08T11:36:56.225Z","avatar_url":"https://github.com/zenvin-dev.png","language":"C#","readme":"![# Unity Settings Framework Logo](/.GitHubResources/Banner.png)\n\nThis package aims to provide a comprehensible and expandable way of creating in-game settings for any Unity game.\n\\\nTo do so, it uses [Scriptable Objects](https://docs.unity3d.com/Manual/class-ScriptableObject.html) and [generics](https://docs.microsoft.com/en-us/dotnet/standard/generics/), the latter of which Unity can serialize since version [2020.1](https://forum.unity.com/threads/generics-serialization.746300/).\n\\\n**The package will not work in pre-2020.1 versions!**\n\n## Table of contents\n- [Features](#features)\n- [Installation](#installation)\n- [Requirements](#requirements)\n- [Usage](#usage)\n- [Known Issues](#known-issues)\n- [(Basic) Documentation](#documentation)\n- [Creating your own Setting type](#creating-your-own-setting-types)\n- [Saving and Loading](#saving-and-loading-setting-values)\n- [Loading external settings](#loading-external-settings)\n- [Examples](#examples)\n\n\n# Features\n- Flexible and extensible way of setting up game settings\n\t- Intuitive editor for creating and managing settings\n\t- ScriptableObject-based architecture, no need to manage scene objects\n\t- Settings can be grouped together\n\t- No code changes or recompilation required for creating or referencing setting instances\n\t- Easy creation of custom setting types and setting group types\n\t- Type-safety through use of generics\n\t- Values of custom settings can easily be validated before they are assigned\n- Staged value changing allows reverting a setting to its previous state before a new value is applied\n- Multiple ways of referencing settings\n\t- As a reference in a wrapper class, that also provides a fallback value\n\t- With direct references to Settings objects\n\t- Through code by their respective ID\n- Utility for automatically creating UI menus from a Settings asset\n\t- UI controls can be chosen automatically, based on setting type\n\t- UI controls are designed to work with Unity's UI events\n\t- Show, hide, or disable individual settings or entire groups in the UI\n- Built to easily adapt to the way you save and load your game\n\t- Settings can implement an arbitrary number of serialization methods\n\t- Built-in JSON and binary serializers\n- Little memory overhead: Setting objects are **not** cloned during runtime\n- Additional settings can be added during runtime by loading a json string (great for modding support)\n- [Version 3.0.0+] Component-based workflow to allow for easier extending of Setting or Setting Group behaviour\n\n# Installation\nThis package can be installed through the Unity Package Manager using the following URL:\n```\nhttps://github.com/zenvin-dev/UnitySettingsFramework.git\n```\nOr you could download the ZIP Archive, unpack it, and add the contents to your Unity project's \"Assets\" directory.\n\n# Requirements\n- Unity 2020.1 or later\n- Newtonsoft Json 2.0.0 or later\n\nFor the \"Localization Setting\" sample:\n- [Unity Localization](https://docs.unity3d.com/Packages/com.unity.localization@1.4/manual/index.html) package (any version should work)\n\nFor the \"Volume Setting FMOD\" sample:\n- [Unity FMOD](https://www.fmod.com/unity) plugin (any recent version should work, tested with `2.02.22`)\n\nFor the \"Keybind Setting\" sample:\n- [Input System](https://docs.unity3d.com/Packages/com.unity.inputsystem@1.8/manual/index.html) package (any version should work, tested with `1.2.0`)\n- Credits: The Keybind Control prefab currently uses an icon by [Icons8](https://icons8.com), which is subject to their [license](https://icons8.com/license) [terms](https://intercom.help/icons8-7fb7577e8170/en/articles/5534926-universal-multimedia-license-agreement-for-icons8)\n\n# Usage\n### 1. Creating a Settings Asset\nA `SettingsAsset` will hold all of your individual Settings and Settings Groups. \\\nTo create one, simply use the create menu \\\n`Create \u003e Scriptable Objects \u003e Zenvin \u003e Settings Asset`\n\n### 2. Editing a Settings Asset\nOnce you have created the `SettingsAsset`, you can use the **Settings Editor Window** (`Window \u003e Zenvin \u003e Settings Asset Editor`) to add, delete, move and group Settings. Double-clicking `SettingsAsset`s will open the editor. \\\nNote that changing the Settings' hierarchy is only permitted during edit-time. The corresponding popup menus will not appear during runtime. \\\nIf there is no asset being edited currently, the editor will show a list of available instances.\n\n### 3. Initializing a Settings Asset\nWhen your game first starts, you will need to initialize any SettingsAsset whose nested settings you intend on using. \\\nThis is done through the `SettingsAsset.Initialize()` method. (Calling it multiple times will not have any effect) \\\nFor performance reasons, it is recommended to load external Settings during initialization, rather than afterwards.\n\n### 4. Using Settings\nGenerally speaking, there are 3 different ways of referencing Settings:\n- As a `SettingBase\u003cT\u003e` reference that is assigned in the editor or through code.\n- Wrapped in a `SettingReference\u003cT\u003e` instance, whose value is assigned in the editor. This has the advantage that a default value can be given, even if the Setting is `null`.\n- Accessed by its `GUID` using `SettingsAsset.TryGetSettingByGUID(string, out SettingBase)`, assuming that the containing `SettingsAsset` has been initialized.\n\nEach Setting object contains 2 essential values that are managed by the Framework:\n- `CurrentValue`: The value that is currently **applied** to the Setting.\n- `CachedValue`: The value that the Setting will have once applied.\n\nTo get a Setting's value, you would usually poll `CurrentValue`. This can be done either continuously, or every time `SettingBase\u003cT\u003e.OnValueApplied` is invoked.\n\n\n# Known Issues\n- When a project is opened and contains compiler errors, or a package is imported that introduces compiler errors, a SettingsAsset may lose references to any child object whose type is not built into the package. \\\nI have attempted to provide a method of solving this, but it may not work in all instances. Using version control is recommended.\n\n\n# Documentation\nSettings are represented by Scriptable Object instances that inherit `Zenvin.Settings.Framework.SettingBase\u003cT\u003e`. They each contain a number of properties by default, but can be extended to contain further members by creating own classes inheriting the aforementioned base class.\n\nSettings Groups can be used to group Settings together. Just like Settings, they are Scriptable Objects (inheriting `Zenvin.Settings.Framework.SettingsGroup`), and it is possible to extend the built-in `SettingsGroup` type by inheriting from it.\n\\\nWhen creating UI for your Settings, Groups can be used to separate them into tabs or sub-headers.\n\n### Shared serialized Properties\nBelow is a list of properties shared between `Zenvin.Settings.Framework.SettingBase` and `Zenvin.Settings.Framework.SettingsGroup`, that show up in the inspector.\n\n| Property | Type | Description |\n|-|-|-|\n| `GUID` | string | The `GUID` provides a unique identifier for each Setting or Group. By default, it will be assigned a pseudo-random, unique hexadecimal string which can be changed through the Setting Editor window.\u003cbr\u003eHowever, the value cannot be empty and it must be unique among **all** Settings/Groups within the same `SettingsAsset`. Should that not be the case, the system will reset the `GUID` to its previous value. |\n| `Name` | string | The `Name` is supposed to be the default label for the Setting on UI. Is also will show up in the hierarchy of the Settings Editor window.\u003cbr\u003eSetting names do not need to be unique. |\n| `NameLocalizationKey` | string | The `NameLocalizationKey` can be used to add localization to your Settings menus. Just as the `Name`, it can have an arbitrary value. |\n\n\n### SettingBase serialized properties\nBelow is a list of properties unique to `Zenvin.Settings.Framework.SettingBase\u003cT\u003e`, that show up in the inspector.\n\n| Property | Type | Description |\n|-|-|-|\n| `DefaultValue` | T | The `DefaultValue` is a generically typed value, and will be assigned to the Setting by default during runtime initialization. |\n\n\n### SettingsGroup serialized properties\nBelow is a list of properties unique to `Zenvin.Settings.Framework.SettingsGroup`, that show up in the inspector.\n\n| Property | Type | Description |\n|-|-|-|\n| `Icon` | Sprite | The `Icon` is a sprite that can be used to represent the Group on UI, either instead or along with the name. |\n\n\n# Creating your own Setting types\nThere are basic types of settings built into the framework. In case that this is not sufficient for your project, you can easily create your own type of setting by creating a class that inherits `Zenvin.Settings.Framework.SettingBase\u003cT\u003e`.\n\nSee below for more info on what you can do in custom settings:\n\n### Processing Setting values\nIn some cases, it is necessary that your Setting value adheres to specific rules. For example, when your Setting refers to an array using its value.\n\\\n`ProcessValue(ref T)` in `SettingBase\u003cT\u003e` is a `virtual void` method allows to process a given value, before the Setting is updated with it. By default, this method does nothing, so it does not _have_ to be overridden if you just want to use the value as-is.\n\n### Setting, Applying, Reverting and Resetting values\n- When `SetValue(T)` is called on a given `SettingBase\u003cT\u003e`, it will update the Setting's `CachedValue` and mark the Setting as _dirty_.\n- Dirty Settings can be applied with a call to `ApplyValue()`. This will remove the _dirty_ flag, update the Setting's `CurrentValue` with whatever `CachedValue` was set to, and invoke `OnValueApplied`.\n- Reverting a _dirty_ Setting with a call to `RevertValue()` will set its `CachedValue` to its `CurrentValue`.\n- A Setting can be reset by calling `ResetValue()`. This will set its value to the `DefaultValue` it was given in the editor.\n- Reverting or resetting will invoke `OnValueReverted` or `OnValueReset`, respectively. They will also both mark the Setting as _dirty_.\n\n\n# Saving and Loading Setting values\nSettings can be serialized in any number of ways. The Framework uses the `ISerializer\u003cT\u003e` and `ISerializable\u003cT\u003e` interfaces to facilitate a most abstract approach to this. You can have a look at the included [JSON](./Runtime/Framework/Serialization/JSON/) and [binary](./Runtime/Framework/Serialization/Binary/) serializers to get an idea of how to implement `ISerializer\u003cT\u003e`, and check out any of the [built-in Setting types](./Runtime/Framework/Settings/) to see, how `ISerializable\u003cT\u003e` may be implemented. \\\nSee below for a more in-depth explanation.\n\n### Serialization\nSerializing Settings starts with a call to `SettingsAsset.SerializeSettings`. This method needs to be passed an `ISerializer\u003cT\u003e` instance. \\\nThat instance is responsible for managing save data for all Settings that implement `ISerializable` with the same `T`. From this follows, that **any Settings that do not implement `ISerializable` of the required type will be ignored during the serialization process.** \\\nWhen Settings are serialized, a new instance of `T` will be created for each Setting and passed to the Setting's implementation of `ISerializable\u003cT\u003e.OnSerialize` to be manipulated (i.e. receive information about the Setting's state).\nAfter that, it is passed on to the given `ISerializer\u003cT\u003e` instance, along with the currently serialized Setting's `GUID` via `ISerializer\u003cT\u003e.Serialize(string, T)`. \\\nFrom that point on, it is the serializer's task to store this information.\n\n### Deserialization\nDeserializing Settings starts with a call to `SettingsAsset.DeserializeSettings`. This method needs to be passed an `ISerializer\u003cT\u003e` instance. \\\nThat instance then has to provide a collection of all saved `GUID`s, along with their associated data in the form of an instance of `T`, via `ISerializer\u003cT\u003e.GetSerializedData()`. \\\nSubsequently, that collection will be iterated and any Setting whose GUID was found in the data and that implements a fitting `ISerializable\u003cT\u003e` will receive the respective data to read from. This again means that **any Settings that do not implement `ISerializable` of the required type will be ignored during the deserialization process.** \\\nJust with serialization, the specific way of deserialization will have to be implemented by the consumer, using `ISerializable\u003cT\u003e.OnDeserialize`. \\\n\\\n**Important** \\\nDue to the generic nature of the deserialization process, Settings' values cannot automatically be assigned to the loaded data. This means that calling `SettingBase\u003cT\u003e.SetValue` manually is required at the end of the `ISerializable\u003cT\u003e.OnDeserialize` method, if that method is supposed to fulfil its function. \\\nThe Framework will however automatically call `ApplyValue` on each deserialized Setting.\n\n### Hooking into the Serialization/Deserialization process\nSometimes, the serialized or deserialized data might need to be processed, such as loading data from a file before deserialization, or writing it to a file after serialization. \\\nFor this purpose, any class implementing `ISerializer\u003cT\u003e` may also implement `ISerializerCallbackReceiver` (not to be confused with Unity's [`ISerializationCallbackReceiver`](https://docs.unity3d.com/ScriptReference/ISerializationCallbackReceiver.html)!). \\\nThis interface implements the following four methods, which can be used to respond to specific steps of the serialization process: \n- `InitializeSerialization()` will be called before serialization starts.\n- `FinalizeSerialization()` will be called after serialization has finished.\n- `InitializeDeserialization()` will be called before deserialization starts.\n- `FinalizeDeserialization()` will be called after deserialization has finished.\n\nSee [JSON File Serializer](./Runtime/Framework/Serialization/JSON/JsonFileSerializer.cs) or [Binary File Serializer](./Runtime/Framework/Serialization/Binary/BinaryFileSerializer.cs) for examples on how to implement the interface.\n\nNote that none of the above methods will be invoked, if the serialization/deserialization fails instantly, due to the executing `SettingsAsset` not being initialized.\n\n# Loading external Settings\nThe Framework allows loading one or multiple Settings and Setting Groups from one or several JSON strings.\n\\\nLoading will ignore all Settings and Groups whose `GUID`s already exist. However, it is possible to load external Settings and Groups as children of existing Groups, as well as loading external Settings as children of external Groups from the same or a previous load process.\n\\\n\\\nHowever, loading is only possible during the initialization process of the SettingsAsset. To load, first subscribe to `SettingsAsset.OnInitialize`, then call `SettingsAsset.Initialize()`.\n\n### Setting Factories\nIn order to load external Settings, the `RuntimeSettingLoader` needs to know how to translate the `string` values it gets from the parsed JSON objects into `SettingBase\u003cT\u003e` instances.\n\\\nThat is where the `ISettingFactory` interface comes into play:\n- `ISettingFactory.GetDefaultValidType()`: This method returns the default type `string` which this factory can translate into a Setting object. This value can be overridden while calling `RuntimeSettingLoader.LoadSettingsIntoAsset`.\n- `ISettingFactory.CreateSettingFromType(string, StringValuePair[])`: Should return an instance of your desired Setting class.\n\n### Group Factories\nLoading external Groups happens similarly to the way external Settings are loaded, with the main difference being that the `RuntimeSettingLoader` will fall back to the built-in `SettingsGroup` type, if it cannot translate the JSON values into Group instances.\n\\\nTranslating the values again, is where an interface is used - respectively `IGroupFactory`:\n- `IGroupFactory.GetDefaultValidType()`: This method returns the default type `string` which this factory can translate into a Group object. This value can be overridden while calling `RuntimeSettingLoader.LoadSettingsIntoAsset`.\n- `IGroupFactory.CreateGroupFromType(StringValuePair[])`: Should return an instance of your desired Group class.\n\n\n# Examples\n## 1. Creating a Setting based on an `int` to serve as a dropdown\nMake a new script and paste the below code into it:\n```csharp\nusing System;\nusing Zenvin.Settings.Framework;\n\npublic class DropdownSetting : SettingBase\u003cint\u003e\t // declare custom Setting type\n{\n\t[SerializeField] private string[] values;\t   // expose field in the editor to allow assigning dropdown values\n}\n```\nAfter you let Unity recompile, the new Setting type should show up in your create setting context menu.\n\n## 2. Clamping a Setting's value\nAssume you have the class from **Example 1**, and now you would like to make sure your Setting's `CurrentValue` does not go out of the `values`' bounds.\n\\\nAll you need to do to achieve this, is `override` the `ProcessValue` method like this:\n```csharp\nprotected override void ProcessValue(ref int value)\n{\n\tvalue = Mathf.Clamp (value, 0, values.Length - 1);\n}\n```\n\n## 3. Loading external Settings on runtime\nFirst, create factories for your custom Setting types. For the class from **Example 1**, this could look somewhat as follows:\n```csharp\npublic class DropdownSettingFactory : ISettingFactory\n{\n\tstring ISettingFactory.GetDefaultValidType() =\u003e \"dropdown\";\t // make default type string \"dropdown\"\n\t\n\tSettingBase ISettingFactory.CreateSettingFromValue(string defaultValue, StringValuePair[] values)\n\t{\n\t\tif (!int.TryParse(defaultValue, out int val)) {\t // try parsing the json default value to an int\n\t\t\tval = 0;\t// if not possible, use 0 as default\n\t\t}\n\t\treturn DropdownSetting.CreateInstanceWithValues\u003cDropdownSetting\u003e(val, values);  // create a new instance.\n\t}\n}\n```\nThe above factory can create an instance of `DropdownSetting`. By default, it will respond to the json type string `\"dropdown\"`.\nNote that the factory uses `SettingBase\u003cT\u003e.CreateInstanceWithValues`, rather than [`ScriptableObject.CreateInstance`](https://docs.unity3d.com/ScriptReference/ScriptableObject.CreateInstance.html). This is necessary, because the Setting needs to be initialized. Setting instances created with the latter method will not be considered during loading.\n\\\n\\\nNext, make a `MonoBehaviour` to initialize your Settings Asset and load Settings using the `Zenvin.Settings.Loading.RuntimeSettingLoader` class:\n```csharp\nusing UnityEngine;\nusing Zenvin.Settings.Framework;\nusing Zenvin.Settings.Loading;\n\npublic class SettingsInitializer : MonoBehaviour\n{\n\t[SerializeField] private SettingsAsset asset;\n\t[SerializeField, TextArea (10, 10)] private string json;  // this is for the JSON string you want to load\n\t\n\tprivate void Start ()\n\t{\n\t\tSettingsAsset.OnInitialize += OnInitialize; // static event, hence the SettingAsset parameter\n\t\tasset.Initialize();\n\t}\n\t\n\tprivate void OnInitialize (SettingsAsset asset)\n\t{\n\t\tvar options = new SettingLoaderOptions (asset)\t\t\t\t\t\t  // initialize options object with the target asset\n\t\t\t.WithData (json)\t\t\t\t\t\t\t\t\t\t\t\t\t// set the options' data from the json string \n\t\t\t.WithSettingFactory (\"bool\", new BoolSettingFactory ())\t\t\t // add factories provided by the package\n\t\t\t.WithSettingFactory (\"int\", new IntSettingFactory ())\t\t\t   // for the Int and Bool factories, the \"type\" they are used for will be overwritten\n\t\t\t.WithSettingFactory (new FloatSettingFactory ())\t\t\t\t\t// for the Float factory, its default \"type\" value will be used\n\n\t\t\t.WithSettingFactory (\"dropdown\", new DropdownSettingFactory ());\t// add the factory we created earlier\n\n\t\tRuntimeSettingLoader.LoadSettingsIntoAsset (options);   // load settings into the asset, using the options created above\n\t}\n}\n```\nNote that the `LoadSettingsIntoAsset` method can override individual factories' target types. This allows using the same factory for multiple types of Settings.\n\\\nLast, create a JSON string for the Settings you want to load and assign it to that `MonoBehaviour`, along with the Settings Asset.\nSuch a JSON string could look like this:\n```json\n{\n\t\"Groups\": [\n\t\t{\n\t\t\t\"GUID\": \"_graphics\",\n\t\t\t\"Name\": \"Graphics\",\n\t\t\t\"LocalizationKey\": \"\",\n\t\t\t\"ParentGroupGUID\": \"\",\n\t\t\t\"IconResource\": \"\"\n\t\t}\n\t],\n\t\"Settings\": [\n\t\t{\n\t\t\t\"GUID\": \"anti_aliasing\",\n\t\t\t\"Name\": \"Anti-Aliasing\",\n\t\t\t\"LocalizationKey\": \"\",\n\t\t\t\"ParentGroupGUID\": \"_graphics\",\n\t\t\t\"Type\": \"dropdown\",\n\t\t\t\"DefaultValue\": \"2\",\n\t\t\t\"Values\": [\n\t\t\t\t{\n\t\t\t\t\t\"Key\": \"\",\n\t\t\t\t\t\"Value\": \"Disabled\"\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"Key\": \"\",\n\t\t\t\t\t\"Value\": \"2x Multisampling\"\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"Key\": \"\",\n\t\t\t\t\t\"Value\": \"4x Multisampling\"\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"Key\": \"\",\n\t\t\t\t\t\"Value\": \"8x Multisampling\"\n\t\t\t\t}\n\t\t\t]\n\t\t}\n\t]\n}\n```\nThis would first try to create a new Group called `Graphics` with GUID `_graphics`, and then to make a Setting from a hypothetical `dropdown` factory, give it a default value of `2` and try to set it up with an array of values. Assuming both were successful, the new Setting would become a child of the new Group.\n\\\nIf there already was a Group with GUID `_graphics`, no new Group will be created, and the Setting will be added to the existing one instead.\n\n## 4. Setting up a dynamic Setting\nSometimes, a default value alone is not enough to set up an external Setting with. Because of that, the `SettingBase\u003cT\u003e` class allows you to override its `OnCreateWithValues(StringValuePair[])` method. Sticking with the class from the previous examples, you could use the `Value`s of all the `StringValuePair`s you get, to populate your `values`.\n\\\nIn code, this can look like this:\n```csharp\nprotected override void OnCreateWithValues (StringValuePair[] _values)\n{\n\tthis.values = new string[_values.Length]; // assign a new array with appropriate length to values\n\tfor (int i = 0; i \u003c values.Length; i++)   // iterate through either array\n\t{\n\t\tvalues[i] = _values[i].Value;\t\t // set content of values\n\t}\n}\n```\n\n## 5. Automatically spawning UI for registered Settings\nThe Framework does not provide a way to do this, but it has a tool to help:\n\\\n`Zenvin.Settings.UI.SettingControlCollection`\n\\\nThis class provides a way to reference `SettingControl` prefabs and get the fitting prefab for any given `SettingBase` sub-class, as long as there is one referenced.\n\\\nBelow is a simple example for how that can be used in a dynamically created settings menu:\n```csharp\nusing Zenvin.Settings.Framework;\nusing Zenvin.Settings.UI;\nusing UnityEngine.UI;\n\npublic class SettingsMenu : MonoBehaviour\n{\n\t[SerializeField] private SettingsAsset asset;   // the asset to source the Settings from\n\t[SerializeField] private SettingControlCollection prefabs;  // a collection of available Setting control prefabs\n\t[SerializeField] private LayoutGroup parent;\t// the layout group to parent the spawned Setting controls to\n\n\n\tprivate void Start ()\n\t{\n\t\tasset.Initialize();\t// initializing Settings could be done somewhere else as well.\n\t\tSpawnSettings();\n\t}\n\n\tprivate void SpawnSettings ()\n\t{\n\t\tvar settings = asset.GetAllSettings();\n\t\tforeach (var setting in settings)   // iterate over all registered Settings\n\t\t{\n\t\t\tif (prefabs.TryGetControl(setting.GetType(), out SettingControl prefab))\t// try get a SettingControl prefab matching the current Setting\n\t\t\t{\n\t\t\t\tif (prefab.TryInstantiateWith (setting, out SettingControl control))\t // try instantiating the found prefab with the given Setting. If successful, this will automatically spawn and initialize the prefab.\n\t\t\t\t{\n\t\t\t\t\tcontrol.transform.SetParent (parent.transform); // make instance a child of the layout group\n\t\t\t\t\tcontrol.transform.localScale = Vector3.one; // reset instance scale, because parenting UI elements likes to mess that up\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n```\nThis could be expanded to utilize the Settings' group structure to implement tabs and/or headers in the menu as well. Have a look into [SettingsMenu.cs](https://github.com/zenvin-dev/UnitySettingsFramework/blob/main/Samples~/Settings%20Menu/Scripts/SettingsMenu.cs) to see how that might work.\n\n## 6. Creating a SettingControl for a specific Setting type\nIn **Example 1**, we implemented a Setting to represent a dropdown. In order to properly display it on UI, a SettingControl is required that can take that Setting's values and represent them.\n\\\nTo achieve this, we first need a way of accessing the `DropdownSetting`'s `values`. A simple way to do this is by adding the following property:\n```csharp\npublic string[] Options =\u003e values; // return the values\n```\nWith that, creating a control for that Setting type is simply a matter of making a new class that inherits `Zenvin.Settings.UI.SettingControl\u003cTControlType, THandledType\u003e` and using either `UnityEngine.UI` or `TMPro.TMP_Dropdown` to actually display the values:\n```csharp\npublic class DropdownControl : SettingControl\u003cDropdownSetting, int\u003e // DropdownSetting is the SettingBase this Control is meant for, and int is the value type ultimately managed by the Setting\n{\n\t[SerializeField] private TMP_Dropdown dropdown;\n\n\tprotected override void OnSetup () {\t// OnSetup is called when the Control is spawned via TryInstantiateWith()\n\t\tdropdown.ClearOptions ();\n\t\tdropdown.AddOptions (new List\u003cstring\u003e (Setting.Options));   // Setting is provided by the base class. It will have the type given in the class declaration, so DropdownSetting in  this case.\n\t\tdropdown.SetValueWithoutNotify (Setting.CurrentValue);\n\t}\n\n\tprotected override void OnSettingValueChanged (SettingBase.ValueChangeMode mode) {  // called whenever the assigned Setting's value changes\n\t\tdropdown?.SetValueWithoutNotify (Setting.CachedValue);  // make sure the dropdown's selection is \"in sync\" with the Setting's value\n\t}\n}\n```\nTo have the dropdown update the Setting's value, you can hook it up to the `SetValue(THandledType)` method provided by `SettingControl\u003cTControlType, THandledType\u003e` - which simply calls `Setting.SetValue(THandledType)` - or implement your own way.\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzenvin-dev%2Funitysettingsframework","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fzenvin-dev%2Funitysettingsframework","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzenvin-dev%2Funitysettingsframework/lists"}