ZombieSurvival Item Random 생성, 삭제 및 GameManager, UIManager
20261027 ZombieSurvival Item Random 생성, 삭제 및 GameManager, UIManager
Item Random 생성
생성 자체는 ZombieSpawner와 비슷하다. 단 이번에는 생성위치를 몇가지로 지정해줬던 ZombieSpawner와 다르게 Random한 위치에 생성한다. 주의할점은 생성 위치를 NavMesh위의 Random한 위치로 생성해야 한다는 것이다. NavMesh로 한정하지않으면 Player가 갈 수 없는 위치에 Item이 생성될 수 있다.
IItem을 상속
Zombie나 Player가 IDamageable을 가진 LivingEntityclass를 상속받은 것 처럼 Item도 IItem 인터페이스를 생성하여 별도의 class(명칭은 임의라서 UseItem으로 지었음)에 부착하고 해당 class를 각 Item들이 상속받도록 한다.
충돌에 대한 처리는 Item에서 하거나 Player쪽에서 해도 되지만 나는 Item에서 하는걸로 작성했다.
충돌하면 Use 함수가 실행되고 자신을 비활성화. 이후 UseItem을 상속받은 Item에서는 Use함수만 override하면 되도록 해보았다.
// IItem을 상속받는 임의의 class.
public class UseItems : MonoBehaviour, IItem
{
public UnityEvent OnUse { get; set; } = new UnityEvent();
public void OnTriggerEnter(Collider other)
{
if(other.CompareTag("Player"))
{
Use(other.gameObject);
gameObject.SetActive(false);
}
}
public virtual void Use(GameObject target) {}
public virtual void OnDisable()
{
OnUse.Invoke();
}
}
Item위치 Random Spawn
SpawnPoint를 만들지 않고 Random 하게 생성하려면 범위를 한정해두고 Random하게 위치를 출력 후 Zombie가 NavMesh에서 벗어나지 않도록 확인 후 수정했던 것처럼 NavMesh의 SamplePosition을 통해서 수정해주면 된다.
// Random한 위치 생성 예시
[SerializeField] private float minX = -10f;
[SerializeField] private float minZ = -10f;
[SerializeField] private float maxX = 10f;
[SerializeField] private float maxZ = 10f;
private void Update()
{
Vector3 spawnPosition = new Vector3(Random.Range(minX, maxX), 0.5f, Random.Range(minZ, maxZ));
if(NavMesh.SamplePosition(spawnPosition, out NavMeshHit meshHit, 10f, NavMesh.AllAreas))
{
spawnPosition = meshHit.position;
spawnPosition.y = 0.5f;
GameObject newGo = itemPools[index][0];
newGo.transform.position = spawnPosition;
newGo.SetActive(true);
itemPools[index].Remove(newGo);
}
}
- 참고사항: Instantiate 할 때 바라보는 방향이 상관 없다면 기본값으로 주고 생성하는 것도 가능하다.
- Quaternion의 기본값: Quaternion.identity
GameManager와 UIManager
게임 전반에 걸쳐 필요한부분에 대한 관리를 하는 GameManager. Score에 대한 보관 및 Score의 UI 처리나 Player 사망시 UI 처리, 게임 재시작등을 수행한다. GameManager처럼 UI에 대한 전반적인 접근 및 관리를 하는 UIManager
GameOverUI 연결
UI와의 연결 혹은 현재 점수 등은 GameManager에서 관리하도록 작성했다. Player 사망시 Player가 직접 UI를 호출하는게 아니라 GamaManager에 사망을 알리고 GameManager에서 GameOverUI를 표시하도록 했다.
// player 사망시 Player가 GameManager에서 EndGame을 호출하면 GameManager가 UIManger에서 GameOverUI를 활성화 한다.
public void EndGame()
{
isGameOver = true;
uIManager.SetActiveGameOverUI(true);
itemSpawner.enabled = false;
zombieSpawner.OnEndGame();
zombieSpawner.enabled = false;
}
// 점수를 획득하는 상황에서 GameManager의 AddScore를 호출해서 점수를 저장하고 UI에도 표시한다.
public void AddScore(int add)
{
if(isGameOver)
{
return;
}
score += add;
uIManager.SetScore(score);
}
Item과 GameManager 연결
위에서 UseItems을 상속받은 각 Item class에서 Use를 재정의 하도록 했는데 현재 Coin Item만 점수에 관여하기 때문에 GameManager를 Coin Item에서 불러와서 가지고 있도록 했었다. 지금 생각해보니 이렇게 될 경우 나중에 점수에 관여할 Item을 추가할 때 Item별로 GameManager를 가지고 있어야 해서 Coin Item에서 불러올 필요 없이 UseItems에서 GameManager를 가지고 있어도 될 것 같다.



