What Is the Purpose of the EventController in Undertale-Changer-Template?

The EventController serves as the runtime interpreter that drives the game’s event-driven architecture by loading data tables, evaluating rules against current game facts, and dispatching registered methods to execute gameplay logic without hard-coded dependencies.

The EventController is the central orchestrator of the Undertale-Changer-Template, an open-source Unity framework designed for narrative-driven games. Located in Assets/Scripts/UCT/EventSystem/EventController.cs, this component bridges external data assets—specifically EventTable, FactTable, and RuleTable—with concrete C# implementations, allowing designers to script complex gameplay sequences through editable tables rather than modifying source code.

Method Registry and Lookup

At the heart of the controller lies the MethodDictionary, a static dictionary defined around lines 37–46 that maps string identifiers (e.g., "bool:PlayerCanMove") to lambda delegates. This registry decouples the data tables from implementation details, enabling external scripts to trigger gameplay logic by name alone.

When a rule specifies "float:MakePlayerSpin", the controller resolves this to the concrete method through the dictionary, converting string parameters to appropriate types before invocation.

Table Loading Architecture

On initialization, the LoadTables method (lines 85–103) retrieves table assets from the Resources folder. The controller maintains separate references for global tables (persisting across scenes) and scene-specific tables (local to the current overworld instance). If the active scene is not an overworld, the system automatically falls back to global tables, ensuring consistent event handling across different game contexts.

Event Update Loop

Every frame, the Update method (lines 60–70) iterates through both global and scene event tables, calling UpdateEvent on each entry. For every EventEntry flagged as triggering, the controller initiates rule evaluation. This continuous polling model ensures that state changes are detected immediately without requiring explicit event broadcasts from other systems.

Rule Evaluation Engine

The DetectionRule method (lines 44–78) implements the core decision logic. When processing a triggering event, the controller:

  • Validates the associated RuleEntry against current conditions
  • Clears the triggering flag upon successful match
  • Activates new triggers via SetTriggering (lines 91–99)
  • Invokes specified methods through InvokeRuleMethod
  • Updates facts via SetFact (lines 82–110)

This sequence enables chained reactions where one event can cascade into multiple follow-up actions.

Fact Management

The controller maintains mutable game state through numeric facts stored in FactTable assets. The SetFact implementation supports arithmetic operations (Add, Subtract, Multiply, etc.) and automatically persists changes to either scene-local or global tables depending on the fact's scope. Rules reference these facts for conditional logic, creating a data-driven state machine.

Method Invocation Pipeline

InvokeMethodByName (lines 131–162) handles the final dispatch step. This method parses method signatures (e.g., "string:StartOverworldTypeWritter"), resolves the corresponding delegate from MethodDictionary, performs type conversion on string parameters, and executes the call. It optionally chains additional events, allowing designers to create sequential behaviors like playing dialogue then transitioning to battle.

Practical Implementation Examples

Triggering Scripted Events

To initiate a typewriter dialogue from another script:

EventController.InvokeMethodByName(
    "string:StartOverworldTypeWritter",
    "IntroDialogue",
    "true",
    "AfterIntro",
    false,
    "",
    null);

This calls the registered method (implemented around lines 180–210) with the specified dialogue key and post-dialogue event trigger.

Defining Data-Driven Rules

A designer can create a spin attack behavior without coding:


# EventTable.asset

rules:
  - triggeredBy: ["SpinTrigger"]
    methodNames: ["float:MakePlayerSpin"]
    firstStringParams: ["2.5"]
    useMethodEvents: [true]
    methodEvents: ["AfterSpin"]

When SetTriggering("SpinTrigger") is called, the controller automatically invokes MakePlayerSpin(2.5f, true, "AfterSpin").

Chaining Event Reactions

The propagation system enables complex sequences:

// From within a rule's method execution:
EventController.SetTriggering("OpenChest");
// This immediately flags the OpenChest event, which will be 
// evaluated on the next Update() cycle against RuleTable entries

Summary

  • The EventController serves as the runtime bridge between data tables and C# implementations in the Undertale-Changer-Template.

  • MethodDictionary (lines 37–46) provides string-to-delegate mapping for decoupled method invocation.

  • LoadTables (lines 85–103) manages both global and scene-specific EventTable, FactTable, and RuleTable assets.

  • The Update loop (lines 60–70) continuously polls triggering events and evaluates rules through DetectionRule.

  • Rule evaluation supports fact modification, trigger propagation, and method chaining without code changes.

  • The system enables designers to script gameplay through external table assets while maintaining type-safe method dispatch.

Frequently Asked Questions

How does the EventController differ from Unity's standard EventSystem?

While Unity's EventSystem focuses on UI input handling, the EventController implements a data-driven narrative scripting layer. It specifically manages EventTable, FactTable, and RuleTable assets, evaluating custom rules every frame to trigger methods registered in the MethodDictionary rather than handling pointer clicks or touch events.

What is the difference between global and scene-specific tables?

The controller loads both variants through LoadTables (lines 85–103). Global tables persist across scene changes and store universal facts or recurring events, while scene-specific tables contain local triggers and facts that only apply to the current overworld instance. The system prioritizes scene tables but falls back to global assets when the current context lacks specific definitions.

How are string identifiers mapped to actual C# methods?

The MethodDictionary defined around lines 37–46 acts as the registry. During initialization or static construction, concrete methods—such as StartOverworldTypeWritter or camera movement functions—are registered with string keys following the pattern "returnType:MethodName". When InvokeMethodByName (lines 131–162) processes a rule, it parses this identifier, retrieves the corresponding lambda, performs parameter type conversion, and executes the delegate.

Can events trigger other events automatically?

Yes. The SetTriggering method (lines 91–99) allows any rule or external script to flag an event as active in either the global or scene table. Additionally, the InvokeRuleMethod logic supports method events—string parameters specifying follow-up events that the controller automatically triggers after a method completes, enabling complex multi-step sequences without circular code dependencies.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →