R3 Integration¶
SOAR is designed to be highly extensible with R3 (Reactive Extensions for C#), a modern and feature-rich reactive programming library. When R3 is present in the project, SOAR automatically integrates with it, unlocking a powerful set of features for asynchronous programming, event handling, and data stream manipulation.
This integration enhances SOAR's core features by:
- Exposing
ObservableStreams: SOAR objects likeGameEvents,Variables,Collections, andTransactions expose their events as R3Observablestreams, allowing for complex event processing with LINQ-style operators. - Providing
async/awaitSupport: Awaiting events and transactions becomes seamless withasync/await. - Advanced Concurrency Control: For
Transactions, R3 provides fine-grained control over how concurrent requests are handled.
Enabling the Integration¶
To enable the R3 integration, simply install R3 into the Unity project. SOAR will automatically detect its presence via the SOAR_R3 scripting define symbol, which is typically added by the R3 package installation.
If the SOAR_R3 symbol is not automatically defined, it can be added manually in Project Settings > Player > Other Settings > Scripting Define Symbols.
Core Concepts¶
Observable Streams¶
With R3, most events in SOAR can be treated as Observable streams. This means that powerful R3 operators like Where, Select, Merge, CombineLatest, and Throttle can be used to create sophisticated event-driven logic in a declarative way.
Async/Await Support¶
The integration provides ...Async() methods for many operations, which return a ValueTask or ValueTask<T>. This allows for writing clean and efficient asynchronous code without manual callback management.
Disposables and Lifetime Management¶
All subscriptions to SOAR events (whether through Subscribe() or R3's Observables) return an IDisposable. It is crucial to manage the lifetime of these subscriptions to prevent memory leaks. R3 provides convenient extension methods like AddTo(Component) to automatically dispose of subscriptions when a GameObject is destroyed.
using R3;
using Soar.Events;
using UnityEngine;
public class MyComponent : MonoBehaviour
{
[SerializeField] private GameEvent myGameEvent;
void Start()
{
myGameEvent.AsObservable()
.Subscribe(_ => Debug.Log("Event raised!"))
.AddTo(this); // Automatically disposes when this GameObject is destroyed
}
}