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

> Understand the EventController in Undertale-Changer-Template. This runtime interpreter loads data, evaluates rules, and executes logic for a flexible event-driven architecture.

- Repository: [Archived AIk/undertale-changer-template](https://github.com/arch-aik/undertale-changer-template)
- Tags: deep-dive
- Published: 2026-02-25

---

**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`](https://github.com/arch-aik/undertale-changer-template/blob/main/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:

```csharp
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:

```yaml

# 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:

```csharp
// 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.