using UnityEngine.Pool;
// This component returns the particle system to the pool when the OnParticleSystemStopped event is received.
[RequireComponent(typeof(ParticleSystem))]
publicclassReturnToPool : MonoBehaviour
{
public ParticleSystem system;
public IObjectPool<ParticleSystem> pool;
voidStart()
{
system = GetComponent<ParticleSystem>();
var main = system.main;
main.stopAction = ParticleSystemStopAction.Callback;
}
voidOnParticleSystemStopped()
{
// Return to the pool
pool.Release(system);
}
}
// This example spans a random number of ParticleSystems using a pool so that old systems can be reused.publicclassPoolExample : MonoBehaviour
{
publicenum PoolType
{
Stack,
LinkedList
}
public PoolType poolType;
// Collection checks will throw errors if we try to release an item that is already in the pool.publicbool collectionChecks = true;
publicint maxPoolSize = 10;
IObjectPool<ParticleSystem> m_Pool;
public IObjectPool<ParticleSystem> Pool
{
get
{
if (m_Pool == null)
{
if (poolType == PoolType.Stack)
m_Pool = new ObjectPool<ParticleSystem>(CreatePooledItem, OnTakeFromPool, OnReturnedToPool, OnDestroyPoolObject, collectionChecks, 10, maxPoolSize);
else
m_Pool = new LinkedPool<ParticleSystem>(CreatePooledItem, OnTakeFromPool, OnReturnedToPool, OnDestroyPoolObject, collectionChecks, maxPoolSize);
}
return m_Pool;
}
}
ParticleSystem CreatePooledItem()
{
var go = new GameObject("Pooled Particle System");
var ps = go.AddComponent<ParticleSystem>();
ps.Stop(true, ParticleSystemStopBehavior.StopEmittingAndClear);
var main = ps.main;
main.duration = 1;
main.startLifetime = 1;
main.loop = false;
// This is used to return ParticleSystems to the pool when they have stopped.var returnToPool = go.AddComponent<ReturnToPool>();
returnToPool.pool = Pool;
return ps;
}
// Called when an item is returned to the pool using ReleasevoidOnReturnedToPool(ParticleSystem system)
{
system.gameObject.SetActive(false);
}
// Called when an item is taken from the pool using GetvoidOnTakeFromPool(ParticleSystem system)
{
system.gameObject.SetActive(true);
}
// If the pool capacity is reached then any items returned will be destroyed.// We can control what the destroy behavior does, here we destroy the GameObject.voidOnDestroyPoolObject(ParticleSystem system)
{
Destroy(system.gameObject);
}
voidOnGUI()
{
GUILayout.Label("Pool size: " + Pool.CountInactive);
if (GUILayout.Button("Create Particles"))
{
var amount = Random.Range(1, 10);
for (int i = 0; i < amount; ++i)
{
var ps = Pool.Get();
ps.transform.position = Random.insideUnitSphere * 10;
ps.Play();
}
}
}
3.
내가 구현한 방식이다.
Spawn에도 IObjectPool로 PoolManager에 BulletPool을 받아서 사용한다.Manager 에서 새로운 오브젝트가 아닐경우 서로 공유해서 사용하게 한다.
글쓴이는 싱글톤으로 PoolManager을 만들어서 같은 총알은 서로 공유하여 사용하게 만들어보았다.
이런식으로 만들경우 Spawn컴퍼넌트를 오브젝트에 붙여주고 원하는 BulletPrefab을 넣어주면 완성이다.
하지만 null 이 필요할수 있기때문에 자료형 뒤에 ? 를 붙이면 null 표현이 가능해진다.
사용 방식
값 타입 자료형 ? 변수명
int? a = 10;
int? b = null;
// int c = null; null을 허용하지 않는 값 형식classA{}
// A a?; null 을 허용하지 않는 값 형식 이여야 한다.int?[] arr = newint?[10];
//배열 선언방법
Nullable 값 형식에서 기본 형식으로 변환
int? a = 10;
int b = 0;
b = a ?? -1;
// a가 null 이면 -1이 들어가고 null이 아닐경우 a값이 그대로 들어가 10이 들어간다.
?? 연산자는 왼쪽 값이 null 이면 오른쪽 값을 사용하고 null이 아닐경우 왼쪽 값을 사용하는
일종의 null 을 검사하는 연산자다.
is
is 연산자로는 Nullable 형식인지 아닌지 구분 불가하다
마소 예제코드
int? a = 1;
int b = 2;
if ( a isint )
{
Console.WriteLine(int? instance is compatible withint);
}
if (b isint?)
{
Console.WriteLine("int instance is compatible with int?");
}
// Output:// int? instance is compatible with int// int instance is compatible with int?
GetType
Object.GetType은 Null 허용값 형식의 boxing으로 기본형식 값의 boxing과 동일하게 나온다.
GetType은 기본형식 Type 인스턴스를 반환한다.
int? a = 17;
Type typeOfA = a.GetType();
Console.WriteLine(typeOfA.FullName);
// Output:// System.Int32
그럼으로 아래 코드 처럼 구분할수 있다
마소코드
Console.WriteLine($"int? is {(IsNullable(typeof(int?)) ? "nullable" : "non nullable")} value type");
Console.WriteLine($"int is {(IsNullable(typeof(int)) ? "nullable" : "non-nullable")} value type");
boolIsNullable(Type type) => Nullable.GetUnderlyingType(type) != null;
// Output:// int? is nullable value type// int is non-nullable value type
//마소 c# 튜플 사용 사례var ys = new[] { -9, 0, 67, 100 };
var (minimum, maximum) = FindMinMax(ys);
// Output:// Limits of [-9 0 67 100] are -9 and 100
(int min, int max) FindMinMax(int[] input)
{
if (input isnull || input.Length == 0)
{
}
var min = int.MaxValue;
var max = int.MinValue;
foreach (var i in input)
{
if (i < min)
{
min = i;
}
if (i > max)
{
max = i;
}
}
return (min, max);
}
위 사용 사례에서 보이는것 처럼 minimum 과 maximum 을 따로 구하지 않고 한번의 묶음으로 처리하여
하나의 함수로 처리하는것을 볼수있다.
또다른 사용 예시로는 비교문에서 알수있다.
//튜플 비교문
(int a, byte b) left = (5, 10);
(long a, int b) right = (5, 10);
Console.WriteLine(left == right); // output: True
Console.WriteLine(left != right); // output: Falsevar t1 = (A: 5, B: 10);
var t2 = (B: 5, A: 10);
Console.WriteLine(t1 == t2); // output: True
Console.WriteLine(t1 != t2); // output: False
보이는것 처럼 두개의 묶음으로 비교하여 비교문을 줄일수 있다.
튜플은 Dictionary 에서도 사용이 가능하다.
var limitsLookup = new Dictionary<int, (int Min, int Max)>()
{
[2] = (4, 10),
[4] = (10, 20),
[6] = (0, 23)
};
if (limitsLookup.TryGetValue(4, out (int Min, int Max) limits))
{
Console.WriteLine($"Found limits: min is {limits.Min}, max is {limits.Max}");
}
// Output:// Found limits: min is 10, max is 20
이처럼 쉽게 저장하고 사용하는것을 볼수있다.
참고
1. 지금 사용한 튜플 형식사용은 기존 Tuple class 와는 다르다.
ㄴ 지금 사용한 형식은 System.ValueTuple 이고 Tuple class는 System.Tuple 이다.