1. Object Pool 분리 관리
기존에는 prefabs 배열 하나로 Bullet과 Enemy를 같이 관리했는데,
종류를 구분하기 위해 PoolKey Enum을 만들어 관리하도록 변경했다.
public enum PoolKey
{
PlayerBullet,
Enemy
}
ObjectPoolManager에서 Get(PoolKey key)로 종류를 명확히 지정하면,
총알과 적 프리팹을 구분해서 꺼내올 수 있다.
2. Bullet이 Enemy에 데미지를 직접 적용
기존 구조에서는 Enemy가 Bullet을 참조해서 데미지를 가져왔지만,
이러면 Enemy가 Bullet의 내부를 알아야 해서 의존성이 생긴다.
그래서 Bullet이 Enemy의 TakeDamage()를 직접 호출하게 변경했다.
private void OnTriggerEnter2D(Collider2D collision)
{
if (collision.CompareTag("Enemy"))
{
Enemy enemy = collision.GetComponent<Enemy>();
if (enemy != null)
{
enemy.TakeDamage(damage);
}
gameObject.SetActive(false);
}
}
3. GameManager 리팩터링 (Enemy 스폰)
GameManager에서 Enemy를 스폰할 때,
필드에 Enemy를 직접 들고 있지 않고 풀에서 꺼낸 Enemy에서 speed를 가져오는 방식으로 변경했다.
IEnumerator MonsterSpawn()
{
GameObject monster = ObjectPoolManager.Instance.Get(PoolKey.Enemy);
Enemy enemyScript = monster.GetComponent<Enemy>();
Rigidbody2D rb = monster.GetComponent<Rigidbody2D>();
monster.transform.position = enemySp.position;
rb.velocity = enemySp.up * enemyScript.speed;
yield return null;
}
Enemy 속도를 Enemy 스크립트에서 관리하므로 몬스터별 속도 설정 가능
GameManager는 언제, 어디서 스폰할지만 책임짐
4. Enemy가 Player와 충돌 시 멈추기
Enemy에 OnTriggerEnter2D()를 구현해서 Player에 닿으면 속도를 0으로 만든다.
private void OnTriggerEnter2D(Collider2D collision)
{
if (collision.CompareTag("Player"))
{
rb.velocity = Vector2.zero;
Debug.Log($"{gameObject.name} → 플레이어 충돌, 이동 정지");
}
}
Player 오브젝트에 Tag를 "Player"로 설정
Enemy 또는 Player 중 한쪽에는 Rigidbody2D 필요
닿는 동안 멈추게 하려면OnTriggerStay2D()도 가능
떨어졌을 때 다시 이동하려면 OnTriggerExit2D()에서 속도 부여
오브젝트 풀링은 종류별로 구분하면 나중에 관리가 훨씬 편하다.
ObjectPoolManager
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public enum PoolKey
{
PlayerBullet,
//EnemyBullet,
Enemy
}
public class ObjectPoolManager : Singleton<ObjectPoolManager>
{
[System.Serializable]
public class Pool
{
public PoolKey key;
public GameObject prefab;
}
public Pool[] poolsConfig;
private Dictionary<PoolKey, List<GameObject>> poolsDict;
private void Awake()
{
poolsDict = new Dictionary<PoolKey, List<GameObject>>();
foreach (var config in poolsConfig)
{
poolsDict[config.key] = new List<GameObject>();
}
}
public GameObject Get(PoolKey key)
{
var list = poolsDict[key];
GameObject select = null;
foreach (GameObject item in list)
{
if (!item.activeSelf)
{
select = item;
select.SetActive(true);
return select;
}
}
var prefab = System.Array.Find(poolsConfig, p => p.key == key).prefab;
select = Instantiate(prefab, transform);
list.Add(select);
return select;
}
}