Skip to main content

01 Void Event: The Decoupled Architecture

GES ยท Examples

Fire a parameterless event and let a receiver react to it, with the sender and receiver never referencing each other in code.

For developers writing their first event. Assumes the system is already initialized from the Quick Start page.

Overviewโ€‹

Click the scene button to raise a parameterless event. The button calls the raiser, and the manager uses the event asset to reach the receiver's callback. The two scripts communicate through that shared asset.

๐Ÿ”ˆ Hover for sound

Demo Sceneโ€‹

Assets/TinyGiants/GameEventSystem/Demo/01_VoidEvent/01_VoidEvent.unity

Scene Compositionโ€‹

UI Layer (Canvas):

  • ๐ŸŽฎ Button - Canvas UI button located at the bottom center
    • OnClick() event is wired to โ†’VoidEventRaiser.RaiseBasicEvent()
    • This is standard Unity UI event binding

Game Logic Layer (Demo Scripts):

  • ๐Ÿ“ค VoidEventRaiser - GameObject with VoidEventRaiser.cs script

    • Holds a reference to the OnVoidEvent GameEvent asset
    • When RaiseBasicEvent() is called by the Button, it triggers voidEvent.Raise()
    • Also plays UI audio feedback
  • ๐Ÿ“ฅ VoidEventReceiver - GameObject with VoidEventReceiver.cs script

    • Listens to OnVoidEvent through visual binding in Game Event Editor
    • References the blue cube's Rigidbody to apply physics responses

Visual Feedback Layer (Demo Objects):

  • ๐ŸŽฒ Blue Cube - 3D object in the scene
    • Has a Rigidbody component for physics simulation
    • Responds with jump and spin when the event fires
    • Ground plane below for landing surface

How to Interactโ€‹

Step 1: Enter Play Modeโ€‹

Press the Play button in Unity to start the demo.

Step 2: Click the "Raise" Buttonโ€‹

Click the "Raise" button at the bottom of the Game View.

Event Flow:

  1. ๐Ÿ–ฑ๏ธUnity's Button OnClick() triggers โ†’VoidEventRaiser.RaiseBasicEvent()
  2. ๐Ÿ”Š Audio feedback plays from VoidEventRaiser
  3. ๐Ÿ“ก voidEvent.Raise() broadcasts the signal through GameEventManager
  4. ๐Ÿ“ฅ VoidEventReceiver's OnEventReceived() method is invoked automatically
  5. ๐ŸŽฒ The cube jumps upward with random horizontal drift and spin
  6. ๐Ÿ“ Console logs confirm each step: [VoidEvent] Raise() โ†’[VoidEvent] OnEventReceived()

Scene Architectureโ€‹

Event Definitionโ€‹

Open the Game Event Editor window (Tools > TinyGiants > GES > Game Event System, then click "Game Event Editor"):

Game Event Editor

Key Components:

  • Event Name: OnVoidEvent
  • Event Type: void (parameterless)
  • Database: GameEventDatabase_Void
  • Behavior Column: Shows a green (void) icon indicating callback binding

This ScriptableObject acts as the signal channel between sender and receiver.


Sender Setup (VoidEventRaiser)โ€‹

Select the VoidEventRaiser GameObject in the Hierarchy (Demo Scripts/VoidEventRaiser):

VoidEventRaiser Inspector

Configuration:

  • GameObject Section:

    • Void Event field uses [GameEventDropdown] attribute
    • Set to OnVoidEvent asset
  • Audio Section:

    • UI Clip assigned for button click feedback

The script simply calls voidEvent.Raise() when the button triggers itโ€”no knowledge of who listens*.


Receiver Binding (Behavior Configuration)โ€‹

This is where the decoupling magic happens! The connection between event and callback is configured entirely in the Editor.

How to Configure:

  1. In the Game Event Editor window, find OnVoidEvent in the event list
  2. Look at the Behavior column on the right
  3. Click the green (void) icon to open the Behavior Window

Behavior Window

Configuration Details:

Event Action Section:

  • Mode: Runtime Only (executes at runtime, not in Editor)
  • Target Object: VoidEventReceiver GameObject
  • Method: VoidEventReceiver.OnEventReceived (void method)

This binding tells the GameEventManager: "When OnVoidEvent.Raise() is called, automatically invoke VoidEventReceiver.OnEventReceived()"

๐ŸŽฏ Visual Binding Benefits
  • โœ…No code references needed between Raiser and Receiver
  • โœ…Easy to add/remove listeners without touching scripts
  • โœ…Clear visual overview of event โ†’callback relationships
  • โœ…Runtime-only mode prevents accidental Editor execution

Code Breakdownโ€‹

VoidEventRaiser.cs (Event Sender)โ€‹

using TinyGiants.GES.Runtime;
using UnityEngine;

public class VoidEventRaiser : MonoBehaviour
{
[Header("GameEvent")]
[GameEventDropdown] public GameEvent voidEvent;

[Header("Audio")]
[SerializeField] private AudioClip UIClip;

private AudioSource _audioSource;

private void Start()
{
_audioSource = gameObject.AddComponent<AudioSource>();
}

/// <summary>
/// [Input Trigger]
/// This method is called by the Button's OnClick() event (configured in Inspector).
/// It broadcasts the event signal without knowing who is listening.
/// </summary>
public void RaiseBasicEvent()
{
if (UIClip) _audioSource.PlayOneShot(UIClip);

if (voidEvent == null)
{
Debug.LogWarning("[VoidEvent] No GameEvent assigned on VoidEventRaiser.");
return;
}

voidEvent.Raise();
Debug.Log("[VoidEvent] Raise() called on GameEvent.");
}
}

Key Points:

  • ๐ŸŽฏ [GameEventDropdown] - Provides a dropdown to select events in Inspector
  • ๐Ÿ”Š Audio Feedback - Plays sound before raising the event
  • ๐Ÿ“ข voidEvent.Raise() - Single line broadcasts to all listeners
  • ๐Ÿ”‡ Zero coupling - No references to VoidEventReceiver or the cube

VoidEventReceiver.cs (Event Listener)โ€‹

using UnityEngine;

public class VoidEventReceiver : MonoBehaviour
{
[SerializeField] private Rigidbody targetRigidbody;

private float jumpForce = 5.0f;
private float horizontalRandomness = 1.0f;
private float spinStrength = 5.0f;

/// <summary>
/// [Event Callback]
/// This method is NOT called by VoidEventRaiser directly.
/// It is bound to 'OnVoidEvent' via the Game Event Editor's Behavior Window.
///
/// Effect: Resets vertical velocity, then applies jump + random drift + spin.
/// </summary>
public void OnEventReceived()
{
Debug.Log("[VoidEvent] OnEventReceived() called on GameEvent.");

if (targetRigidbody != null)
{
// Reset vertical velocity for consistent jump height
Vector3 currentVel;
#if UNITY_6000_0_OR_NEWER
currentVel = targetRigidbody.linearVelocity;
#else
currentVel = targetRigidbody.velocity;
#endif
currentVel.y = 0;

#if UNITY_6000_0_OR_NEWER
targetRigidbody.linearVelocity = currentVel;
#else
targetRigidbody.velocity = currentVel;
#endif

// Apply jump with random horizontal drift
Vector2 randomCircle = Random.insideUnitCircle * horizontalRandomness;
Vector3 sideForce = new Vector3(randomCircle.x, 0, randomCircle.y);
Vector3 finalForce = (Vector3.up * jumpForce) + sideForce;
targetRigidbody.AddForce(finalForce, ForceMode.Impulse);

// Apply random spin
Vector3 randomTorque = Random.insideUnitSphere * spinStrength;
targetRigidbody.AddTorque(randomTorque, ForceMode.Impulse);
}
else
{
Debug.LogWarning("VoidEventReceiver: Please assign targetRigidbody in Inspector!");
}
}
}

Key Points:

  • ๐ŸŽฒ Velocity Reset - Ensures consistent jump height by zeroing Y velocity first
  • ๐ŸŽฏ Physics Response - Combines upward impulse + random horizontal drift + random torque
  • ๐Ÿ”‡ Zero coupling - No references to VoidEventRaiser or Button
  • ๐Ÿ”„ Unity Version Compatibility - Handles both legacy and Unity 6's physics API

Key Takeawaysโ€‹

ConceptImplementation
๐ŸŽฏ DecouplingRaiser and Receiver never reference each other
๐Ÿ“ก BroadcastingSingle Raise() call notifies all listeners
๐ŸŽจ Visual BindingEvent callbacks configured in Behavior Window, not in code
๐Ÿ”— Layer SeparationUI โ†’Logic (Raiser) โ†’Event System โ†’Logic (Receiver) โ†’Visual
๐Ÿ”„ ScalabilityAdd more receivers without modifying sender code
๐Ÿง  Design Pattern

The button calls VoidEventRaiser. The receiver's callback is bound through the same event asset in the editor.