Action types
Actions are available since v2.1.0.
Purpose
This reference documents the Action API for creating data-driven, reusable commands. You will find the API reference, implementation patterns, and examples for the ActionSO base classes.
Type overview
| Type | Description |
|---|---|
| ActionSO | Base class for parameterless actions |
| ActionSO<T> | Generic base class for actions with a parameter |
ActionSO
Abstract base class for ScriptableObject-based actions implementing the Command pattern.
Properties
| Property | Type | Description |
|---|---|---|
| Description | string | User-defined description shown in Inspector |
Methods
| Method | Returns | Description |
|---|---|---|
Execute(...) | void | Execute the action (abstract, must override) |
Editor-only properties
| Property | Type | Description |
|---|---|---|
| showInMonitor | bool | Show in Monitor Window during Play Mode |
| showInConsole | bool | Log executions to Console |
Editor-only methods
| Method | Returns | Description |
|---|---|---|
NotifyActionExecuted(CallerInfo) | void | Notify Monitor Window of execution |
LogAction(string) | void | Log action execution to Console |
Editor-only events
| Event | Type | Description |
|---|---|---|
| OnAnyActionExecuted | Action<ActionSO, CallerInfo> | Static event for monitoring |
ActionSO<T>
Generic base class for actions that accept a parameter at execution time.
Methods
| Method | Returns | Description |
|---|---|---|
Execute(T value, ...) | void | Execute with parameter (abstract, must override) |
Execute(...) | void | Execute with default value (calls Execute(default)) |
Implementing ActionSO
Basic implementation without parameters.
Create
using Tang3cko.ReactiveSO;
using UnityEngine;
[CreateAssetMenu(
fileName = "PlaySound",
menuName = "Game/Actions/Play Sound"
)]
public class PlaySoundAction : ActionSO
{
[Header("Settings")]
[SerializeField] private AudioClip clip;
[SerializeField] private float volume = 1f;
public override void Execute(
string callerMember = "",
string callerFile = "",
int callerLine = 0)
{
AudioSource.PlayClipAtPoint(clip, Vector3.zero, volume);
#if UNITY_EDITOR
var callerInfo = new CallerInfo(callerMember, callerFile, callerLine);
NotifyActionExecuted(callerInfo);
LogAction($"Played {clip.name}");
#endif
}
}
Usage
[SerializeField] private ActionSO playSoundAction;
public void OnButtonClick()
{
playSoundAction?.Execute();
}
Implementing ActionSO<T>
Implementation with a parameter.
Create
using Tang3cko.ReactiveSO;
using UnityEngine;
[CreateAssetMenu(
fileName = "SpawnAtPosition",
menuName = "Game/Actions/Spawn At Position"
)]
public class SpawnAtPositionAction : ActionSO<Vector3>
{
[Header("Settings")]
[SerializeField] private GameObject prefab;
public override void Execute(Vector3 position,
string callerMember = "",
string callerFile = "",
int callerLine = 0)
{
Object.Instantiate(prefab, position, Quaternion.identity);
#if UNITY_EDITOR
var callerInfo = new CallerInfo(callerMember, callerFile, callerLine);
NotifyActionExecuted(callerInfo);
LogAction($"Spawned at {position}");
#endif
}
}
Usage
[SerializeField] private ActionSO<Vector3> spawnAction;
public void SpawnEnemy()
{
Vector3 spawnPoint = GetRandomSpawnPoint();
spawnAction?.Execute(spawnPoint);
}
Caller information
Actions automatically track caller information for debugging.
CallerInfo structure
| Field | Type | Description |
|---|---|---|
| MemberName | string | Name of calling method |
| FilePath | string | Full path to calling file |
| LineNumber | int | Line number of call |
Formatted output
// CallerInfo.ToString() returns:
// "FileName.cs:MethodName:42"
Important notes
- Do not pass explicit values to caller parameters
- Let the compiler fill them automatically
- Values are only meaningful when left as defaults
// Good: Let compiler fill caller info
action.Execute();
// Bad: Explicit values lose caller tracking
action.Execute("", "", 0);
Monitor integration
Actions integrate with the Monitor Window for real-time debugging.
Enable monitoring
- Select the action asset in Project window
- In Inspector, enable
Show In Monitor - Open Monitor Window (Window > Reactive SO > Monitor)
- Enter Play Mode and trigger the action
Console logging
- Enable
Show In Consolein Inspector - Call
LogAction(string)in your Execute method - Messages appear in Console during Play Mode
Custom log messages
public override void Execute(...)
{
// Your logic here
#if UNITY_EDITOR
NotifyActionExecuted(new CallerInfo(callerMember, callerFile, callerLine));
LogAction($"Custom message with {details}");
#endif
}
Common patterns
Multiple actions in sequence
public class SequenceAction : ActionSO
{
[SerializeField] private ActionSO[] actions;
public override void Execute(
string callerMember = "",
string callerFile = "",
int callerLine = 0)
{
foreach (var action in actions)
{
action?.Execute();
}
#if UNITY_EDITOR
NotifyActionExecuted(new CallerInfo(callerMember, callerFile, callerLine));
#endif
}
}
Conditional action
public class ConditionalAction : ActionSO
{
[SerializeField] private BoolVariableSO condition;
[SerializeField] private ActionSO trueAction;
[SerializeField] private ActionSO falseAction;
public override void Execute(
string callerMember = "",
string callerFile = "",
int callerLine = 0)
{
if (condition != null && condition.Value)
{
trueAction?.Execute();
}
else
{
falseAction?.Execute();
}
#if UNITY_EDITOR
NotifyActionExecuted(new CallerInfo(callerMember, callerFile, callerLine));
#endif
}
}
Random action
public class RandomAction : ActionSO
{
[SerializeField] private ActionSO[] actions;
public override void Execute(
string callerMember = "",
string callerFile = "",
int callerLine = 0)
{
if (actions.Length > 0)
{
int index = Random.Range(0, actions.Length);
actions[index]?.Execute();
}
#if UNITY_EDITOR
NotifyActionExecuted(new CallerInfo(callerMember, callerFile, callerLine));
#endif
}
}
Best practices
Always wrap editor code
public override void Execute(...)
{
// Runtime logic here
#if UNITY_EDITOR
// Monitoring and logging only in editor
NotifyActionExecuted(new CallerInfo(callerMember, callerFile, callerLine));
LogAction("Details");
#endif
}
Use null-conditional operator
// Safe execution
action?.Execute();
Keep actions focused
One action should do one thing. Compose complex behaviors from simple actions.
Document with description field
Set the description field in Inspector to explain what the action does.
References
- Actions Guide - How to use actions
- Monitor Window - Debug action execution
- Debugging Overview - All debugging tools