TIL (86) | 2023.11.27 | Sector 코드 구조 개선

kjg5370·2023년 11월 27일
0

TIL

목록 보기
84/91
post-thumbnail

들어가기 앞서

오늘은 개발중인 게임의 Sector부분이 구조적 문제가 있다는 지적을 받아서 코드를 개선하게 되었습니다.

오늘 배운 것

  • 각 코드의 역할 문제

    • Sector 클래스:

      초기 목적: 구간을 나눠서 각 구간에 맞게 적을 생성하고 관리.
      현재 역할: Manager 역할이 강화되어 전체 구간들을 관리하고, 다음 구간으로의 이동 등을 담당.
      설명: 초기에는 각 구간에서의 적 생성 및 관리가 주 목적이었지만 시간이 지나면서 Manager 역할이 강화되어 전체적인 구간들을 통합적으로 관리하고, 다음 구간으로의 전환을 처리.

    • EnemySpawner 클래스:

      주요 기능: 적을 생성하고, 생성에 필요한 포지션 데이터를 관리.
      확장성: 적을 생성하는 역할을 수행하고, 생성에 필요한 위치 데이터를 관리함. 이는 새로운 적의 타입이나 다양한 위치에 적을 생성하고자 할 때 확장성이 낮음.
      Sector 클래스와 EnemySpawner 간의 관계 : Sector가 EnemySpawner를 구간 별로 가지고 있기 때문에 하위에 있는 느낌이 강한 EnemySpawner가 위치데이터를 가지고 있을 필요가 없음.

  • 해결 방법
    Sector클래스의 이름을 SectorController로 바꾼 후 EnemySpawner의 적 생성 함수를 Sector가 가지고 있도록 변경.
    EnemySpawner 클래스 삭제.
    위치데이터에 위치 뿐 아니라 적 타입, SectorIndex를 추가하여 구간을 구분해서 적을 생성.

  • 코드

    • EnemySpawnData

      public enum StatsChangeType
      {
          Melee,
          Rifle,
          Sniper,
          Sniper2,
          Elite,
      }
      
      public class EnemySpawnData : ScriptableObject
      {
          public int sectorIdx;
          public StatsChangeType statsChangeType = StatsChangeType.Rifle;
          // targetPositions -> enemy
          public Vector3 position;
      }
    • SectorController 의 적 생성

        public void SpawnEnemie(EnemySpawnData spawnData)
          {
              GameObject enemy = null;
      
              switch (spawnData.statsChangeType)
              {
                  case StatsChangeType.Melee:
                      enemy = enemyPrefabMelee[Random.Range(0, enemyPrefabMelee.Length)];
                      break;
                  case StatsChangeType.Rifle:
                      enemy = enemyPrefabRifle[Random.Range(0, enemyPrefabRifle.Length)];
                      break;
                  case StatsChangeType.Sniper:
                      enemy = enemyPrefabSniper[Random.Range(0, enemyPrefabSniper.Length)];
                      break;
                  case StatsChangeType.Sniper2:
                      enemy = enemyPrefabStandingSniper[Random.Range(0, enemyPrefabStandingSniper.Length)];
                      break;
                  case StatsChangeType.Elite:
                      enemy = enemyPrefabElite;
                      break;
              }
      
              if (enemy == null)
                  return;
      
              enemy = Instantiate(enemy, spawnData.position, Quaternion.identity);
      
              Health enemyHealth = enemy.GetComponent<Health>();
              enemyHealth.OnDie += OnEnemyDied;
              enemyCount++;
      
              spawnedEnemies.Add(enemy);
          }

      생성할 오브젝트의 프리팹을 받아와 타입별로 랜덤한 스킨을 넣은 후 포지션 값에 생성을 함.

  • 위치 데이터들

  • 위치데이터를 모을 컨테이너

    SectorController에게 위치데이터들을 전달하는 역할

기억 할 것

  • 데이터와 동작의 분리
    클래스는 주로 데이터를 표현하는데 집중하고, 해당 데이터를 처리하는 기능은 다른 클래스에 위임하는 것이 좋음.
    이렇게 하면 변경이 발생할 때 특정 부분만 수정하면 되므로 유지보수가 훨씬 쉬워짐.

  • 의존성 역전
    상위 수준 모듈은 하위 수준 모듈에 의존해서는 안되며, 양쪽 모두 추상화에 의존해야 함.
    추상화를 통해 인터페이스를 정의하고, 이를 구현하는 하위 수준 모듈을 분리함으로써 데이터와 기능을 더욱 효과적으로 분리할 수 있음.

내일 할 일

재시작 만들기
저장 만들기

profile
학생입니다

0개의 댓글