Skip to main content

Events API Reference

Complete API reference for SoapKit's event system.

Base Classes

GameEvent<T>

The foundation class for all typed events in SoapKit.

[System.Serializable]
public abstract class GameEvent<T> : ScriptableObject, IGameEvent<T>

Properties

PropertyTypeDescription
ListenerCountintNumber of registered listeners
EnableEventHistoryboolWhether to track event history (Editor only)

Methods

MethodParametersDescription
AddListener(UnityAction<T> listener)UnityAction<T> listenerAdds event listener
RemoveListener(UnityAction<T> listener)UnityAction<T> listenerRemoves event listener
Raise(T value)T valueRaises event with typed parameter
RemoveAllListeners()-Removes all registered listeners
RaiseTestEvent()-Context menu method for testing

Editor Properties (Editor Only)

PropertyTypeDescription
EventHistoryList<EventHistoryEntry>Historical event data
EventsRaisedThisFrameintEvents raised in current frame
TotalEventsRaisedlongTotal events raised since startup

Editor Methods (Editor Only)

MethodDescription
ClearEventHistory()Clears event history
GetEventFrequency()Returns events per second

Unit Events

GameEvent

Parameter-less event for simple notifications.

[CreateAssetMenu(menuName = "SoapKit/Events/Unit Event")]
public class GameEvent : ScriptableObject, IGameEvent

Methods

MethodParametersDescription
AddListener(UnityAction listener)UnityAction listenerAdds parameter-less listener
RemoveListener(UnityAction listener)UnityAction listenerRemoves parameter-less listener
Raise()-Raises event without parameters

Usage Example

[SerializeField] private GameEvent onGameStart;
[SerializeField] private GameEvent onPlayerDeath;

private void Start()
{
onGameStart.Raise();
}

private void OnEnable()
{
onPlayerDeath.AddListener(HandlePlayerDeath);
}

private void OnDisable()
{
onPlayerDeath.RemoveListener(HandlePlayerDeath);
}

private void HandlePlayerDeath()
{
// Handle player death
}

Primitive Event Types

BoolGameEvent

Boolean event for state changes and toggles.

[CreateAssetMenu(menuName = "SoapKit/Events/Bool Event")]
public class BoolGameEvent : GameEvent<bool>

Usage Example

[SerializeField] private BoolGameEvent onGamePaused;

private void TogglePause()
{
bool newPauseState = !isPaused;
onGamePaused.Raise(newPauseState);
}

private void OnEnable()
{
onGamePaused.AddListener(OnPauseStateChanged);
}

private void OnPauseStateChanged(bool isPaused)
{
Time.timeScale = isPaused ? 0f : 1f;
}

IntGameEvent

Integer event for scores, counters, and numeric IDs.

[CreateAssetMenu(menuName = "SoapKit/Events/Int Event")]
public class IntGameEvent : GameEvent<int>

Usage Example

[SerializeField] private IntGameEvent onScoreChanged;
[SerializeField] private IntGameEvent onHealthChanged;

private void AddScore(int points)
{
onScoreChanged.Raise(points);
}

private void TakeDamage(int damage)
{
onHealthChanged.Raise(-damage);
}

FloatGameEvent

Float event for values, percentages, and measurements.

[CreateAssetMenu(menuName = "SoapKit/Events/Float Event")]
public class FloatGameEvent : GameEvent<float>

Usage Example

[SerializeField] private FloatGameEvent onVolumeChanged;
[SerializeField] private FloatGameEvent onProgressUpdated;

private void SetMasterVolume(float volume)
{
onVolumeChanged.Raise(volume);
}

private void UpdateProgress(float percentage)
{
onProgressUpdated.Raise(percentage);
}

StringGameEvent

String event for messages, names, and text data.

[CreateAssetMenu(menuName = "SoapKit/Events/String Event")]
public class StringGameEvent : GameEvent<string>

Usage Example

[SerializeField] private StringGameEvent onDialogueSpoken;
[SerializeField] private StringGameEvent onSceneChanged;

private void ShowDialogue(string text)
{
onDialogueSpoken.Raise(text);
}

private void LoadScene(string sceneName)
{
onSceneChanged.Raise(sceneName);
}

Unity Type Events

Vector2GameEvent

2D vector event for positions, UI coordinates, and directions.

[CreateAssetMenu(menuName = "SoapKit/Events/Vector2 Event")]
public class Vector2GameEvent : GameEvent<Vector2>

Usage Example

[SerializeField] private Vector2GameEvent onMouseClicked;
[SerializeField] private Vector2GameEvent onPlayerMoved2D;

private void HandleMouseClick()
{
Vector2 mousePos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
onMouseClicked.Raise(mousePos);
}

Vector3GameEvent

3D vector event for positions, directions, and velocities.

[CreateAssetMenu(menuName = "SoapKit/Events/Vector3 Event")]
public class Vector3GameEvent : GameEvent<Vector3>

Usage Example

[SerializeField] private Vector3GameEvent onPlayerMoved;
[SerializeField] private Vector3GameEvent onObjectSpawned;

private void UpdatePlayerPosition(Vector3 newPosition)
{
onPlayerMoved.Raise(newPosition);
}

private void SpawnObject(Vector3 spawnPoint)
{
onObjectSpawned.Raise(spawnPoint);
}

Vector2IntGameEvent

Integer 2D vector event for grid coordinates and tile positions.

[CreateAssetMenu(menuName = "SoapKit/Events/Vector2Int Event")]
public class Vector2IntGameEvent : GameEvent<Vector2Int>

Usage Example

[SerializeField] private Vector2IntGameEvent onTileSelected;
[SerializeField] private Vector2IntGameEvent onGridMoved;

private void SelectTile(int x, int y)
{
Vector2Int tileCoord = new Vector2Int(x, y);
onTileSelected.Raise(tileCoord);
}

ColorGameEvent

Color event for visual effects and theme changes.

[CreateAssetMenu(menuName = "SoapKit/Events/Color Event")]
public class ColorGameEvent : GameEvent<Color>

Usage Example

[SerializeField] private ColorGameEvent onThemeColorChanged;
[SerializeField] private ColorGameEvent onPlayerColorSelected;

private void ChangeTheme(Color newThemeColor)
{
onThemeColorChanged.Raise(newThemeColor);
}

GameObjectGameEvent

GameObject event for object references and interactions.

[CreateAssetMenu(menuName = "SoapKit/Events/GameObject Event")]
public class GameObjectGameEvent : GameEvent<GameObject>

Usage Example

[SerializeField] private GameObjectGameEvent onObjectInteracted;
[SerializeField] private GameObjectGameEvent onEnemyDefeated;

private void OnTriggerEnter(Collider other)
{
if (other.CompareTag("Interactable"))
{
onObjectInteracted.Raise(other.gameObject);
}
}

TransformGameEvent

Transform event for transform references and spatial data.

[CreateAssetMenu(menuName = "SoapKit/Events/Transform Event")]
public class TransformGameEvent : GameEvent<Transform>

Usage Example

[SerializeField] private TransformGameEvent onTargetChanged;
[SerializeField] private TransformGameEvent onWaypointReached;

private void SetNewTarget(Transform target)
{
onTargetChanged.Raise(target);
}

Advanced Event Patterns

Custom Event Types

Create custom events for complex data structures:

[System.Serializable]
public class PlayerData
{
public string playerName;
public int level;
public Vector3 position;
}

[CreateAssetMenu(menuName = "Game/Events/Player Event")]
public class PlayerDataEvent : GameEvent<PlayerData>
{
[ContextMenu("Raise Test Player Event")]
public override void RaiseTestEvent()
{
var testData = new PlayerData
{
playerName = "TestPlayer",
level = 1,
position = Vector3.zero
};
Raise(testData);
}
}

Event Chains

Chain events for complex workflows:

public class GameFlowManager : MonoBehaviour
{
[Header("Game Flow Events")]
[SerializeField] private GameEvent onGameStart;
[SerializeField] private GameEvent onLevelLoaded;
[SerializeField] private GameEvent onPlayerReady;
[SerializeField] private GameEvent onGameplayStart;

private void OnEnable()
{
onGameStart.AddListener(StartLevel);
onLevelLoaded.AddListener(InitializePlayer);
onPlayerReady.AddListener(BeginGameplay);
}

private void StartLevel() => onLevelLoaded.Raise();
private void InitializePlayer() => onPlayerReady.Raise();
private void BeginGameplay() => onGameplayStart.Raise();
}

Conditional Events

Implement conditional event raising:

public class ConditionalEventRaiser : MonoBehaviour
{
[SerializeField] private BoolVariable canTrigger;
[SerializeField] private IntVariable triggerCount;
[SerializeField] private GameEvent conditionalEvent;

public void TryRaiseEvent()
{
if (canTrigger.Value && triggerCount.Value > 0)
{
conditionalEvent.Raise();
triggerCount.Subtract(1);
}
}
}

Performance Considerations

Listener Management

Efficient Subscription Pattern

public class EfficientEventListener : MonoBehaviour
{
[SerializeField] private GameEvent[] criticalEvents;

private void OnEnable()
{
foreach (var evt in criticalEvents)
{
evt?.AddListener(HandleCriticalEvent);
}
}

private void OnDisable()
{
foreach (var evt in criticalEvents)
{
evt?.RemoveListener(HandleCriticalEvent);
}
}

private void HandleCriticalEvent()
{
// Lightweight handling only
StartCoroutine(HandleEventAsync());
}

private IEnumerator HandleEventAsync()
{
yield return null; // Defer heavy work
// Heavy processing here
}
}

Event Frequency Monitoring

public class EventPerformanceMonitor : MonoBehaviour
{
[SerializeField] private GameEvent[] monitoredEvents;

private void Update()
{
foreach (var evt in monitoredEvents)
{
if (evt.EventsRaisedThisFrame > 10)
{
Debug.LogWarning($"High frequency event: {evt.name} raised {evt.EventsRaisedThisFrame} times this frame");
}
}
}
}

Debugging and Testing

Event History Analysis

#if UNITY_EDITOR
public class EventHistoryAnalyzer : MonoBehaviour
{
[SerializeField] private GameEvent targetEvent;

[ContextMenu("Analyze Event History")]
private void AnalyzeEventHistory()
{
if (targetEvent == null || targetEvent.EventHistory == null) return;

Debug.Log($"Event {targetEvent.name} History:");
Debug.Log($"Total Events: {targetEvent.EventHistory.Count}");

if (targetEvent.EventHistory.Count > 0)
{
var recent = targetEvent.EventHistory.TakeLast(5);
Debug.Log("Recent events:");
foreach (var entry in recent)
{
Debug.Log($" {entry.timestamp}: {entry.parameters}");
}
}
}
}
#endif

Automated Event Testing

[System.Serializable]
public class EventTest
{
public GameEvent eventToTest;
public float interval = 1f;
public bool enabled = true;
}

public class EventTester : MonoBehaviour
{
[SerializeField] private EventTest[] eventTests;

private void Start()
{
foreach (var test in eventTests)
{
if (test.enabled && test.eventToTest != null)
{
InvokeRepeating(nameof(RaiseTestEvent), 0f, test.interval);
}
}
}

private void RaiseTestEvent()
{
foreach (var test in eventTests)
{
if (test.enabled)
{
test.eventToTest.Raise();
}
}
}
}

Best Practices

Event Design

  1. Use specific event types instead of generic objects
  2. Keep event parameters simple and focused
  3. Avoid raising events in Update() loops without throttling
  4. Use descriptive names for event assets

Listener Management

  1. Always pair AddListener with RemoveListener
  2. Use OnEnable/OnDisable pattern for automatic cleanup
  3. Keep event handlers lightweight and fast
  4. Move heavy processing to coroutines or separate frames

Performance

  1. Monitor listener counts using debug tools
  2. Avoid excessive event chaining
  3. Use conditional logic to prevent unnecessary events
  4. Profile event-heavy systems regularly

Debugging

  1. Enable event history during development
  2. Use SoapKit Debug Window for real-time monitoring
  3. Implement event testing utilities
  4. Add validation for critical event flows

See Also