본문 바로가기
Unity/땡땡마법사류

2025.02.03 ~ 2025.02.16

by 윤원용 2025. 2. 17.

이번 주에 작업할 목록

  1. 라운드 UI 표시
  2. LEVEL UP 시 사용할 팝업
  3. 팝업에서 스킬을 upgrade 할 수 있도록 기능 추가

이였는데 라운드 UI 표시하기 위해 코드를 만지다가 코드 수정이 필요하다 느껴서 GameControl과 EnemyManager의 기능을 확실히 나눠야 했다.

 

  1. GameControl에 기대하는 로직은 Lobby Scene에서 Round를 선택할 때 Round의 정보를 문자열로 받아 EnemyManager에게 전달하기
  2. GameControl은 Round를 진행하며 EnemyManager에게 다음 Round의 Enemy들을 생성
  3. 추우 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을 불러오고 멤버 변수에 캐싱한다.

Resources .Load 함수의 경로

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