기존에는 대부분의 상황에서 Instantiate()를 사용해 오브젝트를 복사하는 방법을 사용했었다.
그러나 계속되는 생성과 삭제로 메모리를 많이 사용하게 되어 다른 방법이 필요했고, 오브젝트 풀링을 알게 되었다.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class MonsterSpawner : MonoBehaviour
{
public static MonsterSpawner instance;
public Monster monsterPrefab;
public Player player;
public Queue<Monster> monsterSpawnQueue = new Queue<Monster>();
BoxCollider rangeCollider;
private void Awake()
{
instance = this;
rangeCollider = GetComponent<BoxCollider>();
StartCoroutine(SpawnTime());
}
private void CreateMonster(int _count)
{
for(int i = 0; i < _count; i++)
{
Monster monsterSpawn = Instantiate(monsterPrefab, RandomPosition(),transform.rotation, transform);
monsterSpawnQueue.Enqueue(monsterSpawn);
}
}
IEnumerator SpawnTime()
{
yield return new WaitForSeconds(3f);
CreateMonster(10);
}
public void ReturnQueue(Monster _gameObject)
{
_gameObject.gameObject.SetActive(false);
monsterSpawnQueue.Enqueue(_gameObject);
Invoke("GetQueue", 7f);
}
public Monster GetQueue()
{
Monster getGameObject = monsterSpawnQueue.Dequeue();
gameObject.transform.position = RandomPosition();
getGameObject.gameObject.SetActive(true);
return getGameObject;
}
private Vector3 RandomPosition()
{
Vector3 originPosition = transform.position;
float spawnX = Random.Range((rangeCollider.bounds.size.x /2)*-1, (rangeCollider.bounds.size.x/2));
float spawnZ = Random.Range((rangeCollider.bounds.size.z /2)*-1, (rangeCollider.bounds.size.z/2));
Vector3 newPosition = new Vector3(spawnX, 0f, spawnZ);
Vector3 respawnPosition = originPosition + newPosition;
return respawnPosition;
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;
using UnityEngine.Events;
public class Monster : MonoBehaviour
{
public static Monster instance;
public static UnityAction<Monster> onSpawn;
public UnityAction onDie;
public NavMeshAgent monsterNav;
public GameObject monsterDropItem;
public Transform monsterDropItemPosition;
public string monsterName;
public float hp;
public float maxHp;
public float defence;
public int monsterExp;
public float monsterSpeed;
public float playerDistance;
public Player target;
public bool isWalk;
public bool isAttack;
public bool isSafeZoneIn;
private void OnEnable()
{
onSpawn(this);
monsterNav = GetComponent<NavMeshAgent>();
MonsterNavMeshMove(monsterSpeed);
hp = (int)maxHp;
}
public void Start()
{
onDie += Die;
onDie += DropExp;
}
public void Die()
{
MonsterSpawner.instance.ReturnQueue(this);
}
public void DropExp()
{
PlayerState.instance.CurreunExp += monsterExp;
PlayerState.instance.MonsterHunterCount++;
}
public void DropItem()
{
GameObject _dropItem = Instantiate(monsterDropItem, monsterDropItemPosition);
_dropItem.transform.parent = null;
}
public void MonsterNavMeshMove(float _monsterSpeed)
{
if(isSafeZoneIn == true)
{
return;
}
playerDistance = (target.transform.position - transform.position).magnitude;
if (playerDistance < 20 && 2 < playerDistance)
{
isWalk = true;
monsterNav.SetDestination(target.transform.position);
}
if (playerDistance <= 2)
{
isWalk = false;
isAttack = true;
monsterNav.SetDestination(transform.position);
if(isAttack == true)
{
Attack();
}
}
}
public virtual void Attack()
{
Debug.Log("공격");
}
#region Monster HP
public float Hp
{
get
{
return hp;
}
set
{
hp = value;
if (hp <= 0)
{
hp = 0;
onDie();
}
if (hp > maxHp)
{
hp = maxHp;
}
}
}
#endregion
}