Shared Values

Shared Values are individual variables wrapped in a ScriptableObject. They can be used to represent one value shared between several GameObjects or other ScriptableObjects.

The project already includes Shared Values of different types, like int, float, Boolean, Vector3, Vector2, Quaternion, string, and Color; but you can create custom types by extending the base class (see below).

Sample usages 💡

If you have a lot of prefabs that draw debug gizmos in the scene, a Shared Value can be used in place of a boolean to centralise that debug setting. Instead of having to turn individual Prefab's values on/off, you can now do it from a centralised place.

Another example can be to express some stats related to a character with Shared Values: both the player character and the UI can reference the player's health. When the character gets damage or heals itself, the UI immediately reacts to that.


Using Shared Values

Creating a new Shared Value

To create a Shared Value, simply position your mouse in the Project View and right click, then Create > ScriptableObject Tools > Shared Values, and then choose the type you want to create.

Referencing a Shared Value in scripts

To reference the Shared Value SO, simply declare a variable of its type, like usual:

public SharedInt playerHealth;
// Or also
[SerializeField] private SharedInt _playerHealth;

If visualised in the inspector, you should see the field appear and display its value.

Accessing/writing the value

To use the value contained in a Shared Value SO, all you need to do is reference it and access its .Value property, like so:

int health = _playerHealth.Value;

Alternatively, you can use the SO reference directly to access its value, which will be cast to its inside type:

int health = _playerHealth; // Implicit cast to int
bool isAlive = _playerIsAlive; // Implicit cast to Boolean

However, assignment and other operators like +, +=, -, -= etc. can't be used on the SO directly, but need to be used on its .Value property:

_playerHealth.Value += 2; // This works
_playerHealth += 2; // This doesn't work

To manipulate the data in it, you just add, assign, subtract etc. to its .Value property:

_playerHealth.Value = _playerHealth.Value + (damage * 3f);

The 'AllowIndirectEditing' property

When a Shared Value SO is referenced in a script, it shows its contained property in the Inspector of the script that is referencing it. Using AllowIndirectEditing one can decide whether this value is editable from these Inspectors, or whether to protect it from unwanted edits.

It is off by default, to suggest a workflow where the user of a Shared Value SO has to intentionally go to the SO and edit the value there, reinforcing the idea that they are editing an external value that might be used by other scripts too.

It has no effect at runtime.


Extending Shared Values

Adding a new Shared Value type

To create a new Shared Value class holding a different type, all you need to do is to create a new C-sharp file, and in it, subclass SharedValueBase<T> like this (we'll use Vector4 as an example):

[CreateAssetMenu]
public class SharedVector4 : SharedValueBase<Vector4> { }

Don't forget to include the [CreateAssetMenu] attribute at the top, so you can create a new ScriptableObject using the right-click menu.

Giving it a custom PropertyDrawer

With this, the value is ready to use, however, it won't display using a custom PropertyDrawer like all the others. Using a custom PropertyDrawer is absolutely not needed, but it's a nice thing that can improve usability.

To create one: create a new script in an Editor folder, and put something like this in it:

[CustomPropertyDrawer(typeof(SharedVector4))]
public class SharedVector4Drawer : SharedValueDrawerBase
{
    protected override float GetFieldMaxWidth() => 200f;
}

The important thing is that you specify which class you are providing a PropertyDrawer for (in this case, SharedVector4), and in the GetFieldMaxWidth() method, provide the space you want the property to take when visualised inside a referencing MonoBehaviour or ScriptableObject. This will really depend on the type you are embedding.

Note: This pre-made PropertyDrawer will only work for one-value types. For other types like structs and complex classes, you might have to write a PropertyDrawer from scratch.

For more information on this, refer to the Unity API Reference for PropertyDrawers.

Last updated