# MainControl.cs in Undertale-Changer Template: Purpose, Architecture, and Usage

> Understand MainControl.cs in the Undertale-Changer Template. This script orchestrates services, manages scene states, and offers a singleton gateway for runtime systems.

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

---

**MainControl.cs is the central MonoBehaviour orchestrator that initializes core services, manages scene states (Normal, Overworld, Battle), and provides a singleton gateway for the Undertale-Changer Template's runtime systems.**

Located at [`Assets/Scripts/UCT/Core/MainControl.cs`](https://github.com/arch-aik/undertale-changer-template/blob/main/Assets/Scripts/UCT/Core/MainControl.cs) in the `arch-aik/undertale-changer-template` repository, this script functions as the brain of the game. It bootstraps the initialization pipeline, maintains global state across scenes, and coordinates high-level subsystems including audio, combat, and UI management.

## Core Responsibilities of MainControl.cs

### Singleton Pattern and Global Access

`MainControl` implements a thread-safe singleton pattern to ensure exactly one master controller exists throughout the game lifecycle. The implementation exposes a static instance property at **line 111**:

```csharp
public static MainControl Instance { get; private set; }

```

This design allows any script to access global game state without direct references:

```csharp
// Access the master controller from any context
var main = MainControl.Instance;
main.SettingsStorage.Pause = true;

```

### Scene State Management

The controller tracks three distinct high-level modes through the `SceneState` enum defined at **lines 34-39**:

```csharp
public enum SceneState { Normal, Overworld, Battle }

```

The `StartWithSceneState()` method (**lines 48-90**) instantiates appropriate subsystems based on the current enum value. When `sceneState` changes, the controller automatically triggers initialization routines for battle mechanics or overworld navigation accordingly.

### Service Initialization

The initialization pipeline follows a strict lifecycle:

1. **Awake()** (**lines 22-47**) – Loads saved preferences, assigns the singleton instance, and triggers first-time setup
2. **Start()** (**lines 66-99**) – Configures fade transitions, volume levels, UI components, and event tables
3. **Initialization() & InitializationScene()** (**lines 43-104**) – Loads language packs, item databases, and localized UI text

## Key Methods and Implementation Details

### HitPlayer() and Combat Utilities

The `HitPlayer()` method (**lines 59-83**) provides standardized damage application with integrated feedback:

```csharp
// Reduce player HP by 10 and trigger effects
bool tookDamage = MainControl.Instance.HitPlayer(10);
if (tookDamage) 
{
    // Damage applied successfully; visual flash and audio play automatically
}

```

This method handles damage calculation, sound-effect triggering, and screen-flash coordination through the `AudioControl` and `PlayerControl` subsystems.

### Chase Mode Visual Effects

When enemies detect the player in overworld sections, `EnterChase()` (**lines 85-122**) and `ExitChase()` animate global lighting and UI elements to create urgency:

```csharp
// Trigger red-alert lighting and speed lines
MainControl.Instance.EnterChase();

// Restore normal lighting when escape succeeds
MainControl.Instance.ExitChase();

```

These methods manipulate global light tweens and post-processing effects to signal pursuit states without modifying core game logic.

### Debug Utilities

The `DebugUpdate()` method (**lines 100-131**) provides hot-key shortcuts for rapid iteration:

- **F5** – Reloads the current scene via `GameUtilityService.RefreshTheScene()`
- **Ctrl+I** – Toggles invincibility by flipping `playerControl.keepInvincible`

These tools execute only in development builds, allowing designers to test combat scenarios without restarting the application.

## Practical Code Examples

### Accessing Subsystem References

`MainControl` maintains cached references to frequently accessed controllers:

```csharp
// Reference pattern used throughout the codebase
MainControl.Instance.AudioControl.PlaySound("UI_Select");
MainControl.Instance.BattleControl.StartEncounter("Enemy_Papyrus");

```

### Switching Game Modes

Transition between exploration and combat states programmatically:

```csharp
// Change state and trigger battle initialization
MainControl.Instance.sceneState = MainControl.SceneState.Battle;
MainControl.Instance.InitializationBattle();

```

### Global Visual Transitions

Coordinate fade effects through the central controller:

```csharp
// Trigger scene-wide fade-out
MainControl.Instance.StartCoroutine(
    MainControl.Instance.FadeOutTransition()
);

```

## Related Subsystems and Dependencies

[`MainControl.cs`](https://github.com/arch-aik/undertale-changer-template/blob/main/MainControl.cs) directly references the following core files to maintain system coherence:

- **[`PlayerControl.cs`](https://github.com/arch-aik/undertale-changer-template/blob/main/PlayerControl.cs)** ([`Assets/Scripts/UCT/Control/PlayerControl.cs`](https://github.com/arch-aik/undertale-changer-template/blob/main/Assets/Scripts/UCT/Control/PlayerControl.cs)) – Stores player statistics, inventory, and debug invincibility flags
- **[`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)) – Handles map navigation and overworld entity management
- **[`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)) – Manages turn-based combat flow and enemy configuration
- **[`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)) – Centralizes audio mixer routing and sound-effect playback
- **[`LanguagePackControl.cs`](https://github.com/arch-aik/undertale-changer-template/blob/main/LanguagePackControl.cs)** ([`Assets/Scripts/UCT/Control/LanguagePackControl.cs`](https://github.com/arch-aik/undertale-changer-template/blob/main/Assets/Scripts/UCT/Control/LanguagePackControl.cs)) – Loads localized UI strings based on player settings
- **[`SettingsStorage.cs`](https://github.com/arch-aik/undertale-changer-template/blob/main/SettingsStorage.cs)** ([`Assets/Scripts/UCT/Settings/SettingsStorage.cs`](https://github.com/arch-aik/undertale-changer-template/blob/main/Assets/Scripts/UCT/Settings/SettingsStorage.cs)) – Persists global preferences including volume and resolution

These dependencies are wired during the `Awake()` and `Start()` phases (**lines 27-30, 46-50, 70-84**), ensuring all subsystems are available before gameplay begins.

## Summary

- **MainControl.cs** serves as the singleton orchestrator at [`Assets/Scripts/UCT/Core/MainControl.cs`](https://github.com/arch-aik/undertale-changer-template/blob/main/Assets/Scripts/UCT/Core/MainControl.cs), providing global access via `MainControl.Instance`
- It manages three distinct **scene states** (Normal, Overworld, Battle) through the `SceneState` enum and `StartWithSceneState()` method
- **Initialization** occurs in two phases: `Awake()` for singleton setup and `Start()` for subsystem configuration
- **Combat utilities** like `HitPlayer()` integrate damage calculation with audiovisual feedback
- **Debug shortcuts** (F5 for reload, Ctrl+I for invincibility) streamline development workflows through `DebugUpdate()`

## Frequently Asked Questions

### Where is MainControl.cs located in the Undertale-Changer Template repository?

The file resides at [`Assets/Scripts/UCT/Core/MainControl.cs`](https://github.com/arch-aik/undertale-changer-template/blob/main/Assets/Scripts/UCT/Core/MainControl.cs) according to the source tree in `arch-aik/undertale-changer-template`. This location follows Unity's standard Assets folder structure, placing core architecture scripts in a dedicated Core subdirectory for organizational clarity.

### How does MainControl.cs implement the singleton pattern?

The script uses a static auto-property `public static MainControl Instance { get; private set; }` defined at line 111, populated during the `Awake()` lifecycle method. This approach guarantees exactly one instance persists across scene loads while preventing external modification of the reference.

### What scene states does MainControl.cs manage?

The controller defines three states in the `SceneState` enum at lines 34-39: **Normal** (menu/initialization), **Overworld** (exploration and NPC interaction), and **Battle** (turn-based combat encounters). The `StartWithSceneState()` method routes initialization logic based on the active state value.

### How do I access player health data through MainControl.cs?

Access player statistics through the cached `PlayerControl` reference: `MainControl.Instance.playerControl.hp`. For damage application, use the abstraction method `MainControl.Instance.HitPlayer(damageAmount)`, which modifies health internally while triggering associated sound and visual effects.