적을 일정 시간마다 맵 좌표 밖에서 소환하는 코드를 작성함
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class EnemySpawner : MonoBehaviour
{
//적 프리팹 리스트
public GameObject[] enemyPrefab;
//적 스폰 타임
//public float maxSpawnTime;
//public float curSpawnTime;
//맵 크기 좌표 x,z
public int[] spawnPos = new int[2];
public float spawnRange;
public int selection;
private void Start()
{
}
// spawnPos = 1024 x 1080
// 1024 / 2 = -512 ~ 512
// 1080 / 2 = -540 ~ 540
// Random 0 1
// 0 : -pos
// float posX = Random.Range(-700f, -512f);
// 1 : +pos
// float posX = Random.Range(+512f, 700f);
public void EnemySpawn()
{
//정해진 적 선택 후 생성
GameObject selectPrefab = enemyPrefab[selection];
GameObject enemy = Instantiate(selectPrefab);
//소환할 좌표
float posX;
float posZ;
int pos = Random.Range(0, 4);
if (pos == 0)
{
posX = Random.Range((-spawnPos[0] / 2) - spawnRange, 0);
if(posX < -spawnPos[0] / 2)
{
posZ = Random.Range(0, spawnPos[1] / 2 + spawnRange);
}
else
{
posZ = Random.Range(spawnPos[1] / 2, spawnPos[1] / 2 + spawnRange);
}
}
else if (pos == 1)
{
posX = Random.Range(0, spawnPos[0] / 2 + spawnRange);
if (posX > spawnPos[0] / 2)
{
posZ = Random.Range(0, spawnPos[1] / 2 + spawnRange);
}
else
{
posZ = Random.Range(spawnPos[1] / 2, spawnPos[1] / 2 + spawnRange);
}
}
else if (pos == 2)
{
posX = Random.Range(0, spawnPos[0] / 2 + spawnRange);
if (posX > spawnPos[0] / 2)
{
posZ = Random.Range(-(spawnPos[1] / 2 + spawnRange), 0);
}
else
{
posZ = Random.Range(-(spawnPos[1] / 2 + spawnRange), -(spawnPos[1] / 2));
}
}
else
{
posX = Random.Range((-spawnPos[0] / 2) - spawnRange, 0);
if (posX < -spawnPos[0] / 2)
{
posZ = Random.Range(-(spawnPos[1] / 2 + spawnRange), 0);
}
else
{
posZ = Random.Range(-(spawnPos[1] / 2 + spawnRange), -(spawnPos[1] / 2));
}
}
enemy.transform.position = new Vector3(posX, 0.5f, posZ);
}
public void Update()
{
}
}
spawnPos[] 배열에 각각 x와 z좌표(가로, 세로)를 유니티에서 맵 크기만큼 할당해준 후 맵 외부에서 스폰이 되는 방식이다.
Random.Range(0,4)를 통해 0~3의 변수값을 얻고, 이 변수에 따라 1~4사분면에 해당하는 부분에 스폰이 된다.
1사분면이라고 가정한다면 노란색 부분에 스폰이 되어야하므로 x값을 랜덤으로 뽑아서 맵보다 작은 수치라면 z값을 맵 밖으로 하게 하였고, x값이 이미 맵보다 크다면 z값을 1사분면에 랜덤으로 뽑히게 하였다.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class WaveSystem : MonoBehaviour
{
EnemySpawner spawner;
public int waveStage;
int[] SpawnNum = new int[5];
enum enemySelection
{
basic = 0,
rush = 1,
interrupt = 2,
tanker = 3,
healer = 4,
}
private void Start()
{
spawner = GameObject.Find("spawner").GetComponent<EnemySpawner>();
waveStage = 0;
}
void Wave1()
{
SpawnNum = new int[] {7, 3, 0, 0, 0};
SpawnWave(SpawnNum);
}
void Wave2()
{
SpawnNum = new int[] {10, 5, 0, 0, 0};
SpawnWave(SpawnNum);
}
void SpawnWave(int[] roopTime)
{
for(int i = 0; i < spawner.enemyPrefab.Length; i++)
{
spawner.selection = i;
for(int j = 0; j < roopTime[i]; j++)
{
spawner.EnemySpawn();
}
}
waveStage = 0;
}
void waveManage()
{
switch (waveStage)
{
case 1:
Wave1();
break;
case 2:
Wave2();
break;
default:
break;
}
}
private void Update()
{
waveManage();
}
}
EnemySpawner에 enemyPrefab 배열에 타입별 적들이 들어가 있고, selectPrefab에 enum형태인 enemySelection에 해당하는 적들을 골라서 해당 웨이브가 선언되었다면 SpawnNum에 타입별 적에 대한 수를 반복문으로 스폰해준다.
이제 웨이브 타임에 관한 스크립트이다
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class WaveManager : MonoBehaviour
{
//웨이브 시간 관련 필드
float waveTime;
float waveTimer;
int timeAdder;
GameObject enemyAlive;
//현재 웨이브
public int wave;
//코드 참조
WaveSystem waveSystem;
//UI
GameObject timer;
// Start is called before the first frame update
void Start()
{
waveTime = 10f;
waveTimer = 10f;
timeAdder = 5;
wave = 0;
waveSystem = GameObject.Find("waveSystem").GetComponent<WaveSystem>();
timer = GameObject.Find("Timer");
}
void TimeAdd()
{
enemyAlive = GameObject.FindWithTag("Enemy");
//몹이 전부 죽은 경우 wave 카운트 다운
if (enemyAlive == null)
{
timer.SetActive(true);
waveTime -= Time.deltaTime;
}
else
{
timer.SetActive(false);
}
}
void waveStarter()
{
if(waveTime < 0f)
{
wave += 1;
waveSystem.waveStage = wave;
Debug.Log(wave + " 웨이브 시작");
waveTime = waveTimer + (timeAdder * waveSystem.waveStage);
}
}
void VisualizeTimer()
{
timer.GetComponent<Text>().text = "다음 웨이브까지 " + (int)waveTime + "초";
}
// Update is called once per frame
void Update()
{
TimeAdd();
waveStarter();
VisualizeTimer();
}
}
기본 웨이브 타임은 10초이고 웨이브 타임은 기본 웨이브타임 +(시간 가중치 * 스테이지 수)로 해놨다
또한 적이 살아있는 경우 타이머를 진행시키지 않고 UI를 비활성화 시켰다
0초이하가 되면 웨이브가 시작되게 waveSystem에 waveStage에 wave를 넣어서 웨이브를 실행시키고 웨이브 변수값을 증가시켰다
아래는 구현한 것을 영상으로 찍었다
'Unity' 카테고리의 다른 글
[TowerDefence] 타워 디펜스 게임 마무리 및 코드 정리 (0) | 2023.04.17 |
---|---|
[턴제 생존 게임] We Mustn't Die Here (0) | 2023.04.14 |
[타워디펜스] 타워 철거기능 구현 (0) | 2023.02.03 |
[타워디펜스] 메뉴UI와 자기장 (0) | 2023.01.13 |
[타워 디펜스] 플레이어 만들기 (0) | 2022.12.30 |