# Table of Contents - [Scriptable Variable | Soap - 3.5.1](#scriptable-variable-soap-3-5-1) - [Where to get Soap? | Soap - 3.5.1](#where-to-get-soap-soap-3-5-1) - [Why use Soap? | Soap - 3.5.1](#why-use-soap-soap-3-5-1) - [Debugging | Soap - 3.5.1](#debugging-soap-3-5-1) - [Scriptable List | Soap - 3.5.1](#scriptable-list-soap-3-5-1) - [Properties | Soap - 3.5.1](#properties-soap-3-5-1) - [Properties | Soap - 3.5.1](#properties-soap-3-5-1) - [FAQ | Soap - 3.5.1](#faq-soap-3-5-1) - [Runtime Variables | Soap - 3.5.1](#runtime-variables-soap-3-5-1) - [Bindings | Soap - 3.5.1](#bindings-soap-3-5-1) - [Properties | Soap - 3.5.1](#properties-soap-3-5-1) - [Callbacks | Soap - 3.5.1](#callbacks-soap-3-5-1) - [Variable Reference | Soap - 3.5.1](#variable-reference-soap-3-5-1) - [Scriptable Event | Soap - 3.5.1](#scriptable-event-soap-3-5-1) - [FAQ | Soap - 3.5.1](#faq-soap-3-5-1) - [Debugging | Soap - 3.5.1](#debugging-soap-3-5-1) - [FAQ | Soap - 3.5.1](#faq-soap-3-5-1) - [Event Listener | Soap - 3.5.1](#event-listener-soap-3-5-1) - [Properties | Soap - 3.5.1](#properties-soap-3-5-1) - [Dynamic Binding | Soap - 3.5.1](#dynamic-binding-soap-3-5-1) - [FAQ | Soap - 3.5.1](#faq-soap-3-5-1) - [Callbacks | Soap - 3.5.1](#callbacks-soap-3-5-1) - [Scriptable Enum | Soap - 3.5.1](#scriptable-enum-soap-3-5-1) - [FAQ | Soap - 3.5.1](#faq-soap-3-5-1) - [FAQ | Soap - 3.5.1](#faq-soap-3-5-1) - [Accessing SubAssets | Soap - 3.5.1](#accessing-subassets-soap-3-5-1) - [Scriptable Dictionary | Soap - 3.5.1](#scriptable-dictionary-soap-3-5-1) - [Creating Soap ScriptableObjects | Soap - 3.5.1](#creating-soap-scriptableobjects-soap-3-5-1) - [Scriptable SubAssets | Soap - 3.5.1](#scriptable-subassets-soap-3-5-1) - [Creating/Deleting SubAssets | Soap - 3.5.1](#creating-deleting-subassets-soap-3-5-1) --- # Scriptable Variable | Soap - 3.5.1 [PreviousWhere to get Soap?](/soap/getting-started/where-to-get-soap) [NextProperties](/soap/soap-core-assets/scriptable-variable/properties) Last updated 5 months ago A Scriptable Variable (SV) is a scriptable object of a specific type containing a value and other parameters. Here is an example of a FloatVariable: ![](https://obvious-game.gitbook.io/~gitbook/image?url=https%3A%2F%2Flh7-rt.googleusercontent.com%2Fdocsz%2FAD_4nXcTrWFeez2X9omNKTUyCHmBE33DLta-2LblKNagiTYU9EaeN1r_qvMWM_OhTRQyBzIsWxa1UgolSGbLLon_YMW24fMTBnbCqiGAuWseMmgcsLF2KJct5Zkh4v53DvKmbSKe8KT2TbZOAU6xMrsO63_fWZU%3Fkey%3DN4RcKQrHpqe_tYkdKbHJhg&width=768&dpr=4&quality=100&sign=c38a258&sv=2) --- # Where to get Soap? | Soap - 3.5.1 Currently, you can purchase **Soap** through two different platforms: 1. [**Unity Asset Store**](https://assetstore.unity.com/packages/tools/utilities/soap-scriptableobject-architecture-pattern-232107?aid=1100lACyq) **(Next Sale from April 17 2025 to May 08 2025)** Buying through the Unity Asset Store allows you to update Soap directly from the Unity editor, making it a convenient option. When the asset is on sale, it’s a great deal; however, Unity controls the timing of sales, and they take a 30% commission on each purchase. Additionally, updates can take up to **three days** to be approved and uploaded to the store. 1. [**Itch.io**](https://obvious-game.itch.io/soap) **(Next Sale from March 16 2025 to March 31 2025)** Purchasing through **Itch.io** better supports me, as the platform only takes a 5% commission. However, updating requires downloading the latest version on Itch and importing it into your project—making it less convenient than the Unity route. On the plus side, updates are instant, giving you access to new versions of Soap much faster. [PreviousWhy use Soap?](/soap/getting-started/why-use-soap) [NextScriptable Variable](/soap/soap-core-assets/scriptable-variable) Last updated 13 days ago --- # Why use Soap? | Soap - 3.5.1 1. ### [](#solve-dependencies-through-the-editor) Solve dependencies through the editor By utilizing scriptable objects at its core, it prevents your code from becoming coupled (spaghetti code). This is especially true in the casual mobile market for several reasons: * Many features are enabled or disabled through independent A/B Tests. This can lead to hardcoded or messy code within the core of our game. Having these features 'hooked' into an independent architecture makes it easy to add, remove, or toggle them on and off. * Soap enables you to reuse features more easily. By using Soap, you can create features as 'drag and drop,' which can be a huge time saver in the long run for elements that don’t change much across games (like meta features, ability systems, etc.). 1. ### [](#increase-development-speed) Increase Development Speed * Avoid creating new classes for straightforward behaviors. * Directly access key variables using a simple reference. * Modify global variables from the editor or within the code. * Maintain persistent data across scenes or play sessions. * Effortlessly debug at runtime. 1. ### [](#code-efficiency-clarity) Code Efficiency / Clarity * Subscribe to what you need and have each class handle itself. * Avoid useless managers. * Reduce code complexity (by preventing spaghetti code) * Performant Finally, because it's fun. Once you start developing with Soap, you might realize that the workflow is more enjoyable. It is not for everyone, but people who like this kind of workflow will love Soap. [PreviousWhat is Soap?](/soap) [NextWhere to get Soap?](/soap/getting-started/where-to-get-soap) Last updated 5 months ago --- # Debugging | Soap - 3.5.1 [PreviousProperties](/soap/soap-core-assets/scriptable-variable/properties) [NextVariable Reference](/soap/soap-core-assets/scriptable-variable/variable-reference) Last updated 5 months ago When you are in play mode, the objects (and their components) that have registered for the OnValueChanged Event of a Scriptable Variable become visible in the inspector. As seen in the screenshot above, three objects are registered to this variable. Examining the first element that responds to this variable, we find the GameObject named 'HealthText' in the hierarchy, specifically its component 'BindTextMeshPro.' By clicking, the object is pinged in the hierarchy. Double-clicking will select the object in the hierarchy. This visual debugging is useful for tracking what responds to the changes of your variable. For more detailed explanation and examples of Scriptable Variables, please refer to the example scene '1\_ScriptableVariables\_Example\_Scene' and its [documentation](/soap/scene-documentation/1_scriptablevariables) . ![](https://obvious-game.gitbook.io/~gitbook/image?url=https%3A%2F%2F1391552916-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FWqhD9b0UbiZjyC9B8azX%252Fuploads%252FW4rrSRmenWnG5kb2wGAB%252Fimage.png%3Falt%3Dmedia%26token%3D3feaf9ec-9f89-4e10-80b8-96ae2ef5d9e0&width=768&dpr=4&quality=100&sign=f2738aa0&sv=2) --- # Scriptable List | Soap - 3.5.1 [PreviousBindings](/soap/soap-core-assets/bindings) [NextProperties](/soap/soap-core-assets/scriptable-list/properties) Last updated 1 month ago A Scriptable Lists (SL) is a scriptable object of a specific type containing a list of objects. SL can be useful to solve dependencies by avoiding the need to have a “manager” in between your classes. ![](https://obvious-game.gitbook.io/~gitbook/image?url=https%3A%2F%2Flh7-rt.googleusercontent.com%2Fdocsz%2FAD_4nXeo-GeCYR0wxKu0bfxa8ZaJV6ZpZH18IlylvKEvBiWRT0JInxZGnVSEktsrutbJ3_O8Zj5z2WMDwdMtfdn16t5UGD-1bDVuWMvIoKmj-bhLFGxNJ8VwFgIhT5FVFwwyRyRc7r-mjyT-voniUIhKRSVzUIQb%3Fkey%3DN4RcKQrHpqe_tYkdKbHJhg&width=768&dpr=4&quality=100&sign=1d7d0dbd&sv=2) --- # Properties | Soap - 3.5.1 [PreviousScriptable Variable](/soap/soap-core-assets/scriptable-variable) [NextDebugging](/soap/soap-core-assets/scriptable-variable/debugging) Last updated 5 months ago Let’s go through its properties, starting from the Header: * **Description**: Add/edit an optional description to your SV * **Tag**: Makes it easier to filter in the Soap Wizard. * **Value**: the current value of the variable. Can be changed in inspector, at runtime, by code or in unity events. Changing the value will trigger an event “OnValueChanged” that can be registered to by code. See examples for practical usage. * **PreviousValue**: the previous value of the variable. Accessible only via code. (not visible in the inspector) * **Debug Log Enabled**: if true, will log in the console whenever this value is changed. * **Saved**: If true, the value of the variable will be saved to Player Prefs when it changes. (See 1\_ScriptableVariables\_Example scene & documentation). * _**Default Value**_: Default value used the first time you load from PlayerPrefs. * _**Save Guid:**_ by default, a unique Guid is created for the variable. In case you want to override it, change this setting to Manual and assign your own custom Guid. * **Reset On:** when is this variable reset (or loaded, if saved)? * _**Scene Loaded:**_ whenever a scene is loaded. Use this if you want the variable to be reset if it is only used in a single scene. Note: does not reset when loading additive scenes. * _**Application Start**_: reset once when the game starts. Useful if you want changes made to the variable to persist across scenes. * _**None**_: will not reset(useful for [Runtime Variables](/soap/soap-core-assets/scriptable-variable/runtime-variables) ) * **Is Clamped**: only for FloatVariable and IntVariable, gives you the ability to clamp its value. (See [1\_ScriptableVariables Documentation](/soap/scene-documentation/1_scriptablevariables) ). In the Editor, non-saved Scriptable Variables automatically revert to their initial values (the values shown in the inspector before entering play mode) upon exiting play mode. Additionally, there is a convenient utility button labeled 'Reset to Initial Value.' This allows you to quickly reset the variable to its initial value from the inspector. ![](https://obvious-game.gitbook.io/~gitbook/image?url=https%3A%2F%2Flh7-rt.googleusercontent.com%2Fdocsz%2FAD_4nXcTrWFeez2X9omNKTUyCHmBE33DLta-2LblKNagiTYU9EaeN1r_qvMWM_OhTRQyBzIsWxa1UgolSGbLLon_YMW24fMTBnbCqiGAuWseMmgcsLF2KJct5Zkh4v53DvKmbSKe8KT2TbZOAU6xMrsO63_fWZU%3Fkey%3DN4RcKQrHpqe_tYkdKbHJhg&width=768&dpr=4&quality=100&sign=c38a258&sv=2) --- # Properties | Soap - 3.5.1 [PreviousScriptable List](/soap/soap-core-assets/scriptable-list) [NextCallbacks](/soap/soap-core-assets/scriptable-list/callbacks) Last updated 5 months ago Let’s go through its properties: * **Reset On**: when is this list cleared? * _**Scene Loaded**_: whenever a scene is loaded. Ignore Additive scene loading. * _**Application Start**_: when the game starts. * _**None**_: does not clear * **List content**: in play mode, you can see all the elements that populate the list. For more detailed explanation and examples of Scriptable Lists, please refer to the example scene '3\_ScriptableLists\_Example\_Scene' and its [documentation](/soap/scene-documentation/3_scriptablelists) . ![](https://obvious-game.gitbook.io/~gitbook/image?url=https%3A%2F%2Flh7-rt.googleusercontent.com%2Fdocsz%2FAD_4nXeo-GeCYR0wxKu0bfxa8ZaJV6ZpZH18IlylvKEvBiWRT0JInxZGnVSEktsrutbJ3_O8Zj5z2WMDwdMtfdn16t5UGD-1bDVuWMvIoKmj-bhLFGxNJ8VwFgIhT5FVFwwyRyRc7r-mjyT-voniUIhKRSVzUIQb%3Fkey%3DN4RcKQrHpqe_tYkdKbHJhg&width=768&dpr=4&quality=100&sign=1d7d0dbd&sv=2) --- # FAQ | Soap - 3.5.1 [](#it-seems-like-you-might-need-to-have-every-individual-variable-be-its-own-scriptable-object-so-for-5) **It seems like you might need to have every individual variable be its own scriptable object, so for 50 enemies, each enemy’s HP would be 50 different scriptable variables?** ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Yes. If you don’t want to create the variables beforehand, you can instantiate Scriptable variables at runtime containing the HP and pass it as a reference to your different systems (see [Runtime Variables](/soap/soap-core-assets/scriptable-variable/runtime-variables) and [Runtime Injectors](/soap/soap-core-assets/runtime-injectors) ). However, maybe that is not the best approach. Scriptable variables are best for things that have dependencies with other systems but are singular. It suits more for things like Player HP or a Boss HP as well. For many enemies maybe it's overkill. Most of the time, if there are a lot of enemies, you don’t really want or need to solve dependency with their individual stats. Instead, the most common use case is to create a [Scriptable List](/soap/soap-core-assets/scriptable-list) of enemies that you can reference anywhere (solving most of your dependencies) and access their stats there. [](#onvaluechanged-is-not-raised-when-i-modify-one-field-of-my-custom-c-class-how-can-raise-it) OnValueChanged is not raised when I modify one field of my custom C# Class, how can raise it? -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- If you create the following class: Copy [System.Serializable] public class Stats { float Speed; int Damage; } And you create a Scriptable Variable of that class: Copy [CreateAssetMenu(menuName = "Examples/StatsVariable"))] public class StatsVariable : ScriptableVariable { } You might expect that modifying any of the fields (e.g., `Speed` or `Damage`) would trigger the `OnValueChanged` event. However, by default, this does **not** happen. This is because **Scriptable Variables check for reference equality**, meaning the event is only triggered when the reference itself changes, not when fields inside the object are modified. **Solution: Implement** `**IEquatable**` To make this work, your class should implement the `IEquatable` interface. This allows the system to detect changes at the field level rather than relying solely on reference equality. Here’s how you can modify your `Stats` class: Copy [System.Serializable] public class Stats : IEquatable { float Speed; int Damage; public bool Equals(Stats other) { if (ReferenceEquals(this, other)) { return this.Speed == other.Speed && this.Damage == other.Damage; } return false; } } Now, when you register for the `OnValueChanged` event, changes to individual fields will now trigger the event: Copy [SerializeField] private StatsVariable _stats; private void Start() { _stats.OnValueChanged += OnStatsChanged; _stats.Value.Speed += 1; //This will trigger OnValueChanged now! _stats.Value = new Stats { Speed = 1, Damage = 1 }; //This too! } private void OnStatsChanged(Stats value) { Debug.Log($"Stats changed: Speed = {value.Speed}, Damage = {value.Damage}"); } private void OnDestroy() { _stats.OnValueChanged -= OnStatsChanged; } [PreviousRuntime Variables](/soap/soap-core-assets/scriptable-variable/runtime-variables) [NextBindings](/soap/soap-core-assets/bindings) Last updated 20 days ago --- # Runtime Variables | Soap - 3.5.1 In some cases, you might want to still enjoy the benefits of Scriptable Variables (like the OnValueChanged event system) without having to create the assets in the project beforehand. For example, let’s imagine you want to have multiple enemies, each with a health bar. You want to use a generic health component and a generic health bar connected by a Scriptable Variable float (health). In those cases, you could create Scriptable Variables at runtime. The concept is simple: instead of already referencing the Scriptable Variable in the components, you create it in Awake() or Start() using the SoapUtils static method CreateRuntimeInstance: Copy private void Awake() { //If the variable is not set in the inspector, create a runtime instance. if (_runtimeHpVariable == null) _runtimeHpVariable = SoapUtils.CreateRuntimeInstance($"{gameObject.name}_Hp"); } Once the variable instance is created, you can pass it to your different components, either using an event system or directly calling a method if the components are in the same context (scene or prefab). For a practical example of how to use runtime variables, please refer to the '8\_RuntimeVariables\_Examples\_Scene' in the Example scene and its accompanying [documentation](/soap/scene-documentation/8_runtimevariables) . Note: I have done this myself in a few games in the past, but each game is different. Make sure to assess if this pattern fits your game. This is a more advanced pattern, and as such, I would not recommend it for people who have just started using Soap. There are other ways to solve the same issue. [PreviousVariable Reference](/soap/soap-core-assets/scriptable-variable/variable-reference) [NextFAQ](/soap/soap-core-assets/scriptable-variable/faq) Last updated 5 months ago --- # Bindings | Soap - 3.5.1 [PreviousFAQ](/soap/soap-core-assets/scriptable-variable/faq) [NextScriptable List](/soap/soap-core-assets/scriptable-list) Last updated 5 months ago Bindings are components attached to GameObjects, enabling them to bind to a scriptable variable and execute a simple behavior when the variable's value changes. They are designed to save time, eliminating the need to create a script for minor adjustments like changing color, text, image, and other elements. For a comprehensive understanding of how to use Bindings and their benefits, please refer to the '2\_Bindings\_Examples\_Scene' in the Example scene and its accompanying [documentation](/soap/scene-documentation/2_bindings) . Example: BindTextMeshPro ![](https://obvious-game.gitbook.io/~gitbook/image?url=https%3A%2F%2Flh7-rt.googleusercontent.com%2Fdocsz%2FAD_4nXeAt_9EXCP9i3ogoJ6W4DsZbAkONssqSMSzf5H24ZQPk9VSHc3KlcKse_IZP78jxw0D17Nj9i5v8yhZ28kmupUNW5fzlpn8MrZh6GdCdFdbT-_OZ8YIdUoHO9L3axdbzG0pCQNoOirREGKn1EldROHzLZL6%3Fkey%3DN4RcKQrHpqe_tYkdKbHJhg&width=768&dpr=4&quality=100&sign=b9b9e4c8&sv=2) --- # Properties | Soap - 3.5.1 [PreviousScriptable Event](/soap/soap-core-assets/scriptable-event) [NextDebugging](/soap/soap-core-assets/scriptable-event/debugging) Last updated 5 months ago Let’s go through its properties: * **Debug Log Enabled**: If true, will log in the console the methods called when this event is raised (and the gameObject concerned). * **Debug Value**: a value you can input to debug from the inspector * **Raise**: this button is only active during play mode. It enables you to raise the event from the inspector. Events can be raised by code, unity actions or from the inspector(via the raise button). Raising events in the inspector can be useful to quickly debug your game. Please refer to the 4\_ScriptableEvents\_Example\_Scene and its [documentation](/soap/scene-documentation/4_scriptableevents) for a practical understanding of Scriptable Events and how to use them. ![](https://obvious-game.gitbook.io/~gitbook/image?url=https%3A%2F%2Flh7-rt.googleusercontent.com%2Fdocsz%2FAD_4nXcSQORzsBOcstrp_Vbbc-8KC4CzVFqiYOgUcl54wZVX7ZD45N4W2ClNTgkZjQTxVsZvEy5Xpdk-nKsGsc2eH-zSslIUSoCi51RZpHwkzVvSgM4Au710byjr95T6bqPeGDO_8URGTUlNz0udwAs6_wxRqwcc%3Fkey%3DN4RcKQrHpqe_tYkdKbHJhg&width=768&dpr=4&quality=100&sign=5d9eaca8&sv=2) --- # Callbacks | Soap - 3.5.1 The Scriptable List has several events that you can subscribe to by code. 1. OnItemAdded/ OnItemRemoved Sends the item added/removed as an argument. 1. Modified Triggered whenever the list is modified. 1. OnItemsAdded / OnItemsRemoved This event is useful if you don’t want the OnItemAdded/OnItemRemoved event triggered every time you add/remove an item. This will be called once after a range of items have been added/removed. [PreviousProperties](/soap/soap-core-assets/scriptable-list/properties) [NextFAQ](/soap/soap-core-assets/scriptable-list/faq) Last updated 1 month ago --- # Variable Reference | Soap - 3.5.1 [PreviousDebugging](/soap/soap-core-assets/scriptable-variable/debugging) [NextRuntime Variables](/soap/soap-core-assets/scriptable-variable/runtime-variables) Last updated 5 months ago Instead of exposing a reference to a ScriptableVariable, you can use a Variable Reference: Copy public class MyCustomClass : MonoBehaviour { [SerializeField] private FloatReference _floatReference; } A variable reference allows you to choose between a local value or a ScriptableVariable. You might want to use a VariableReference instead of a ScriptableVariable when you aren't sure if you will want to use a ScriptableVariable for a specific variable. For example, I have a script called Car.cs and I want to expose the speed float variable. I'm not sure yet if I want to use a FloatVariable or just a float. Therefore, I can expose a FloatReference. Then in the inspector, if I choose 'Use Local', I can input a value as if it were a normal float. If later I want to access/modify the speed from other classes, I can create a FloatVariable called float\_speed, change to 'Use Variable' in the Car component from the inspector, and drag my new FloatVariable. This can also be useful if you have multiple objects that share the same components. Let’s say you have different cars that share the same Car.cs component. Each AI car can use 'Use Local' with a predefined value, while the player car can 'Use Variable' and have it linked to a FloatVariable, making it flexible. ![](https://obvious-game.gitbook.io/~gitbook/image?url=https%3A%2F%2Flh7-rt.googleusercontent.com%2Fdocsz%2FAD_4nXf8bNS1BP6Y_N2rLoH2WFC7I6YfPhRmmetTS5b_6oxe7Hy8LbJpMwWHiW8RX6lXPRmquQCjMy2tvQoFSqOvYbj4lGhF0oKSJTEBpYMXqQsiGQbH61kMVPoZbGYwr69XTx61gCYES87coytNI47FmoazvLE%3Fkey%3DN4RcKQrHpqe_tYkdKbHJhg&width=768&dpr=4&quality=100&sign=cc6e8a&sv=2) --- # Scriptable Event | Soap - 3.5.1 [PreviousFAQ](/soap/soap-core-assets/scriptable-list/faq) [NextProperties](/soap/soap-core-assets/scriptable-event/properties) Last updated 5 months ago A Scriptable Event (SE) is a scriptable object that can raise events with or without arguments. Using SE enable to register and raise the events from anywhere, which is very useful for debugging. There are two types of scriptable events: 1. Events without parameters 1. Events with parameters ![](https://obvious-game.gitbook.io/~gitbook/image?url=https%3A%2F%2Flh7-rt.googleusercontent.com%2Fdocsz%2FAD_4nXcSQORzsBOcstrp_Vbbc-8KC4CzVFqiYOgUcl54wZVX7ZD45N4W2ClNTgkZjQTxVsZvEy5Xpdk-nKsGsc2eH-zSslIUSoCi51RZpHwkzVvSgM4Au710byjr95T6bqPeGDO_8URGTUlNz0udwAs6_wxRqwcc%3Fkey%3DN4RcKQrHpqe_tYkdKbHJhg&width=768&dpr=4&quality=100&sign=5d9eaca8&sv=2) ![](https://obvious-game.gitbook.io/~gitbook/image?url=https%3A%2F%2Flh7-rt.googleusercontent.com%2Fdocsz%2FAD_4nXe8BXyslNQQEED-KZBgyUZrO0t9eFndxqpKTilm6caXsXIgKaQr5PFSHTmRQPI4l4CmdNX3htVhglQ8zvj7TlnHFXP7dCG7CMGwbE7uTqsTO0IYNuOdO-n7n0jU3JQjwbE9ZkeHBYR-pU7pnxAGFOThwKM_%3Fkey%3DN4RcKQrHpqe_tYkdKbHJhg&width=768&dpr=4&quality=100&sign=263ac58d&sv=2) --- # FAQ | Soap - 3.5.1 [](#can-i-use-a-scriptable-list-just-to-store-data-for-instance-can-i-populate-the-data-in-the-editor-th) Can I use a Scriptable List just to store data? For instance, can I populate the data in the editor, then read this data during gameplay? -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Technically, yes. By setting the reset mode to "None," your Scriptable list will function as data storage. However, this is not the primary intended use of Scriptable Lists; typically, you could achieve this functionality by creating a ScriptableObject that contains a List. Nonetheless, I understand that using Scriptable Lists like this can be convenient, which is why I've added support for this usage. Generally, Scriptable Lists are meant for runtime use, with reset modes set to either SceneLoad or ApplicationStart. They are highly versatile and can store any data type. For example, you could have a script storing positions (using a Scriptable List of Vector3) from a moving object. Another object could then use this stored data to spawn coins at those positions. [PreviousCallbacks](/soap/soap-core-assets/scriptable-list/callbacks) [NextScriptable Event](/soap/soap-core-assets/scriptable-event) Last updated 6 days ago --- # Debugging | Soap - 3.5.1 [PreviousProperties](/soap/soap-core-assets/scriptable-event/properties) [NextFAQ](/soap/soap-core-assets/scriptable-event/faq) Last updated 5 months ago Scriptable events also have their own play mode custom inspector. During play mode, you can inspect all GameObjects that are registered to that event: In editor, if you don’t remember which event calls a method in one of your scripts, you can use the Events Debug Window. You can access it through the menu: Window/Obvious/Soap/Event Debug Window By typing the name of the method in the event debug window, it will search all objects in your scene and find which event calls that method. Note: it is case sensitive. Once the method is found (or not), a message is logged in the console. Clicking on this message will ping the corresponding object in the hierarchy. Additionally, you can click on the debug message to view the stack trace for more detailed information. ![](https://obvious-game.gitbook.io/~gitbook/image?url=https%3A%2F%2Flh7-rt.googleusercontent.com%2Fdocsz%2FAD_4nXcE5XqtzgwjhI1iCFSd6PVchNVC5fCH7ErfmXGxpE2UWulSWGue7YVWUKuQGRvw1MNpDs81oJo5oBTW5h9N4NCvzLLXeDKtepAQlKTbNxx3DiGffYKZRE8Nk-j2d83qH02AgntgLbwt-ibtPGKnp2W7B12q%3Fkey%3DN4RcKQrHpqe_tYkdKbHJhg&width=768&dpr=4&quality=100&sign=e443a99e&sv=2) ![](https://obvious-game.gitbook.io/~gitbook/image?url=https%3A%2F%2Flh7-rt.googleusercontent.com%2Fdocsz%2FAD_4nXcjnPChH-HVZqAY8DaZ9p0mRYUDvuK6zflAdoDoSeBPwk5Yv_w7mqgJ-0aMAbRxb0zqvm4_AZ8D3RDYpSkA8Me6s1Hi3DR5VrFOV7q0vEruG6dEa9wnjs7LPZ9S0a7H8k45r-uzynV2gVN_gZNLyYfDxC9w%3Fkey%3DN4RcKQrHpqe_tYkdKbHJhg&width=768&dpr=4&quality=100&sign=6b271be4&sv=2) ![](https://obvious-game.gitbook.io/~gitbook/image?url=https%3A%2F%2Flh7-rt.googleusercontent.com%2Fdocsz%2FAD_4nXd4YnRVYXBTPx2nEY-2jc3HDF2ocCahB5sH-vbI7ee5hsroti7oCyCnyFmsxpfkseyKv5apwPK6gT77d2sVqshmAQqbOztFbbc5PF4nKotTGMlu2Yu8ujCGtWxubtre0mVPPVN2UKOu38zm18uc_jg3Nfnc%3Fkey%3DN4RcKQrHpqe_tYkdKbHJhg&width=768&dpr=4&quality=100&sign=874b9de&sv=2) --- # FAQ | Soap - 3.5.1 [](#when-should-i-use-a-scriptable-event-or-a-scriptable-variable) When should I use a Scriptable Event or a Scriptable Variable? -------------------------------------------------------------------------------------------------------------------------------------- It’s not a black or white answer. The more you use SOAP, the clearer it becomes when to choose one approach over the other. Until then, I can provide a few examples for each use case. These examples are helpful, but they are not the only way. Everyone has their own preferences, and sometimes you might feel like using a different solution for a specific task. Scriptable Variables are mostly useful for solving dependencies of a single element (or global variable) across different parts of the game: \- Player (and anything related to it, like its stats) \- Settings (volume, quality, options, etc.) \- Score, Coins, Level Index \- Boss (and anything related to it, like its stats) \- Game States (TutorialComplete, QuestXCompleted) Scriptable Events are mostly useful for communicating indirectly with other components: \- OnPlayerDamaged(int damageAmount), OnPlayerDeath \- OnLevelCompleted(int levelIndex) \- OnCoinsCollected(int amount of Coins) \- OnPowerUpCollected(Vector3 position) - to spawn a VFX at that location Personally, I use Scriptable Events for UI and for visual feedback (camera shake, VFX, sound, etc.). Many developers use them for game logic as well, but I prefer to keep that in code and use static events or an event bus because I find it easier to track down game flow through code. Another example: If you want to show the score in the UI (using TextMeshPro). Should you use a Scriptable variable or a scriptable event? You can use both but I would choose to bind to a scriptable variable. For this, use the BindTextMeshPro Component. Attach that to the TextMeshPro GameObject and the text will refresh every time the value of the variable changes. [PreviousDebugging](/soap/soap-core-assets/scriptable-event/debugging) [NextEvent Listener](/soap/soap-core-assets/event-listener) Last updated 5 months ago --- # Event Listener | Soap - 3.5.1 [PreviousFAQ](/soap/soap-core-assets/scriptable-event/faq) [NextProperties](/soap/soap-core-assets/event-listener/properties) Last updated 5 months ago An Event Listener is a component that let's you register to Scriptable Events and invoke a Unity Action. without code. Simply attach an Event Listener component (of the same type as your SE) to your GameObject. ![](https://obvious-game.gitbook.io/~gitbook/image?url=https%3A%2F%2Flh7-rt.googleusercontent.com%2Fdocsz%2FAD_4nXcHYK6iiyGHO4Hb6ChcPz1q1hUXLVDaDACdOylRNQxfyAbc0dEe_zMcW2U0wLIhkVCJJe1D5qWVtXiWMB3Y8o2mJqF88hCFge8cDgy4Vjx225G111m2Zme4VpE3Q3VkB26O2-WgUnEXx67c-iG1Ylg8APDm%3Fkey%3DN4RcKQrHpqe_tYkdKbHJhg&width=768&dpr=4&quality=100&sign=5819b979&sv=2) --- # Properties | Soap - 3.5.1 [PreviousEvent Listener](/soap/soap-core-assets/event-listener) [NextDynamic Binding](/soap/soap-core-assets/event-listener/dynamic-binding) Last updated 5 months ago Let’s go through its properties: * **Binding**: * _**Until\_Destroy**_: will register in Awake() and unsubscribe OnDestroy(). * _**Until\_Disable**_: will register OnEnable() and unsubscribe OnDisable(). * **Disable after subscribing**: if true, will deactivate the GameObject after registering to the event. Useful for UI elements. * **Event responses:** each response invoked after the event was raised. * _**Delay**_: a delay in seconds before the response is invoked * _**Scriptable Event**_: the event to listen to * _**Response**_: unity actions triggered You can also register to events directly from code (via the OnRaised action). ![](https://obvious-game.gitbook.io/~gitbook/image?url=https%3A%2F%2Flh7-rt.googleusercontent.com%2Fdocsz%2FAD_4nXcHYK6iiyGHO4Hb6ChcPz1q1hUXLVDaDACdOylRNQxfyAbc0dEe_zMcW2U0wLIhkVCJJe1D5qWVtXiWMB3Y8o2mJqF88hCFge8cDgy4Vjx225G111m2Zme4VpE3Q3VkB26O2-WgUnEXx67c-iG1Ylg8APDm%3Fkey%3DN4RcKQrHpqe_tYkdKbHJhg&width=768&dpr=4&quality=100&sign=5819b979&sv=2) --- # Dynamic Binding | Soap - 3.5.1 [PreviousProperties](/soap/soap-core-assets/event-listener/properties) [NextFAQ](/soap/soap-core-assets/event-listener/faq) Last updated 5 months ago When using an EventListener with a parameter, make sure you bind it to the Dynamic method and not the static method ! Otherwise you won’t be able to receive the parameters. For more details and examples, please refer to the [documentation](/soap/scene-documentation/4_scriptableevents) and the scene 4\_ScriptableEvents\_Example\_Scene. ![](https://obvious-game.gitbook.io/~gitbook/image?url=https%3A%2F%2Flh7-rt.googleusercontent.com%2Fdocsz%2FAD_4nXdPk7Aevg7sNLWx6HE-YfdAfH4enGfAgu8Qk3RnGVVNuQkONYRcrKVUx-sBcLLZ2dYizKLffl9-qMPWJ73m92kxNZNruuOZLu2zz9gK106h3hpa-WCSZb1hSamluyz1J6a-i4Pf3Fk6m9bLIVZm1OiRcVu7%3Fkey%3DN4RcKQrHpqe_tYkdKbHJhg&width=768&dpr=4&quality=100&sign=382bcd48&sv=2) --- # FAQ | Soap - 3.5.1 [](#do-i-need-to-use-an-eventlistener-to-receive-messages-from-scriptableevents) Do I need to use an EventListener to receive messages from ScriptableEvents? ------------------------------------------------------------------------------------------------------------------------------------------------------------------ Not necessarily. EventListeners are useful if you want to trigger logic from the inspector using UnityActions. However, if you don’t want to invoke a response through the inspector but rather by code, you can register to the OnRaised method of ScriptableEvents from code. Simply expose a reference to the ScriptableEvent and register / unregister from code. Here is a simple example: Copy using Obvious.Soap; using UnityEngine; public class EnableGameObjectOnEvent : MonoBehaviour { [SerializeField] private ScriptableEventNoParam _scriptableEvent; private void Awake() { _scriptableEvent.OnRaised += OnEventRaised; } private void OnDestroy() { _scriptableEvent.OnRaised -= OnEventRaised; } private void OnEventRaised() { gameObject.SetActive(true); } } [PreviousDynamic Binding](/soap/soap-core-assets/event-listener/dynamic-binding) [NextScriptable Enum](/soap/soap-core-assets/scriptable-enum) Last updated 5 months ago --- # Callbacks | Soap - 3.5.1 The Scriptable Dictionary has several events that you can subscribe to by code. 1. OnItemAdded/ OnItemRemoved Sends the key and value added/removed as an argument. 1. Modified This event is triggered whenever an entry is added, removed or modified. Modifying a dictionary is when you access the value through the key like so: \_dictionary\[Key\] = newValue; or \_dictionary\[Key\] += newValue; [PreviousProperties](/soap/soap-core-assets/scriptable-dictionary/properties) [NextCustom Dictionary Creation](/soap/soap-core-assets/scriptable-dictionary/custom-dictionary-creation) Last updated 1 month ago --- # Scriptable Enum | Soap - 3.5.1 "ScriptableEnums" is a term used when a ScriptableObject is utilized like an enum. Traditionally, enums are used to represent a fixed set of options such as operators (less than, equal, greater than), directions (north, south, east, west), and other categories like damage types (piercing, blunt, magic), teams, behaviors, and so on. In these scenarios, when enums are defined by code, a programmer must edit the code to add, remove, or modify an enum. [PreviousFAQ](/soap/soap-core-assets/event-listener/faq) [NextCreating new Enum Values](/soap/soap-core-assets/scriptable-enum/creating-new-enum-values) Last updated 5 months ago --- # FAQ | Soap - 3.5.1 [](#how-can-i-automatically-save-all-the-scriptable-variables-that-are-sub-assets-of-a-wrapper-so) How can I automatically save all the scriptable variables that are sub-assets of a wrapper SO? ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ Currently, I have not yet implemented a way to automatically save all scriptable variables marked as sub-assets. I am working on a solution, but in the meantime, here are the alternatives: enable “save” on each [scriptable variable](/soap/soap-core-assets/scriptable-variable) sub-asset individually or implement your own custom save/load method in the scriptable object wrapper. You can also use the [Scriptable Save](/soap/soap-core-assets/scriptable-save) if you just want to have all the data in a single file. [PreviousAccessing SubAssets](/soap/soap-core-assets/scriptable-subassets/accessing-subassets) [NextScriptable Save](/soap/soap-core-assets/scriptable-save) Last updated 5 months ago --- # FAQ | Soap - 3.5.1 [](#why-use-a-scriptable-object-for-saving-data) Why use a Scriptable Object for Saving data? -------------------------------------------------------------------------------------------------- The convenient aspects of having a save wrapped in a SO are that: 1. You can see the save content anytime in the inspector 2. You can reference the save in any components of your game 3. You can create and expose convenient methods 4. You can modify the save at runtime for debug purpose [PreviousProperties](/soap/soap-core-assets/scriptable-save/properties) [NextScriptable Dictionary](/soap/soap-core-assets/scriptable-dictionary) Last updated 5 months ago --- # Accessing SubAssets | Soap - 3.5.1 The \[SubAsset\] attribute can only be used on Soap SOs referenced in wrappers of type ScriptableObjects (or classes inheriting from SOs). You can access a particular sub-asset in two different ways: 1. The same way as any other SO, by exposing a reference and dragging a specific instance. Example: expose a reference to a FloatVariable and then select the \_speed FloatVariable. 2. By exposing a reference to the wrapper (PlayerStats) and accessing it through that. Example: playerStats.Health.Add(10). For more details and examples, please refer to the [documentation](/soap/scene-documentation/7_scriptablesubassets) and the scene 7\_ScriptableSubAssets\_Example\_Scene. [PreviousCreating/Deleting SubAssets](/soap/soap-core-assets/scriptable-subassets/creating-deleting-subassets) [NextFAQ](/soap/soap-core-assets/scriptable-subassets/faq) Last updated 5 months ago --- # Scriptable Dictionary | Soap - 3.5.1 [PreviousFAQ](/soap/soap-core-assets/scriptable-save/faq) [NextProperties](/soap/soap-core-assets/scriptable-dictionary/properties) Last updated 1 month ago A Scriptable Dictionary (SD) is a scriptable object that can hold serialized Key and Values. You can customize the type of the Key and the value to the needs of your game. ![](https://obvious-game.gitbook.io/~gitbook/image?url=https%3A%2F%2F1391552916-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FWqhD9b0UbiZjyC9B8azX%252Fuploads%252FQVWv26r5bHIVuoVdAvcB%252Fimage.png%3Falt%3Dmedia%26token%3Daf5155c8-aebc-4365-a810-1729b1e4c853&width=768&dpr=4&quality=100&sign=6134023b&sv=2) --- # Creating Soap ScriptableObjects | Soap - 3.5.1 There are several ways to create a new instance of a Soap ScriptableObject. 1. Use the [Soap Asset Creator](/soap/custom-windows/soap-asset-creator) 2. From the ["Create" button shortcut](/soap/useful-tips/creating-soap-scriptableobjects/from-create-shortcut) 3. Using the default [Unity Create Menu](/soap/useful-tips/creating-soap-scriptableobjects/default-unity-create-menu) [PreviousRuntime Injectors](/soap/soap-core-assets/runtime-injectors) [NextSoap Asset Creator](/soap/useful-tips/creating-soap-scriptableobjects/soap-asset-creator) Last updated 1 month ago --- # Scriptable SubAssets | Soap - 3.5.1 [PreviousAdding Data](/soap/soap-core-assets/scriptable-enum/adding-data) [NextCreating/Deleting SubAssets](/soap/soap-core-assets/scriptable-subassets/creating-deleting-subassets) Last updated 5 months ago Sometimes, you want to group several scriptable variables, lists, events, or enums together. You can assign them the same Tag (for example, Player) so that you can easily filter them in the Soap Wizard. However, even though this is useful, they still exist as individual assets. For these cases, you can use the \[SubAsset\] attribute to make them children of a specific scriptable object. For example, let’s imagine we want to group all player stats-related scriptable variables under a single SO. We can do it like this: Copy using Obvious.Soap.Attributes; using UnityEngine; namespace Obvious.Soap.Example { [CreateAssetMenu(menuName = "Soap/Examples/SubAssets/PlayerStats")] public class PlayerStats : ScriptableObject { [SerializeField] [SubAsset] private FloatVariable _speed; [SubAsset] public FloatVariable Health; [SubAsset] public FloatVariable MaxHealth; } } The \[SubAsset\] attribute works on \[SerializeField\] private or public Soap SOs. When marking a Soap SO with the \[SubAsset\] attribute, it will be displayed in your scriptable object wrapper like this: ![](https://obvious-game.gitbook.io/~gitbook/image?url=https%3A%2F%2Flh7-rt.googleusercontent.com%2Fdocsz%2FAD_4nXeQrb1urUP1c9oxHXyBFUaEtBgQjXwmxpFwehZIGKbLaiRn6tpfsHiEpPaFan2QYIvpth6oLRiW4Ydc2MNrwEnWg50eSGWwzlwlGs-Xfnq-fdq9FyXR585JrrEXJF5iJGapQ8v6Xb56Ow1zHRrFFJ83Yi8D%3Fkey%3DN4RcKQrHpqe_tYkdKbHJhg&width=768&dpr=4&quality=100&sign=79539be7&sv=2) --- # Creating/Deleting SubAssets | Soap - 3.5.1 [PreviousScriptable SubAssets](/soap/soap-core-assets/scriptable-subassets) [NextAccessing SubAssets](/soap/soap-core-assets/scriptable-subassets/accessing-subassets) Last updated 5 months ago You can create an instance of the sub-asset by clicking the Create button. This will create the Soap SO as a sub-asset of your parent scriptable object. Sub-assets will be prefixed with the following icon: Name. You can delete a specific sub-asset by clicking the X button next to it, or you can delete all the sub-assets by right-clicking the parent SO (or clicking the settings icon): Or by selecting “Delete All SubAssets.” ![](https://obvious-game.gitbook.io/~gitbook/image?url=https%3A%2F%2F1391552916-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FWqhD9b0UbiZjyC9B8azX%252Fuploads%252FocaUcn5jxrSowevBJbcg%252FsubAsset%2520delete.gif%3Falt%3Dmedia%26token%3D073b05df-32f2-492e-883f-1ca259e707f7&width=768&dpr=4&quality=100&sign=f927ef1e&sv=2) ![](https://obvious-game.gitbook.io/~gitbook/image?url=https%3A%2F%2F1391552916-files.gitbook.io%2F%7E%2Ffiles%2Fv0%2Fb%2Fgitbook-x-prod.appspot.com%2Fo%2Fspaces%252FWqhD9b0UbiZjyC9B8azX%252Fuploads%252FtH5Ps3XJBZXvHqYvqjFP%252FsubAsset.gif%3Falt%3Dmedia%26token%3D27db01c4-6ca9-4515-8f5e-523d08f18448&width=768&dpr=4&quality=100&sign=ef8e7178&sv=2) ![](https://obvious-game.gitbook.io/~gitbook/image?url=https%3A%2F%2Flh7-rt.googleusercontent.com%2Fdocsz%2FAD_4nXeU5Z5ls7b0A7Remf8HY5c3ilcVzj1rkESTfHVZ0bA1ZvoqAzgEDHZpwJH3AKUDcqNFifDwVZRdvCteq6CN-CD8rjoELcJd3f959EzNh-SoDdiNriEckYMu5p9U97b9LgcsPIdrwnLNP_K0bQXP_eGbHkdc%3Fkey%3DN4RcKQrHpqe_tYkdKbHJhg&width=768&dpr=4&quality=100&sign=98379fe1&sv=2) ![](https://obvious-game.gitbook.io/~gitbook/image?url=https%3A%2F%2Flh7-rt.googleusercontent.com%2Fdocsz%2FAD_4nXclYyddK6biSVyhmHnlUxHX601WCDfp-zy8nK3z9P_x1ODkK3Y0G6vkzkp4UAP443lgfFnZkj28xOoPUSS95zvwxaCu7Uye98EnxkNCa00vlXZVSmZAJiJpnDQuVFMMkI5SHW0n70T0B_ppzjEN1D_NGgW0%3Fkey%3DN4RcKQrHpqe_tYkdKbHJhg&width=40&dpr=4&quality=100&sign=c1b321dc&sv=2) ![](https://obvious-game.gitbook.io/~gitbook/image?url=https%3A%2F%2Flh7-rt.googleusercontent.com%2Fdocsz%2FAD_4nXe6AM1vNYlN7-N926hV9tHCpSAjvmwOz-2E0AFIkFtEGJuAo5OPfewnYq5Da4sBoYxa5Gi0iq3dVj-SCBBBgr8SuHD88LqrU2kJPeL3peBd7gu0fS81V8eLkcsg2NEWnjW1kn_cyrMUJXrkKLKKMQHVnzJS%3Fkey%3DN4RcKQrHpqe_tYkdKbHJhg&width=768&dpr=4&quality=100&sign=1bfeed5d&sv=2) ---