왜 만들었나

고등학교 물리 시간 태양계 발표에 쓰려고 만들었다. 행성이 왜 도는지를 말로 설명하는 대신, 중력을 실제로 계산해서 도는 화면을 띄워 놓고 설명하고 싶었다.

항목내용
엔진Unity 2021.3.45f2
기여도100% (1인 개발)
용도고등학교 물리 시간 태양계 발표
다루는 것중력 상호작용 · 공전 궤도 · 블랙홀 전환
리소스VFX Graph와 Shader Graph로 전부 직접 제작

중력으로 돌게 만들기

태양을 중심에 두고, 각 행성이 중력에 반응해 공전 궤도를 그리도록 만들었다. 궤도를 애니메이션으로 미리 그려 두는 게 아니라 매 프레임 힘을 계산해서 움직인다.

Unity 에디터 씬 뷰의 우주 공간과, Hierarchy에 Sun 수성 금성 지구 화성 목성 토성 천왕성 해왕성 명왕성이 나열된 화면
에디터 화면. Star 아래에 태양과 행성들이 하나씩 들어가 있고, StarGrvitySystem 이 중력을 관장한다.

계층 구조를 보면 Star 아래에 태양과 아홉 개 천체가 각각 오브젝트로 들어가 있고, StarGrvitySystem 이 따로 있다. 중력 계산을 각 행성이 알아서 하는 게 아니라 한 곳에서 모아 처리하는 구조다.

왜 한곳에 모으는 편이 나은가중력은 모든 천체가 서로에게 작용한다. 각 행성이 자기 Update 에서 다른 모두를 찾아 계산하면 같은 쌍을 두 번씩 계산하게 되고, 프레임 중간에 위치가 갱신되면서 계산 기준이 어긋난다. 한 곳에서 전체 위치를 읽어 힘을 다 구한 뒤 한꺼번에 적용하면 그 문제가 없다.

궤적을 남긴다

어두운 우주 공간 중앙에 밝은 태양이 있고 그 주위로 자홍색 궤적이 여러 겹 원을 그리고 있는 화면
행성이 지나간 자리에 궤적이 남아 공전 궤도의 형태가 보인다.

행성이 지나간 자리에 발자취(Trail) 를 남겼다. 이게 없으면 점이 몇 개 움직이는 화면일 뿐이지만, 궤적이 쌓이면 궤도의 모양이 그대로 드러난다. 발표에서 "이게 공전 궤도다"라고 말할 때 가리킬 게 생긴다.

화면 위쪽에는 슬라이더가 하나 있다. 발표 중에 값을 조절해 가며 보여줄 수 있게 붙여 둔 것이다.

그 자리에 블랙홀이 갑자기 생긴다면

이 프로젝트에서 제일 보여주고 싶었던 장면이다. 시뮬레이션이 돌아가는 도중에 태양 자리에 블랙홀이 갑자기 나타나는 이벤트를 넣었다. 중심이 순식간에 훨씬 무거워지면, 지금까지 안정적으로 돌던 궤도가 그대로 있지 못한다.

중앙의 태양이 고리 형태의 블랙홀로 바뀌고 주변 궤적이 원형을 잃고 흩어진 화면
블랙홀로 바뀐 뒤. 궤적이 원을 그리지 못하고 바깥으로 흩어진다.

행성이 지나간 자리에 발자취(Trail) 를 남겨 뒀기 때문에, 궤도가 무너지는 과정이 잔상으로 남는다. 말로 "중심 질량이 바뀌면 궤도가 달라진다"고 하는 것과, 화면에서 궤적이 실제로 무너지는 걸 같이 보는 것은 다르다.

결과는 행성마다 갈렸다. 어떤 행성은 중심 쪽으로 확 말려 들어갔고, 어떤 행성은 궤적이 길게 늘어나며 바깥으로 흩어졌다. 같은 이벤트를 한 번 걸었는데 정반대로 움직이는 것이 발표에서 제일 반응이 좋았다.

갈리는 이유는 그 순간 행성이 어디에 어떤 속도로 있었느냐다. 중심이 무거워지면 같은 자리에서 받는 중력이 갑자기 커진다. 원래 속도로 그 힘을 버티지 못하는 행성은 안쪽으로 끌려 들어가고, 더 빠르고 멀리 있던 행성은 원 궤도가 길쭉한 타원으로 늘어나면서 한동안 바깥에 머문다.

아주 멀리 튕겨 나간 행성도 있었다. 이건 물리 현상이 아니라 계산이 놓친 것이다. 중심에 너무 가깝게 지나가는 짧은 순간을 시뮬레이션이 따라가지 못하면서 속도가 과하게 붙었다.

블랙홀이라서 흔들린 게 아니다블랙홀은 질량이 무한대인 천체가 아니다. 무한대에 가까운 건 밀도다. 궤도가 무너진 이유는 블랙홀이어서가 아니라 중심 질량이 갑자기 커져서다.

VFX Graph와 Shader Graph를 처음 만졌다

우주 공간, 행성 표면, 태양과 블랙홀의 시각 효과를 만들려고 Shader Graph와 VFX Graph를 이 프로젝트에서 처음 써 봤다. 노드를 연결해서 화면에 결과가 바로 나오는 방식이 낯설었지만, 코드로 셰이더를 쓰는 것보다 시작하기에는 쉬웠다.

블랙홀의 시각적 왜곡을 직접 만들어 본 것이 그래픽 프로그래밍의 기초를 다지는 계기가 됐다.

씬 로딩

발표 중 씬 전환이 끊기지 않도록 비동기 로딩에 진행률 바를 붙였다. 기상 시뮬레이션 과 같은 코드를 그대로 옮겨 썼다.

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;
            }
        }
    }
}

정리

이미지 한 장이 아니라 실시간으로 상호작용하는 시뮬레이션으로 물리 법칙을 설명할 수 있었다. 발표 자료로서는 제 몫을 했다.

기술적으로는 VFX Graph와 Shader Graph에 처음 발을 들인 프로젝트로 남았다. 우주 공간의 광활함이나 블랙홀의 왜곡 같은 건 코드만으로는 만들 수 없는 것들이었다.

당시 기록만들면서 남긴 글이 개인 블로그에 있다. 기록 보기