# 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:

```csharp
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:

```csharp
int health = _playerHealth.Value;
```

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

```csharp
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:

```csharp
_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:

```csharp
_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):

```csharp
[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:

```csharp
[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](https://docs.unity3d.com/ScriptReference/PropertyDrawer.html).


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://tools.continis.io/scriptable-object-tools/components/sharedvalues.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
