# Runtime Anchors

Runtime Anchors, very similarly to [Shared Values](https://tools.continis.io/scriptable-object-tools/components/sharedvalues), in the sense that they are a value that is encased in a ScriptableObject. The difference with Shared Values is that, while Values are intended to hold a quantity or some identifier set at edit or runtime, Anchors hold a reference to a GameObject or Component that will only be provided in Play Mode.

A Runtime Anchor is always null when the game starts, and some object needs to write its reference into it to make it usable.

Accessing a Runtime Anchor and finding it's null means the object is not present or has been destroyed. By implementing simple null checks, you can create decoupled systems that can rely on objects from other scenes, and are independent from them if they haven't been instantiated.

You can think of Runtime Anchors like a "promise". The object referencing it already has the reference but not the value, but it can rely on the fact that at runtime the value will be provided by some other object.

Runtime Anchors come in two flavours: **individual**, and **sets**. A Runtime Anchor Set is simply a list of Anchors, all contained in one ScriptableObject. See below for usage of both cases.

### Sample usages 💡

A typical use for them is a Runtime Anchor with a reference to a Transform (or another component) that represents the player's character. This allows scripts from other scenes to find the player without having to perform stuff like `FindObjectOfType<>` which only works effectively with components existing in one copy, and is an expensive call anyways.

***

## Individual Runtime Anchors

Individual Runtime Anchors, as opposed to Runtime Anchor Sets, are meant to store only one value.

### Creating a new Runtime Anchor

To create a Runtime Anchor, simply position your mouse in the Project View and right click, then **Create > ScriptableObject Tools > Runtime Anchors**, and then choose the type you want to create.

### Referencing a Runtime Anchor in scripts

To reference the Runtime Anchor SO, simply declare a variable of its type, like usual:

```csharp
public TransformAnchor playerTransform;
```

and assign it using the Inspector.

### Providing a value to a Runtime Anchor

When referencing a Runtime Anchor, providing a value is as simple as calling the `Provide()` method and passing a correct type as an argument:

```csharp
private void Start()
{
    myTransform.Provide(transform);
}
```

This will also notify whoever is watching the Anchor and is listening to the event `OnAnchorProvided`.

### Reading an Anchor's value

To access the value of an Anchor, use its `Value` property, like this:

```csharp
public void Update()
{
    transform.LookAt(playerTransform.Value);
}
```

You can also (and it's good practice) check if the Anchor is null. Instead of doing a null check, you can use its `IsSet` boolean property, which is faster:

```csharp
if(playerTransform.IsSet) transform.LookAt(playerTransform.Value);
```

### Unsetting an Anchor

To correctly remove a value from an Anchor, call its `Unset()` method:

```csharp
myTransform.Unset();
```

There is no protection that prevents other objects to unset an Anchor, because Anchors have no concept of "owner".

Calling `Unset()` also invokes the `OnAnchorUnset` event, so that objects hooked into that can be notified of the change.

### Listening to an Anchor's changes in value

Anchors provide two events to listen to the changes to their value.

* `OnAnchorProvided` is called every time the value of an Anchor changes - but not to a null value.
* `OnAnchorUnset` is called when someone sets the Anchor to null.

***

## Runtime Sets

Runtime Sets are very similar to individual Runtime Anchors, and only differ in that they have additional tools to manage the list of values that is contained within the set. The list can be accessed using `.Values` but is not directly writable, but needs to be manipulated using the set's public methods:

* `AddToSet()`
* `RemoveFromSet()`
* `GetRandomElement()`
* `GetRandomElement(T elementToExclude)`

### Listening to changes in the set's values

Runtime Sets provide three events that objects can listen to:

* `OnElementAdded` is called when an element is added.
* `OnElementRemoved` is called when an element is removed, including if it's the last element.
* `OnSetEmptied` is called only when a set is purposely emptied by calling the method `EmptySet()`.

Note that `OnSetEmptied` is not called when the last element is removed via `OnElementRemoved`, to avoid objects firing both events accidentally.

An object that wants to fire `OnSetEmptied` when the last element is removed can, upon reacting to `OnElementRemoved`, check that the `IsEmpty` property is true, and invoke the code manually.

### When is the list reset

Because ideally many objects might want to add elements to a set, there might be no object in charge of emptying the set when exiting Play Mode. For this reason, `RuntimeAnchorSetBase` inherits from the `ManagedScriptableObject` class. Upon exiting Play Mode, the set will be emptied by the `Reset()` method.

See the [Managed Scriptable Object](https://tools.continis.io/scriptable-object-tools/utilities/managedscriptableobject) page for more info.

***

## Extending Runtime Anchors

### Adding a new individual Runtime Anchor type

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

```csharp
[CreateAssetMenu]
public class TransformAnchor : RuntimeAnchorBase<Rigidbody> { }
```

Nothing else is needed.

### Adding a new Runtime Set type

Similarly to individual Anchors, a new set can be added by just declaring a new class inheriting from `RuntimeAnchorSetBase<T>`:

```csharp
[CreateAssetMenu]
public class RigibodyAnchorSet : RuntimeAnchorSetBase<Rigidbody> { }
```
