[개발 일기] 프로젝트 최적화하기(1)

muchan
muchan
∙∙조회 1

공고를 보는데 이런 조건을 발견했습니다. 지금까지 포트폴리오 ppt에 코드 내용은 안넣고 코드 구조를 보여주는 형식으로 만들었는데, 이 기회에 소스 코드를 포함한 포트폴리오를 하나 만들려고했습니다. 물론 저 공고는 마감됐지만 어쨌든 하나 만들어두면 잘 쓰일거 같고 나중에 면접 대비에도 좋을 것 같아서 오늘 작업을 하려고 했습니다.

근데 막상 작업을 시작하려고 보니 어떤걸 어필해야하는지 감이 잘 안오고, '더 좋게 구현할 수 있었는데 이걸 왜 이렇게 짰을까?'하는 코드들도 몇 개 보였습니다. 그래서 일단은 최적화 경험도 쌓을 겸 불필요한 비용이 발생하는 코드를 찾아서 개선해보기로 했습니다. 먼저 첫 번째는 제 프로젝트에서 나무가 등장하는데 나무가 플레이어를 가리면 나무를 투명화 시키는 코드가 있었습니다.

아래는 해당 코드의 Update 부분입니다.

csharp
private void Update()
    {
        HashSet<GameObject> hitLeaves = new();
        HashSet<Renderer> hitRenderers = new();

        Vector3 direction = cam.transform.position - player.position;
        float distance = direction.magnitude;

        RaycastHit[] hits = Physics.SphereCastAll(
            player.position,
            sphereRadius,
            direction.normalized,
            distance,
            canopyLayer
        );

        foreach (var hit in hits)
        {
            Transform canopy = hit.collider.transform;

            // 나뭇잎 처리
            Transform leaves = canopy.Find(leavesBoneName);
            if (leaves != null)
            {
                hitLeaves.Add(leaves.gameObject);
                if (leaves.gameObject.activeSelf)
                {
                    leaves.gameObject.SetActive(false);
                    hiddenLeaves.Add(leaves.gameObject);
                }
            }

            // 줄기 처리
            Transform trunk = canopy.Find(trunkBoneName);
            if (trunk != null)
            {
                foreach (var rend in trunk.GetComponentsInChildren<Renderer>())
                {
                    hitRenderers.Add(rend);
                    if (!fadedRenderers.Contains(rend))
                    {
                        rend.material = transparentMaterial;
                        fadedRenderers.Add(rend);
                    }
                }
            }
        }

        // 나뭇잎 복원
        List<GameObject> toShow = new();
        foreach (var leaf in hiddenLeaves)
        {
            if (!hitLeaves.Contains(leaf))
            {
                if (leaf != null)
                    leaf.SetActive(true);
                toShow.Add(leaf);
            }
        }
        foreach (var leaf in toShow)
            hiddenLeaves.Remove(leaf);

        // 줄기 복원
        List<Renderer> toRestore = new();
        foreach (var rend in fadedRenderers)
        {
            if (!hitRenderers.Contains(rend))
            {
                if (rend != null)
                    rend.material = originalMaterial;
                toRestore.Add(rend);
            }
        }
        foreach (var rend in toRestore)
            fadedRenderers.Remove(rend);
    }

아마 이거 구현할때 밀린 작업이 너무 많았어서 검토를 대충하고 넘어갔던 것 같은데, 지금 다시 보니 정말 쓰레기 같은 코드 군요. 업데이트에서 HashSet, List를 새로 생성하고 거기에 Find에, GetComponentsInChildren에.. 안좋은 코드들을 다 때려박았네요.

우선 Profiler에서 해당 스크립트를 찾아본 결과 GC Alloc이 2.3KB가 나오네요.
최적화를 하고 나서 이후 어떻게 변하는지 한번 비교해보려고 합니다.

하지만.. 최적화는 내일할 것 같습니다..

사실 그동안 프로젝트 하면서 AI한테 '해줘' 모드였기 때문에 오늘부터는 스스로 코드를 작성해보려 합니다. 그러다보니 작업 속도가 매우 늦어져 내일 완료될 것 같습니다. 빨리 작업 완료해서 포폴도 완성하고 새로운 프로젝트도 시작해야할 것 같지만, 오늘 코딩 작업하는거 보니 많이 심각한 상태여서 당분간 실력을 키우는데 집중하려고 합니다.

요즘 C++도 시작해야하나 고민이 많았지만 C++은 무슨.. 일단 C#부터 다시 감 찾고 그때 다시 생각해봐야할 것 같습니다. 그래도 학원 다닐때 초반에는 AI한테 이상한 부분 있는지만 질문해서 고치고 그랬는데, 어느 순간 '해줘'만 하더니 감이 다 떨어졌네요.. AI를 잘 쓰지도 못하는데 의존도만 높은 것 같습니다.. 허허.. 씁슬하군요.. 아무튼 2편은 내일 수정해서 올려보도록 하겠습니다.