using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Spawner : MonoBehaviour
{
public GameObject prefab;
public GameObject target;
//public GameObject makeOne;
private void Update()
{
if (Input.GetKeyDown(KeyCode.A))
{
Spawn();
}
if (Input.GetKeyDown(KeyCode.D))
{
DeSpawn();
}
}
public void Spawn()
{
//makeOne = new GameObject("Spawned GameObject"); // 새로운 게임 오브젝트 생성
Instantiate(prefab, new Vector3(1, 1, 1), Quaternion.identity); // Quaternion -> 회전값 / identity 회전없이
// Instantiate 로 프리팹을 생성
}
public void DeSpawn()
{
Destroy(target, 3); // 3초 뒤에 target을 파괴
}
}
포탄을 미리 일정 수 풀에 생성해서 보관 및 사용
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/* 디자인 패턴 ObjectPool */
/*
<오브젝트 풀 패턴>
프로그램 내에서 빈번하게 재활용하는 인스턴스들을 풀에 보관한 뒤
인스턴스의 생성&삭제 대신 대여&반납을 사용하는 기법
<구현>
1. 인스턴스들을 보관할 풀을 생성
2. 프로그램의 시작시 풀에 인스턴스들을 생성하여 보관
3. 인스턴스 생성이 필요할 때 풀에서 대여하여 사용
4. 인스턴스 삭제가 필요할 때 풀에 반납하여 보관
<장점>
1. 빈번하게 사용하는 인스턴스 생성에 소요되는 오버헤드를 줄임
2. 빈번하게 사용하는 인스턴스 삭제에 부담되는 가비지 콜렉터의 동작을 줄임
<주의점>
1. 미리 생성해놓은 인스턴스들이 사용하지 않는 경우에도 메모리를 차지하고 있음
2. 오브젝트 풀을 힙영역의 여유공간이 줄어들어 오히려 프로그램에 부담이 되는 경우가 있음.
*/
public class ObjectPool : MonoBehaviour
{
[SerializeField] List<PooledObject> pool = new List<PooledObject>(); // 미리 보관할 풀을 리스트로 생성
[SerializeField] PooledObject prefab;
[SerializeField] int size; // 처음에 춘비해놓을 인스턴스 개수
[SerializeField] int capacity; // 풀의 최대 개수
private void Awake()
{
for (int i = 0; i < size; i++)
{
PooledObject instance = Instantiate(prefab); // prefab을 복제하여 인스턴스 생성
instance.gameObject.SetActive(false); // 비활성화 해서
pool.Add(instance); // 인스턴스를 풀에 보관
}
}
public PooledObject GetPool(Vector3 position, Quaternion rotation) // 대여
{ // 어느위치에서 어느각도로 생성할건지
if (pool.Count == 0) // 풀에 인스턴스가 없으면
{
return Instantiate(prefab, position, rotation); // 새로 생성
}
PooledObject instance = pool[pool.Count - 1]; // 풀에서 인스턴스 맨 마지막거 가져오기
pool.RemoveAt(pool.Count - 1); // 풀에서 인스턴스 제거
instance.returnPool = this; // 인스턴스의 returnPool 변수에 현재 풀을 설정
instance.transform.position = position; // 위치 설정
instance.transform.rotation = rotation; // 회전 설정
instance.gameObject.SetActive(true); // 활성화
return instance; // 인스턴스 반환
}
public void ReturnPool(PooledObject instance) // 반납
{
if (pool.Count >= capacity)
{
Destroy(instance.gameObject); // 풀의 개수가 최대치면 인스턴스 삭제
}
instance.gameObject.SetActive(false); // 인스턴스 비활성화
pool.Add(instance); // 풀에 추가
}
}
사용한 오브젝트 풀에 반납
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PooledObject : MonoBehaviour
{
public ObjectPool returnPool; // 오브젝트 풀을 참조하기 위한 변수
[SerializeField] float returnTime; // 오브젝트 풀에 반납될 시간
private float timer; // 현재 시각
private void OnEnable()
{
timer = returnTime; // 오브젝트가 활성화될 때 타이머 초기화
}
private void Update()
{
timer -= Time.deltaTime; // 타이머 감소 - 프레임 마다 진행된 시간
if (timer <= 0) // 타이머가 0 이하가 되면
{
RetuenPool(); // 오브젝트 풀에 반납
}
}
public void RetuenPool()
{
if (returnPool == null)
{
Destroy(gameObject); // returnPool이 null이면 오브젝트 풀에 반납하지 않고 삭제
}
else
{
returnPool.ReturnPool(this); // 오브젝트 풀에 반납
}
}
}
포탄 발사 코드 - 발사 후 3초뒤 삭제
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Shooter : MonoBehaviour
{
[SerializeField] GameObject bulletPrefab; // 총알 프리팹
[SerializeField] Transform muzzlePoint; // 총알 발사 위치
[SerializeField] ObjectPool bulletPool; // 총알 오브젝트 풀
[Range(10, 30)]
[SerializeField] float bulletSpeed; // 발사 속도
public void Fire()
{
// 총알을 발사하는 메서드
GameObject instance = Instantiate(bulletPrefab, muzzlePoint.position, muzzlePoint.rotation); // 총알 인스턴스 생성
// 머즐 포인트 위치와 회전으로 총알 생성
//PooledObject instance = bulletPool.GetPool(muzzlePoint.position, muzzlePoint.rotation);
// 총알 풀에서 총알 인스턴스 가져오기
Rigidbody bulletRigidbody = instance.GetComponent<Rigidbody>(); // 총알의 리지드바디 컴포넌트 가져오기
bulletRigidbody.velocity = muzzlePoint.forward * bulletSpeed; // 총알의 속도 설정
Destroy(instance, 3); // 3초 후 총알 삭제
}
}