# How Scene Transitions Work in the Undertale-Changer Template: A Complete Technical Guide

> Explore how Undertale-Changer Template handles scene transitions. Learn about fade animations scene loading with GameUtilityService and MainControl for seamless game flow.

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

---

**Scene transitions in the Undertale-Changer Template are managed by a centralized subsystem where [`GameUtilityService.cs`](https://github.com/arch-aik/undertale-changer-template/blob/main/GameUtilityService.cs) handles fade animations and scene loading via DOTween and Unity's `SceneManager`, while [`MainControl.cs`](https://github.com/arch-aik/undertale-changer-template/blob/main/MainControl.cs) configures per-scene behavior and automatic fade-in sequences.**

The Undertale-Changer Template provides a production-ready scene management system for Unity-based Undertale fangames. This architecture encapsulates visual blackout fades, optional BGM muting, and asynchronous loading into a single static API call. All transition logic resides in two core scripts that coordinate UI overlay animations with Unity's scene lifecycle.

## Architecture Overview

The template isolates transition logic in two primary locations:

- **[`Assets/Scripts/UCT/Service/GameUtilityService.cs`](https://github.com/arch-aik/undertale-changer-template/blob/main/Assets/Scripts/UCT/Service/GameUtilityService.cs)** – Static utility class containing the fade animation engine, audio tweening, and scene loader (lines 1-150)
- **[`Assets/Scripts/UCT/Core/MainControl.cs`](https://github.com/arch-aik/undertale-changer-template/blob/main/Assets/Scripts/UCT/Core/MainControl.cs)** – Scene-specific configuration and fade-in initialization (lines 80-95)

This separation ensures global transition behavior remains consistent while allowing individual scenes to customize entry animations, pause states, and fade durations through Unity Inspector settings.

## Core Components

### GameUtilityService (Exit Sequence)

Located at [`Assets/Scripts/UCT/Service/GameUtilityService.cs`](https://github.com/arch-aik/undertale-changer-template/blob/main/Assets/Scripts/UCT/Service/GameUtilityService.cs), this static class provides the primary API for scene switching. The **`FadeOutAndSwitchScene`** method (lines 89-124) orchestrates the complete exit sequence:

1. Captures the `sceneSwitchingFadeImage` reference (the `Canvas/InOutBlack` UI Image)
2. Tweens BGM volume to zero when `isBgmMuted` is true (lines 98-108)
3. Sets `SettingsStorage.Pause` to `true`, freezing gameplay updates (line 115)
4. Uses DOTween to animate the overlay color toward the specified `fadeColor` over `fadeTime` seconds (lines 120-132)
5. Invokes the scene switch callback upon tween completion

The actual loading occurs in **`SwitchScene`** (lines 43-58), which handles both synchronous and asynchronous loading via `SceneManager.LoadScene` or `SceneManager.LoadSceneAsync`. This method performs critical housekeeping: clearing the fade image, updating the last-scene cache (unless excluded), restoring resolution via `SetResolution`, and clearing `MainControl.isSceneSwitching`.

### MainControl (Entry Sequence)

[`Assets/Scripts/UCT/Core/MainControl.cs`](https://github.com/arch-aik/undertale-changer-template/blob/main/Assets/Scripts/UCT/Core/MainControl.cs) manages scene entry through its **`Start`** method (lines 80-95). Upon scene load:

1. Locates the `InOutBlack` Image under the Canvas
2. Checks `isFadeTransitionEnabled`—if false, skips fade initialization
3. Sets the image to `Color.black` (unless `isFadeInDisabled` is true)
4. Animates toward `Color.clear` using DOTween
5. Clears the pause flag after completion (unless `isFadeInUnpaused` is enabled)

Configuration fields serialized in the Unity Inspector include **`isFadeTransitionEnabled`** (global fade toggle), **`isFadeInDisabled`** (skip entry fade), and **`isFadeInUnpaused`** (keep gameplay running during fade-in).

### Excluded Scenes Logic

The **`ExcludedScenes`** array (lines 24-27 in GameUtilityService.cs) prevents specific scenes from being recorded as the "last scene" in the history cache. By default, `"Menu"`, `"Rename"`, `"Story"`, `"Start"`, `"Battle"`, and `"GameOver"` are excluded, ensuring the game returns to meaningful gameplay scenes rather than temporary states.

## Step-by-Step Transition Flow

A complete scene transition executes the following pipeline:

1. **Initialization**: The current scene's `MainControl.Start` has already completed its fade-in sequence.
2. **Trigger**: Game code calls `GameUtilityService.FadeOutAndSwitchScene` with target scene parameters.
3. **Audio Management**: If `isBgmMuted` is true, the audio source volume tweens to 0 over the specified duration (instant if `fadeTime` equals 0).
4. **Gameplay Pause**: `SettingsStorage.Pause` sets to `true` to prevent gameplay updates during the visual transition.
5. **Visual Fade**: DOTween animates the `InOutBlack` Image color toward the target `fadeColor` (typically `Color.black`).
6. **Scene Activation**: Upon tween completion, `SwitchScene` invokes `SceneManager.LoadSceneAsync` (or synchronous equivalent).
7. **Housekeeping**: The system restores resolution settings and clears the `isSceneSwitching` flag.
8. **Entry**: The new scene's `MainControl.Start` method executes, performing the fade-in from black to clear.

## Configuration Examples

To implement an instant transition without visual effects:

```csharp
// Disable fades for this scene instance
MainControl.Instance.isFadeTransitionEnabled = false;
GameUtilityService.SwitchScene("Battle", isAsync: false);

```

To create a dramatic slow fade with custom colors:

```csharp
GameUtilityService.FadeOutAndSwitchScene(
    scene: "GameOver",
    fadeColor: Color.red,
    isBgmMuted: true,
    fadeTime: 2.0f,
    isAsync: true
);

```

## Practical Implementation Example

The following pattern demonstrates transitioning from a battle victory back to the main menu:

```csharp
public void OnBattleVictory()
{
    // Fade to black over 0.5 seconds, mute BGM, load Menu asynchronously
    GameUtilityService.FadeOutAndSwitchScene(
        scene: "Menu",
        fadeColor: Color.black,
        isBgmMuted: true,
        fadeTime: 0.5f,
        isAsync: true
    );
}

```

This single call handles the complete sequence: initiating the black fade, tweening audio volume to zero, pausing game logic, loading the Menu scene, and preparing the new scene's fade-in cycle.

## Summary

- **Scene transitions** are centralized in [`GameUtilityService.cs`](https://github.com/arch-aik/undertale-changer-template/blob/main/GameUtilityService.cs) with static methods like `FadeOutAndSwitchScene` and `SwitchScene`.
- **Visual fades** use a UI Image (`Canvas/InOutBlack`) animated via DOTween, supporting custom colors and durations with optional BGM muting.
- **Per-scene configuration** resides in [`MainControl.cs`](https://github.com/arch-aik/undertale-changer-template/blob/main/MainControl.cs), controlling whether fades play, if they pause gameplay, and entry behavior through serialized boolean fields.
- **Automatic housekeeping** includes resolution restoration, scene history management (with exclusions for menu/utility scenes), and pause state reset.
- **Asynchronous loading** prevents frame hitches during heavy scene loads while maintaining the visual blackout until loading completes.

## Frequently Asked Questions

### How do I disable fade effects for a specific scene?

Set the **`isFadeTransitionEnabled`** field to `false` in that scene's `MainControl` component through the Unity Inspector. Alternatively, call `GameUtilityService.SwitchScene` directly to bypass the fade animation system entirely and load immediately.

### Why isn't my scene being recorded in the "last scene" cache?

Check if your scene name appears in the **`ExcludedScenes`** array within [`GameUtilityService.cs`](https://github.com/arch-aik/undertale-changer-template/blob/main/GameUtilityService.cs) (lines 24-27). Scenes like `"Menu"`, `"Battle"`, and `"GameOver"` are excluded by default to prevent the game from returning to temporary states when using scene restoration features.

### Can I keep gameplay running during the fade-in animation?

Yes. In the target scene's `MainControl` component, enable the **`isFadeInUnpaused`** boolean flag. This prevents the system from setting `SettingsStorage.Pause` during the fade-in sequence, allowing animations and game logic to continue while the visual fade completes.

### What happens if I specify a fadeTime of 0?

When **`fadeTime`** is 0, DOTween executes the color change instantly with zero duration. If `isBgmMuted` is also true, the BGM volume sets to 0 immediately rather than tweening. The scene switch still occurs on the next frame after the instant fade completes.