Dev Log 38 - The Christmas Resurrection (Kind - Of )

Published: (December 21, 2025 at 07:48 PM EST)
5 min read
Source: Dev.to

Source: Dev.to

Hello again, internet. Yes, I’m alive. Yes, it’s almost Christmas. No, the Halloween Frontend Challenge results still haven’t been released. I assume the judges were eaten by CSS goblins. Happens.

Anyway, I’m here to talk about why I vanished.

šŸŽƒ 1. The Great Dev Log Hiatus

I fully intended to keep posting dev logs. I really did.

Then the challenge results never came out and my brain went:

ā€œAh. Time to hibernate.ā€

And so I did.

🧪 2. The Mini Game That Became a Monster

I started building a tiny mini‑game inside my main project. I thought it was a ā€œminiā€ game anyway—some fun collectable cards, maybe play‑again AI in my project, just a little side thing. A distraction. A palate cleanser.

Naturally, it mutated into its own ecosystem, a full‑blown second project complete with:

  • its own UI
  • its own logic
  • its own lore
  • its own problems
  • its own identity crisis

Classic me.

🟦 3. The Roblox Arc (a.k.a. My Exile)

Then I decided to ā€œlearn Roblox scripting for fun.ā€

Turns out Roblox has its own coding language, a version of Lua called Luau. I had never even heard of it, but the promise of free server hosting and taking care of all the fiddly stuff was enough for me to give it a try.

This was a mistake.

Within days (or weeks) I got:

  1. a warning
  2. a 1‑day ban
  3. a 3‑day ban

All because the AI moderation system decided that any amount of visible skin is a war crime. I wasn’t even making anything weird—I was making a card game. A card game where the main subject is ducks. Apparently elbows are forbidden, as are any ducks with six‑packs.

So I left Roblox like a disgraced wizard and returned to Unity while I await the banishment, like a peasant thrown from the village.

🧱 4. The Birth of This New Project

Out of the ashes of my Roblox exile came this new Unity side‑project.

It started simple:

  • Title screen
  • Credits panel
  • Settings panel

Then I blinked and suddenly I had:

A Global Audio Engine

using UnityEngine;
using System.Collections;

namespace Audio
{
    public class AudioManager : MonoBehaviour
    {
        public static AudioManager Instance;

        [Header("Music")]
        public AudioClip titleTheme;
        private AudioSource musicSource;

        [Header("SFX Looping")]
        private AudioSource sfxLoopSource;

        private bool hasFadedOut = false;
        private float fadeDuration = 8f;

        void Awake()
        {
            if (Instance != null && Instance != this)
            {
                Destroy(gameObject);
                return;
            }

            Instance = this;
            DontDestroyOnLoad(gameObject);

            // Create audio sources
            musicSource = gameObject.AddComponent();
            musicSource.loop = true;
            musicSource.playOnAwake = false;

            sfxLoopSource = gameObject.AddComponent();
            sfxLoopSource.loop = true;
            sfxLoopSource.playOnAwake = false;

            ApplyVolumesFromOptions();
            PlayTitleTheme();
        }

        public void ApplyVolumesFromOptions()
        {
            if (AudioOptionsManager.Instance != null)
            {
                AudioListener.volume = AudioOptionsManager.Instance.MasterVolume;
                musicSource.volume = AudioOptionsManager.Instance.MusicVolume;
                sfxLoopSource.volume = AudioOptionsManager.Instance.SFXVolume;

                Debug.Log("[AudioManager] Volumes synced from AudioOptionsManager.");
            }
        }

        public void PlayTitleTheme()
        {
            if (titleTheme != null && !hasFadedOut)
            {
                musicSource.clip = titleTheme;
                musicSource.loop = true;
                musicSource.Play();
            }
        }

        public void StopMusic()
        {
            musicSource.Stop();
        }

        public void FadeOutMusic()
        {
            if (!hasFadedOut)
            {
                StartCoroutine(FadeOutRoutine());
            }
        }

        private IEnumerator FadeOutRoutine()
        {
            hasFadedOut = true;
            float startVolume = musicSource.volume;
            musicSource.loop = false;

            for (float t = 0; t  musicSource;
        public AudioSource SFXLoopSource => sfxLoopSource;
    }
}

Audio Options Manager (partial)

using UnityEngine;
using UnityEngine.UI;
using Audio;

public class AudioOptionsManager : MonoBehaviour
{
    public static AudioOptionsManager Instance { get; private set; }

    [Header("UI")]
    [SerializeField] private Slider masterSlider;
    [SerializeField] private Slider musicSlider;
    // ... (rest of the script)
}

Screenshot

Title Screen

That’s where things stand. Stay tuned for more updates, and maybe next year the Halloween results will finally appear! šŸŽƒ

[SerializeField] private Slider sfxSlider;
[SerializeField] private Button resetButton;
[SerializeField] private Button closeButton;

[Header("Audio Sources")]
[SerializeField] private AudioSource musicSource;
[SerializeField] private AudioSource sfxLoopSource;

public const float DefaultMasterVolume = 0.75f;
public const float DefaultMusicVolume = 0.75f;
public const float DefaultSFXVolume = 0.75f;

private float masterVolume = DefaultMasterVolume;
private float musicVolume = DefaultMusicVolume;
private float sfxVolume = DefaultSFXVolume;

public float MasterVolume => masterVolume;
public float MusicVolume   => musicVolume;
public float SFXVolume      => sfxVolume;

private void Awake()
{
    Instance = this;
}

private void Start()
{
    // Auto‑assign sources from AudioManager
    if (AudioManager.Instance != null)
    {
        if (musicSource == null)
            musicSource = AudioManager.Instance.MusicSource;

        if (sfxLoopSource == null)
            sfxLoopSource = AudioManager.Instance.SFXLoopSource;
    }

    // Wire UI
    masterSlider.onValueChanged.AddListener(OnMasterVolumeChanged);
    musicSlider.onValueChanged.AddListener(OnMusicVolumeChanged);
    sfxSlider.onValueChanged.AddListener(OnSFXVolumeChanged);
    resetButton.onClick.AddListener(OnResetAudio);
    closeButton.onClick.AddListener(OnClosePressed);

    // Initialize sliders
    masterSlider.value = masterVolume;
    musicSlider.value  = musicVolume;
    sfxSlider.value    = sfxVolume;

    ApplyVolumes();
}

private void OnMasterVolumeChanged(float value)
{
    masterVolume = Mathf.Clamp01(value);
    ApplyVolumes();
}

private void OnMusicVolumeChanged(float value)
{
    musicVolume = Mathf.Clamp01(value);
    ApplyVolumes();
}

private void OnSFXVolumeChanged(float value)
{
    sfxVolume = Mathf.Clamp01(value);
    ApplyVolumes();
}

private void OnResetAudio()
{
    masterVolume = DefaultMasterVolume;
    musicVolume  = DefaultMusicVolume;
    sfxVolume    = DefaultSFXVolume;

    masterSlider.value = masterVolume;
    musicSlider.value  = musicVolume;
    sfxSlider.value    = sfxVolume;

    ApplyVolumes();
}

private void ApplyVolumes()
{
    AudioListener.volume = masterVolume;

    if (musicSource != null)
        musicSource.volume = musicVolume;

    if (sfxLoopSource != null)
        sfxLoopSource.volume = sfxVolume;
}

private void OnClosePressed()
{
    // MenuManager handles showing/hiding the panel
    gameObject.SetActive(false);
}

UI Controls

  • Enter fullscreen mode
  • Exit fullscreen mode

A clean UI architecture

  • A proper menu flow
  • A credits panel that actually scrolls (growth!)

Progress is faster this time because I actually know Unity now.
I no longer open the editor, panic, and close it for two days.

Character development

🧩 5. The PlayFab Signup

At some point I also signed up for PlayFab (today).

Why? Future me will need:

  • Cloud saves
  • Player data
  • Inventory syncing
  • Maybe multiplayer
  • Maybe trading
  • Maybe a full backend economy

Or maybe I just like dashboards. Hard to say.

šŸƒ 6. The 310‑Card Database

Yes. I imported 310 cards into Unity, each with:

  • Names
  • Stats
  • Rarities
  • Factions
  • Lore
  • Effects
  • Spreadsheet‑driven data

Card database overview

This is the moment I realised:

ā€œOh. This isn’t a mini‑project anymore. This is a real game now.ā€

A few examples

Card 1Card 2
Card 1Card 2
Card 3Card 4

…and another 306 more (I was still busy, sidetracked a lot).

🧠 7. The Present Day

Right now the project has:

  • A clean title screen
  • A working settings panel
  • A scrolling credits panel
  • A global audio system
  • A database of 310 cards
  • A PlayFab backend ready to be used
  • A developer who is no longer afraid of Unity
  • A dev log that has risen from the ashes

From the dead

šŸŽ 8. What’s Next

In no particular order:

  • UI transitions
  • One‑shot SFX
  • Scene loading
  • Card binder
  • Card inspection
  • Gameplay prototype
  • More lore
  • More chaos
  • And maybe — just maybe — the Halloween challenge results.

Merry Christmas

Christmas image

Back to Blog

Related posts

Read more Ā»

LIVEHTML.net Sudoku Generator

Overview Sudoku UI Max is a fully interactive Sudoku game built using pure HTML, CSS, and vanilla JavaScript — no frameworks, no external libraries. The projec...

Day 1278 : No Longer Am

Professional Not a bad day. Had a couple of back‑to‑back meetings. I ran my idea by my manager for the project I'm working on and they agreed, so I started put...