이번 주에 작업할 목록
라운드 UI 표시LEVEL UP 시 사용할 팝업팝업에서 스킬을 upgrade 할 수 있도록 기능 추가
이였는데 라운드 UI 표시하기 위해 코드를 만지다가 코드 수정이 필요하다 느껴서 GameControl과 EnemyManager의 기능을 확실히 나눠야 했다.
- GameControl에 기대하는 로직은 Lobby Scene에서 Round를 선택할 때 Round의 정보를 문자열로 받아 EnemyManager에게 전달하기
- GameControl은 Round를 진행하며 EnemyManager에게 다음 Round의 Enemy들을 생성
- 추우 GameControl이 Player의 정보를 전달할 수 있도록 개발
이 정도로 생각하고 있다.
GameControl의 기능을 요약하면 라운드 진행, Player init, enemy init 정도가 좋을 것 같다.
GameControl Start 함수
void Start () {
dimmed.gameObject.SetActive(false);
// [TODO] Scene 변경 시 round의 정보를 받아야함.
// , == round
// # == monther type
// : == monther id and gen count
string enemyInfo = "1:5,1:5#2:1,1:4#2:2,1:3#2:3,1:5#2:4,1:6#2:6,1:3#2:4#3:2,1:2#2:6#3:5";
initEnemyList(enemyInfo);
}
enemyInfo를 하드코딩했지만 추후엔 Lobby Scene에서 받아올 예정이다.
enemyInfo의 값을 설명하면
","는 각 Round를 의미하고 "#"은 해당 Round의 생성할 Enemy다.
":"은 나눴을 때 왼쪽은 Enemy 유형이고 오른쪽은 생성할 Enemy 개수다.
GameControl initEnemyList 함수
void initEnemyList(string enemyStrInfo) {
string[] rounds = enemyStrInfo.Split(',');
enemyListByRound = new List<Dictionary<int, int>>();
Dictionary<int, int> dict = new Dictionary<int, int>();
for (int i = 0; i < rounds.Length; ++i) {
string enemys = rounds[i];
foreach (string enemy in enemys.Split('#')) {
string[] info = enemy.Split(':');
string enemyIdStr = info[0];
string enemyGenCntStr = info[1];
int enemyId = int.Parse(enemyIdStr);
int enemyGenCnt = int.Parse(enemyGenCntStr);
Debug.Log(i + " round. " + "enemyId: " +enemyId + " genCount: " + enemyGenCnt);
dict.Add(enemyId, enemyGenCnt);
}
enemyListByRound.Add(dict);
dict = new Dictionary<int, int>();
}
this.lastRound = enemyListByRound.Count;
EnemyManager enemyManager = enemyManagerObj.GetComponent<EnemyManager>();
enemyManager.setEnemyList(enemyListByRound);
}
initEnemyList 함수는 enemyInfo를 설정한 방식대로 문자열을 잘라서 EnemyManager Component에게 전달한다.
GameControl Update 함수
void Update() {
float t = Time.time;
if (nextRoundCooltime > t) {
return;
}
nextRoundCooltime = t + roundCooltime;
EnemyManager enemyManager = enemyManagerObj.GetComponent<EnemyManager>();
enemyManager.next();
++this.round;
}
Round를 설정한 시간마다 진행시킴.
다음은 EnemyManager 다.
EnemyManager next 함수
public void next() {
if (this.enemyList.Count == this.genIndex) {
Debug.Log("last round.");
return;
}
Dictionary<int, int> info = this.enemyList[this.genIndex];
Debug.Log("current: " + this.genIndex);
Dictionary<int, int>.Enumerator enumerator = info.GetEnumerator();
while (enumerator.MoveNext()) {
KeyValuePair<int, int> kvp = enumerator.Current;
int monsterType = kvp.Key;
int monsterGenCnt = kvp.Value;
GameObject prefab = getEnemyPrefab(monsterType);
genEnemys(prefab, monsterGenCnt);
}
++this.genIndex;
Debug.Log("next: " + this.genIndex);
}
GameControl Update 함수에서 next 함수를 호출할 때마다 Round의 정보를 순회하면서 Enemy의 Type의 Prefab을 불러온다.
EnemyManager getEnemyPrefab 함수
GameObject getEnemyPrefab(int monsterType) {
if (enemyPrefabs.ContainsKey(monsterType)) {
return enemyPrefabs[monsterType];
}
GameObject prefab = Resources.Load<GameObject>("Monsters/" + monsterType);
enemyPrefabs[monsterType] = prefab;
return prefab;
}
Resources.Load 함수로 Enemy의 prefab을 불러오고 멤버 변수에 캐싱한다.

EnemyManager getEnemys 함수
void genEnemys(GameObject prefab, int genCnt) {
StartCoroutine(genEnemy(prefab, genCnt));
}
IEnumerator genEnemy(GameObject monsterPrefab, int genCnt) {
int i = 0;
while (i < genCnt) {
Instantiate(monsterPrefab, getInitPosition(), Quaternion.identity);
yield return new WaitForSeconds(enemyGenCooltime);
++i;
}
}
Invoke 함수를 사용하려고 엄청 고민했는데 방법이 없어서 코루틴으로 작업했다. 아직 코루틴 개념이 없어서 최대한 동작할 수 있게만 공부하고 적용했다.
이번 리포트는 삶의 힘들어서 적다... ㅎㅎ;;
다음 주엔 스킬쪽을 작업할 예정이다.

'Unity > 땡땡마법사류' 카테고리의 다른 글
2025.02.17 ~ 2025.03.09 (0) | 2025.03.10 |
---|---|
2025.01.13 ~ 2025.02.02 (0) | 2025.02.03 |