각 코드의 역할 문제
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에게 위치데이터들을 전달하는 역할
데이터와 동작의 분리
클래스는 주로 데이터를 표현하는데 집중하고, 해당 데이터를 처리하는 기능은 다른 클래스에 위임하는 것이 좋음.
이렇게 하면 변경이 발생할 때 특정 부분만 수정하면 되므로 유지보수가 훨씬 쉬워짐.
의존성 역전
상위 수준 모듈은 하위 수준 모듈에 의존해서는 안되며, 양쪽 모두 추상화에 의존해야 함.
추상화를 통해 인터페이스를 정의하고, 이를 구현하는 하위 수준 모듈을 분리함으로써 데이터와 기능을 더욱 효과적으로 분리할 수 있음.
재시작 만들기
저장 만들기