# Core Architecture of Undertale-Changer-Template: A Unity Framework Breakdown

> Explore the core architecture of Undertale-Changer-Template a modular Unity framework. Understand its service oriented design data containers and controllers for flexible game development.

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

---

**The Undertale-Changer-Template uses a modular, service-oriented Unity architecture that separates game logic into distinct layers—Core management, ScriptableObject data containers, runtime Services, and scene-specific controllers—to enable flexible, data-driven game development.**

The **Undertale-Changer-Template** is an open-source Unity framework designed for creating Undertale-like RPGs. Understanding the core architecture of Undertale-Changer-Template reveals how it balances singleton managers with ScriptableObject assets to create a scalable, maintainable game engine.

## Architectural Layers Overview

The framework organizes functionality into eight distinct layers, each with specific responsibilities and entry points:

| Layer | Responsibility | Main Entry Point |
|------|----------------|------------------|
| **Core** | Global state, scene initialization, singleton management, language-pack handling, audio setup, and overall game flow. | [`MainControlSummon.cs`](https://github.com/arch-aik/undertale-changer-template/blob/main/MainControlSummon.cs) |
| **Core – Runtime** | Per-scene behavior (overworld, battle, UI) and runtime services. | [`MainControl.cs`](https://github.com/arch-aik/undertale-changer-template/blob/main/MainControl.cs) |
| **Settings** | In-game configuration UI, key-binding editing, language-pack selection, screen-resolution toggles. | [`SettingsController.cs`](https://github.com/arch-aik/undertale-changer-template/blob/main/SettingsController.cs) |
| **Control (ScriptableObjects)** | Data containers for Overworld, Battle, Audio, Language packs, player stats, etc. | [`OverworldControl.cs`](https://github.com/arch-aik/undertale-changer-template/blob/main/OverworldControl.cs), [`AudioControl.cs`](https://github.com/arch-aik/undertale-changer-template/blob/main/AudioControl.cs) |
| **Service** | Helper utilities (text processing, input handling, math helpers, data loading, XML parsing). | [`TextProcessingService.cs`](https://github.com/arch-aik/undertale-changer-template/blob/main/TextProcessingService.cs) |
| **EventSystem** | Decoupled event tables and rules that drive dialogue, battles and overworld triggers. | [`EventController.cs`](https://github.com/arch-aik/undertale-changer-template/blob/main/EventController.cs) |
| **Overworld / Battle / UI** | MonoBehaviour implementations that render the overworld, handle combat, and draw UI elements. | [`OverworldPlayerBehaviour.cs`](https://github.com/arch-aik/undertale-changer-template/blob/main/OverworldPlayerBehaviour.cs), [`BattleControl.cs`](https://github.com/arch-aik/undertale-changer-template/blob/main/BattleControl.cs) |

## How the Core Components Interact

The architecture follows a strict initialization sequence that ensures singleton persistence and proper scene state management:

### 1. Scene Entry and Singleton Guarantees

Every scene contains a `MainControlSummon` object. In its `Awake` method located at [`Assets/Scripts/UCT/Core/MainControlSummon.cs`](https://github.com/arch-aik/undertale-changer-template/blob/main/Assets/Scripts/UCT/Core/MainControlSummon.cs), the system:

- Detects the current `sceneState` (Overworld, Battle, or Normal)
- Calls `SetupController<T>` for the main camera, canvas, audio source, and the `MainControl` instance
- Guarantees a single instance of `MainControl` persists across scene loads

### 2. MainControl as the Scene Engine

`MainControl` at [`Assets/Scripts/UCT/Core/MainControl.cs`](https://github.com/arch-aik/undertale-changer-template/blob/main/Assets/Scripts/UCT/Core/MainControl.cs) serves as the central manager. In its `Awake` method, it loads language packs, player data, and references to ScriptableObjects (`AudioControl`, `BattleControl`, `OverworldControl`). The `Start` method creates the UI canvas, initializes volume, and calls `InitializationScene()`, which branches based on the stored `sceneState`.

### 3. Scene-Specific Initialization

The framework handles three primary scene states:

- **Overworld**: `StartWithSceneState()` creates the player character, global 2D light, and chase UI (`OverworldChaseUIController`)
- **Battle**: `InitializationBattle()` loads the battle configuration (defaulting to `DemoBattle` if none present) and spawns the battle UI
- **Normal**: Basic scene setup without specialized game mode logic

### 4. Settings UI Integration

`SettingsController` at [`Assets/Scripts/UCT/Settings/SettingsController.cs`](https://github.com/arch-aik/undertale-changer-template/blob/main/Assets/Scripts/UCT/Settings/SettingsController.cs) manages the in-game configuration interface. It reads the current `SettingsLayer` from `SettingsStorage`, builds dynamic option lists (resolution, sound volume, key bindings, language packs), and renders them using TextMeshPro. User interaction is handled by polling `InputService` and applying changes via the underlying ScriptableObjects.

### 5. Data Flow Architecture

All static game data resides as **ScriptableObjects** in the `Resources` folder. `DataHandlerService` loads these at runtime, while `TextProcessingService` parses plain-text language packs. This separation allows designers to modify game content (dialogue, item stats, enemy configurations) without touching engine code.

### 6. Event-Driven Logic

`EventController` at [`Assets/Scripts/UCT/EventSystem/EventController.cs`](https://github.com/arch-aik/undertale-changer-template/blob/main/Assets/Scripts/UCT/EventSystem/EventController.cs) loads tables of facts, rules, and events (`FactTable`, `RuleTable`) from resources. These tables drive dialogue branching and overworld triggers through a decoupled event system, eliminating hard-coded logic in MonoBehaviours.

## Key Implementation Details

### Singleton Management with MainControlSummon

The `MainControlSummon` class uses a generic `SetupController<T>` helper method to enforce singleton patterns. This utility either configures an existing singleton instance or instantiates a new one if the instance is missing, ensuring that critical managers like `MainControl`, the main camera, and audio sources persist across scene transitions.

### Scene State Initialization

The `MainControl` class maintains a `sceneState` enum that determines initialization behavior. When `InitializationScene()` is called, it evaluates this state to determine whether to spawn overworld entities, initialize battle systems, or perform standard scene setup. This branching logic ensures that each game mode receives appropriate resources and configuration.

### Data-Driven Configuration

The framework relies heavily on **ScriptableObjects** for configuration management. Classes like `OverworldControl`, `AudioControl`, and `BattleControl` inherit from `ScriptableObject` and store references to assets such as mixer groups, font configurations, and battle turn scripts. This architecture allows designers to tweak game parameters through the Unity Inspector without modifying source code.

## Practical Code Examples

### Instantiating the Core Manager in a New Scene

Place this script on an empty GameObject in any new Unity scene to bootstrap the framework:

```csharp
// Place this script on an empty GameObject in any new Unity scene.
using UnityEngine;
using UCT.Core;

public class SceneBootstrap : MonoBehaviour
{
    void Awake()
    {
        // MainControlSummon will ensure MainControl and related singletons persist.
        gameObject.AddComponent<MainControlSummon>();
    }
}

```

The `MainControlSummon` script automatically runs its `Awake` method which detects the current `sceneState` (Overworld, Battle, Normal) and calls `SetupController` for the main camera, canvas, audio source, and the `MainControl` instance.

### Switching Language Packs at Runtime

```csharp
using UCT.Core;
using UnityEngine;

public class LanguageSwitcher : MonoBehaviour
{
    // Call this with the index of the language pack you want to load.
    public void SetLanguage(int languageIndex)
    {
        // MainControl holds the current languagePackId and exposes Initialization().
        MainControl.Instance.languagePackId = languageIndex;
        MainControl.Instance.Initialization(languageIndex);
        // Refresh the UI to reflect new strings.
        SettingsController.Instance.OpenSetting("SettingLanguagePackageLayer");
    }
}

```

This method mirrors the logic inside `SettingsController.GetKeyDownToLanguagePackage()` which updates `MainControl.Instance.languagePackId` and calls `MainControl.Instance.Initialization()`.

### Opening the Settings Menu from Gameplay

```csharp
using UCT.Core;
using UnityEngine;

public class SettingsOpener : MonoBehaviour
{
    void Update()
    {
        // Press V to open the settings UI (same key used by the engine).
        if (Input.GetKeyDown(KeyCode.V) && !MainControl.Instance.overworldControl.isSetting)
        {
            SettingsController.Instance.OpenSetting();
        }
    }
}

```

The `OpenSetting` method (see [`SettingsController.cs`](https://github.com/arch-aik/undertale-changer-template/blob/main/SettingsController.cs) lines 553-564) fades in the settings canvas, sets the initial selected option, and displays the control description.

## Critical Source Files

| File | Path | Role |
|------|------|------|
| **[`MainControlSummon.cs`](https://github.com/arch-aik/undertale-changer-template/blob/main/MainControlSummon.cs)** | [`Assets/Scripts/UCT/Core/MainControlSummon.cs`](https://github.com/arch-aik/undertale-changer-template/blob/main/Assets/Scripts/UCT/Core/MainControlSummon.cs) | Guarantees singletons, persists core objects across scenes, starts `MainControl`. |
| **[`MainControl.cs`](https://github.com/arch-aik/undertale-changer-template/blob/main/MainControl.cs)** | [`Assets/Scripts/UCT/Core/MainControl.cs`](https://github.com/arch-aik/undertale-changer-template/blob/main/Assets/Scripts/UCT/Core/MainControl.cs) | Central manager for game state, language packs, audio, event tables, and scene-specific initialization. |
| **[`SettingsController.cs`](https://github.com/arch-aik/undertale-changer-template/blob/main/SettingsController.cs)** | [`Assets/Scripts/UCT/Settings/SettingsController.cs`](https://github.com/arch-aik/undertale-changer-template/blob/main/Assets/Scripts/UCT/Settings/SettingsController.cs) | Implements the in-game settings UI, handles user input, and writes changes back to ScriptableObjects. |
| **[`OverworldControl.cs`](https://github.com/arch-aik/undertale-changer-template/blob/main/OverworldControl.cs)** | [`Assets/Scripts/UCT/Control/OverworldControl.cs`](https://github.com/arch-aik/undertale-changer-template/blob/main/Assets/Scripts/UCT/Control/OverworldControl.cs) | ScriptableObject that stores overworld-specific data (camera limits, UI fonts, etc.). |
| **[`AudioControl.cs`](https://github.com/arch-aik/undertale-changer-template/blob/main/AudioControl.cs)** | [`Assets/Scripts/UCT/Control/AudioControl.cs`](https://github.com/arch-aik/undertale-changer-template/blob/main/Assets/Scripts/UCT/Control/AudioControl.cs) | Holds audio mixer references and default clips for BGM and SFX. |
| **[`EventController.cs`](https://github.com/arch-aik/undertale-changer-template/blob/main/EventController.cs)** | [`Assets/Scripts/UCT/EventSystem/EventController.cs`](https://github.com/arch-aik/undertale-changer-template/blob/main/Assets/Scripts/UCT/EventSystem/EventController.cs) | Loads fact, rule, and event tables that power dialogue and overworld triggers. |
| **[`TextProcessingService.cs`](https://github.com/arch-aik/undertale-changer-template/blob/main/TextProcessingService.cs)** | [`Assets/Scripts/UCT/Service/TextProcessingService.cs`](https://github.com/arch-aik/undertale-changer-template/blob/main/Assets/Scripts/UCT/Service/TextProcessingService.cs) | Parses language-pack text assets and provides string lookup for UI and dialogs. |
| **[`DataHandlerService.cs`](https://github.com/arch-aik/undertale-changer-template/blob/main/DataHandlerService.cs)** | [`Assets/Scripts/UCT/Service/DataHandlerService.cs`](https://github.com/arch-aik/undertale-changer-template/blob/main/Assets/Scripts/UCT/Service/DataHandlerService.cs) | Centralized loading of resources, language detection, and item data handling. |
| **[`OverworldPlayerBehaviour.cs`](https://github.com/arch-aik/undertale-changer-template/blob/main/OverworldPlayerBehaviour.cs)** | [`Assets/Scripts/UCT/Overworld/OverworldPlayerBehaviour.cs`](https://github.com/arch-aik/undertale-changer-template/blob/main/Assets/Scripts/UCT/Overworld/OverworldPlayerBehaviour.cs) | Player controller used in the overworld state, interacts with `MainControl`. |
| **[`BattleControl.cs`](https://github.com/arch-aik/undertale-changer-template/blob/main/BattleControl.cs)** | [`Assets/Scripts/UCT/Control/BattleControl.cs`](https://github.com/arch-aik/undertale-changer-template/blob/main/Assets/Scripts/UCT/Control/BattleControl.cs) | Stores the current battle configuration (BGM, turn scripts, enemy data). |

These files together illustrate the **modular, service-oriented architecture** of the Undertale-Changer-Template: a thin Unity MonoBehaviour layer delegates most logic to singleton managers, ScriptableObjects, and utility services, making it straightforward to swap out or extend parts (e.g., adding new battle configs or language packs) without touching core engine code.

## Summary

- The **Undertale-Changer-Template** employs a layered architecture separating Core management, Runtime behavior, Settings UI, and Data layers.
- **Singleton persistence** is enforced by [`MainControlSummon.cs`](https://github.com/arch-aik/undertale-changer-template/blob/main/MainControlSummon.cs), which guarantees that `MainControl` and essential services survive scene transitions.
- **ScriptableObjects** (`OverworldControl`, `BattleControl`, `AudioControl`) store configuration data, enabling designer-friendly tweaking without code changes.
- **Scene state branching** in [`MainControl.cs`](https://github.com/arch-aik/undertale-changer-template/blob/main/MainControl.cs) automatically initializes Overworld, Battle, or Normal modes based on the current `sceneState` enum.
- **Decoupled event logic** via [`EventController.cs`](https://github.com/arch-aik/undertale-changer-template/blob/main/EventController.cs) drives dialogue and triggers through data tables rather than hard-coded MonoBehaviour logic.

## Frequently Asked Questions

### What is the role of MainControlSummon in the Undertale-Changer-Template?

`MainControlSummon` acts as the entry point for every scene in [`Assets/Scripts/UCT/Core/MainControlSummon.cs`](https://github.com/arch-aik/undertale-changer-template/blob/main/Assets/Scripts/UCT/Core/MainControlSummon.cs). It ensures that singleton instances like `MainControl`, the main camera, and audio sources persist across scene loads using the generic `SetupController<T>` helper, preventing duplicate manager objects and maintaining global game state.

### How does the template handle different game modes like Overworld and Battle?

The `MainControl` class in [`Assets/Scripts/UCT/Core/MainControl.cs`](https://github.com/arch-aik/undertale-changer-template/blob/main/Assets/Scripts/UCT/Core/MainControl.cs) stores a `sceneState` enum that determines initialization behavior. When `InitializationScene()` is called, it branches to `StartWithSceneState()` for Overworld mode (spawning the player and chase UI) or `InitializationBattle()` for combat mode (loading battle configurations from `BattleControl` ScriptableObjects).

### Why does the architecture rely heavily on ScriptableObjects?

ScriptableObjects such as `OverworldControl`, `AudioControl`, and `BattleControl` (located in `Assets/Scripts/UCT/Control/`) separate data from behavior. This design allows game designers to modify camera limits, audio mixer groups, and enemy turn scripts directly in the Unity Inspector without modifying C# code, facilitating rapid iteration and modular content creation.

### What services handle text and data loading in the framework?

The `TextProcessingService` in [`Assets/Scripts/UCT/Service/TextProcessingService.cs`](https://github.com/arch-aik/undertale-changer-template/blob/main/Assets/Scripts/UCT/Service/TextProcessingService.cs) parses plain-text language packs for localization, while `DataHandlerService` in [`Assets/Scripts/UCT/Service/DataHandlerService.cs`](https://github.com/arch-aik/undertale-changer-template/blob/main/Assets/Scripts/UCT/Service/DataHandlerService.cs) manages centralized resource loading and item data handling. These utility services abstract file I/O operations, allowing the Core and UI layers to access game data through simple API calls.