왜 만들었나Why I Built It

고등학교 지구과학 시간 발표 자료로 쓰려고 만들었다. 기상 현상(태풍, 뇌우, 우박)이 어떻게 생기는지를 슬라이드로 설명하는 대신, 실제로 돌아가는 3D 화면을 띄워 놓고 발표하고 싶었다.

I built this as visual material for a high school Earth Science presentation. Instead of explaining how typhoons, thunderstorms, and hail form using static slides, I wanted to run a live 3D scene on screen while speaking.

좌우로 밀어서 표 전체 내용을 확인하세요
항목내용
엔진Unity 2021.3.45f2
기여도100% (1인 개발)
용도고등학교 지구과학 시간 발표
다루는 현상태풍 · 뇌우 · 우박
리소스파티클 효과와 텍스처 에셋 전부 직접 제작
Swipe horizontally to view the full table
ItemDetails
EngineUnity 2021.3.45f2
Role100% (Solo development)
PurposeHigh school Earth Science class presentation
Phenomena CoveredTyphoons · Thunderstorms · Hail
AssetsAll particle effects and texture assets made from scratch

PPT를 넘기는 것보다 직관적인 3D 자료가 있으면 듣는 쪽이 이해하기 쉬울 거라고 봤다. 발표의 질을 높이는 게 목적이었지 게임을 만들 생각은 아니었다.

I figured an interactive 3D visual would be much easier for classmates to follow than flipping through PowerPoint slides. The goal was a clearer presentation, not making a game.

뇌우와 우박 — 파티클Thunderstorms and Hail — Particle System

먹구름 아래로 번개와 비가 내리고 집 두 채가 놓인 뇌우 시뮬레이션 화면. 우측 상단에 우박/뇌우 버튼이 있다
뇌우 화면. 오른쪽 위 버튼으로 우박과 뇌우를 전환한다.Thunderstorm view. The button in the top-right corner toggles between hail and thunderstorm modes.

번개, 비, 우박 입자는 파티클 시스템으로 만들었다. 이쪽은 기획한 대로 나왔다. 구름 아래로 떨어지는 것들의 밀도와 속도만 조절하면 우박과 비의 차이가 화면에서 바로 구분된다.

Lightning, rain, and hailstones were built with Unity's Particle System. This part came out just as planned. Simply tuning the emission density and fall speed beneath the cloud layer made hail and rain immediately distinguishable on screen.

설명하기 적합한 형태가 우선사실적으로 만드는 것과 설명하기 좋게 만드는 것은 다르다. 실제 뇌우는 훨씬 어수선하지만, 발표에서는 상승 기류 → 구름 형성 → 강수라는 흐름이 눈에 보여야 한다. 그래서 입자 수를 줄이고 경로를 단순하게 잡는 쪽을 택했다.
Clarity Over PhotorealismMaking something look realistic and making it easy to explain are two different problems. A real thunderstorm is chaotic, but for a class presentation, the sequence of updraft → cloud formation → precipitation had to read clearly from across the room. So I lowered the particle count and kept the motion paths simple.

태풍 — 셰이더Typhoon — Custom Mesh and Shader

태풍은 파티클로 풀 수 없었다. 소용돌이 형태 자체가 모양을 가져야 했기 때문이다. 나선형 메시를 만들고 거기에 셰이더를 입혀 회전하는 구름 덩어리로 보이게 했다.

A typhoon could not be solved with particles alone because the vortex needed a defined silhouette. I modeled a spiral mesh and applied a scrolling shader so it looked like a rotating cloud mass.

Unity 에디터 씬 뷰에서 위에서 내려다본 나선형 소용돌이 메시와, 아래 게임 뷰에 보이는 태풍 형태
에디터에서 본 태풍 오브젝트. 위에서 보면 나선 형태의 메시다.The typhoon object in the Unity Editor. Viewed from above, it is a spiral mesh.
바다 위에 떠 있는 흰색 소용돌이 구름 덩어리
바다 위에 띄운 결과 화면.The resulting typhoon rendered over an ocean surface.
여기는 의도대로 안 됐다처음 기획했던 태풍의 형태가 생각대로 구현되지 않아 허리케인에 더 가까운 형태가 됐다. 발표를 진행하고 원리를 설명하는 데에는 문제가 없었지만, 만들려던 모양은 아니었다. 반대로 뇌우와 우박 파티클은 기획 의도대로 잘 묘사됐다.
What Did Not Go as PlannedThe typhoon shape I originally envisioned did not come out quite right, ending up closer to a funnel-like hurricane structure. It was good enough for explaining the mechanism during the presentation, but it was not the exact shape I had in mind. By contrast, the thunderstorm and hail particles matched my initial plan.

발표 흐름에 맞춰 단계를 넘기기Stepping Through Stages During the Talk

기상 현상은 순서가 있다. 수증기가 증발하고, 상승 기류가 생기고, 구름이 만들어지고, 비나 우박이 내린다. 이 순서를 발표 타이밍에 맞춰 넘길 수 있어야 했다.

Weather phenomena happen in stages: water vapor evaporates, updrafts form, clouds build up, and rain or hail falls. I needed to advance through those stages on cue while speaking.

count 변수 하나를 올리면서 각 단계에 해당하는 파티클 오브젝트를 켜고 끄는 구조로 만들었다. 상태 머신처럼 동작한다.

I wired a single count variable so each click incremented the stage and toggled the corresponding particle GameObjects on or off, acting like a simple state machine.

count += 1;

if (count == 5)
{
    // 모든 이펙트 비활성화 및 초기화
    count = -1;
    rainPar.SetActive(false);
    rainPar2.SetActive(false);
    tT1.SetActive(false);
    // ...
}
else if (count == 1)
{
    // 상승 기류 및 초기 구름 형성
    tT1.SetActive(true);
    upAir1.SetActive(true);
    upAir2.SetActive(true);
}
else if (count == 2)
{
    // 본격적인 뇌우/우박 파티클 재생
    tT2.SetActive(true);
    tT3.SetActive(true);
    rainPar.SetActive(true);
    upAir1.SetActive(false);
    tTen1.SetActive(true);
}
// ... (이후 단계 생략)
count += 1;

if (count == 5)
{
    // Disable all effects and reset
    count = -1;
    rainPar.SetActive(false);
    rainPar2.SetActive(false);
    tT1.SetActive(false);
    // ...
}
else if (count == 1)
{
    // Updrafts and initial cloud formation
    tT1.SetActive(true);
    upAir1.SetActive(true);
    upAir2.SetActive(true);
}
else if (count == 2)
{
    // Main thunderstorm/hail particle playback
    tT2.SetActive(true);
    tT3.SetActive(true);
    rainPar.SetActive(true);
    upAir1.SetActive(false);
    tTen1.SetActive(true);
}
// ... (subsequent stages omitted)

지금 이 코드를 읽으면Looking Back at This Code Now

발표 중에 끊기지 않게Keeping Scene Transitions Smooth During the Talk

씬을 넘길 때 화면이 멈추면 발표 흐름이 끊긴다. 비동기 로딩(LoadSceneAsync)에 진행률 바를 붙였다.

A frozen screen between scenes would break the flow of the presentation, so I attached a progress bar to async scene loading (LoadSceneAsync).

IEnumerator LoadScene(string name)
{
    lodingImg.SetActive(true);
    yield return null;
    AsyncOperation op = SceneManager.LoadSceneAsync(name);
    op.allowSceneActivation = false;
    float timer = 0.0f;

    while (!op.isDone)
    {
        yield return null;
        timer += Time.deltaTime;
        if (op.progress < 0.9f)
        {
            progressBar.fillAmount = Mathf.Lerp(progressBar.fillAmount, op.progress, timer);
            if (progressBar.fillAmount >= op.progress) timer = 0f;
        }
        else
        {
            progressBar.fillAmount = Mathf.Lerp(progressBar.fillAmount, 1f, timer);
            if (progressBar.fillAmount == 1.0f)
            {
                op.allowSceneActivation = true;
                yield break;
            }
        }
    }
}

이 코드는 자동차 오픈월드 의 메인 메뉴에 쓴 것과 같다. 오타(lodingImg)까지 그대로다. 한 번 만들어 둔 것을 다음 프로젝트에 그대로 옮겨 쓴 흔적이다.

This is the exact same coroutine I used in the main menu of Car Open World—right down to the lodingImg typo. I copied my working script straight into the next project.

정리Wrap-Up

게임이 아니라 교육용 시뮬레이션을 만들면서, 기상 현상을 유니티의 입자 제어와 셰이더로 풀어내는 경험을 했다. 파티클 시스템을 이때 처음 제대로 다뤘다.

Building an educational simulation rather than a game was my first proper hands-on practice with Unity's particle system and shaders.

형태를 가진 것(태풍)과 흩뿌려지는 것(비·우박·번개)은 접근이 다르다는 것도 여기서 배웠다. 전자는 메시와 셰이더, 후자는 파티클이다. 둘을 바꿔서 시도했다면 훨씬 오래 걸렸을 것이다.

It also taught me that phenomena with a coherent volume (typhoons) and phenomena made of scattered elements (rain, hail, lightning) require different tools: meshes and shaders for the former, particles for the latter. Trying to force them the other way around would have taken much longer.

당시 기록만들면서 남긴 글이 개인 블로그에 있다. 기록 1 · 기록 2
Original NotesMy notes from when I built this are on my personal blog: Log 1 · Log 2