04-pool-factories
Status: ACTIVE
AppliesTo: v20
Type: Component Specification
1. 목적
IPoolFactory의 실사용 구현 2종 및 static facade 1종 제공:
- •
InspectorPoolFactory- 인스펙터에서 프리팹 등록 (MonoBehaviour) - •
BundlePoolFactory- AssetBundle 기반 로딩 (Lazy singleton + IPoolFactory) - •
BundlePool- BundlePoolFactory의 static facade (권장 사용법)
2. 네임스페이스
모든 코드는 namespace Devian 고정.
3. 생성 대상 패키지
- •
com.devian.foundation
4. 파일 위치 (정본)
code
com.devian.foundation/Runtime/Unity/Pool/Factory/ ├── IPoolFactory.cs ├── PoolFactoryExtensions.cs ├── InspectorPoolFactory.cs ├── BundlePoolFactory.cs └── BundlePool.cs
Note: 이 폴더는 수기 코드이며, 생성기는 clean+generate하지 않음.
5. InspectorPoolFactory 규약
형태: public sealed class InspectorPoolFactory : MonoBehaviour, IPoolFactory
프리팹 등록 방식
csharp
[SerializeField] private GameObject[] _prefabs;
내부 캐시
csharp
private Dictionary<string, GameObject> _prefabByName;
- •
Awake()또는OnEnable()에서 캐시 구성 - •
OnValidate()에서 에디터 편의를 위해 재구성
GetPrefab(name)
csharp
_prefabByName.TryGetValue(name, out var prefab) ? prefab : null
GetPoolType(prefab)
- •
prefab.GetComponents<Component>()를 순회 - •각 컴포넌트 타입이 구현하는 인터페이스 중
IPoolable<>(generic type definition) 찾기 - •찾으면 해당 컴포넌트 타입 반환
- •못 찾으면
InvalidOperationException
CreateInstance(prefab)
csharp
var go = UnityEngine.Object.Instantiate(prefab); var poolType = GetPoolType(prefab); return go.GetComponent(poolType);
DestroyInstance(instance)
../05-unity-object-destruction/skill.md 규약 준수:
csharp
#if UNITY_EDITOR
if (!UnityEngine.Application.isPlaying)
{
UnityEngine.Object.DestroyImmediate(instance.gameObject);
return;
}
#endif
UnityEngine.Object.Destroy(instance.gameObject);
- •컴포넌트가 아닌
instance.gameObject를 Destroy
6. BundlePoolFactory 규약
형태: public sealed class BundlePoolFactory : SimpleSingleton<BundlePoolFactory>, IPoolFactory
생성자
csharp
public BundlePoolFactory() { } // SimpleSingleton의 new() 제약 충족
Generic GetPrefab (권장)
csharp
public TAsset GetPrefab<TAsset>(string name) where TAsset : UnityEngine.Object
{
UnityMainThread.EnsureOrThrow("BundlePoolFactory.GetPrefab<TAsset>");
return AssetManager.GetAsset<TAsset>(name);
}
- •
AssetManager.GetAsset<T>(name)그대로 사용 - •Generic으로 다양한 에셋 타입 지원
IPoolFactory.GetPrefab (명시적 구현)
csharp
GameObject IPoolFactory.GetPrefab(string name)
{
return GetPrefab<GameObject>(name);
}
- •IPoolFactory 인터페이스는 GameObject 고정
- •Generic API를 GameObject로 연결
GetPoolType/CreateInstance/DestroyInstance
InspectorPoolFactory와 동일 규약.
모든 public API에 UnityMainThread.EnsureOrThrow(...) 적용.
7. BundlePool 규약 (권장 사용법)
형태: public static class BundlePool
사용자는 BundlePool을 통해 풀링하는 것을 권장
Spawn
csharp
public static T Spawn<T>(
string name,
Vector3 position = default,
Quaternion rotation = default,
Transform parent = null,
PoolOptions options = default)
where T : Component, IPoolable<T>
{
UnityMainThread.EnsureOrThrow("BundlePool.Spawn");
return BundlePoolFactory.Instance.Spawn<T>(name, position, rotation, parent, options);
}
Despawn
csharp
public static void Despawn(Component instance)
{
UnityMainThread.EnsureOrThrow("BundlePool.Despawn");
BundlePoolFactory.Instance.Despawn(instance);
}
ClearAll
csharp
public static void ClearAll()
{
UnityMainThread.EnsureOrThrow("BundlePool.ClearAll");
PoolManager.Instance.ClearAll();
}
8. 사용 예시
BundlePool (권장)
csharp
// Spawn
var enemy = BundlePool.Spawn<Enemy>("Goblin", position, rotation);
// Despawn
BundlePool.Despawn(enemy);
BundlePoolFactory (직접 사용)
csharp
// Spawn (factory 확장 메서드)
var enemy = BundlePoolFactory.Instance.Spawn<Enemy>("Goblin", position, rotation);
// Despawn
BundlePoolFactory.Instance.Despawn(enemy);
9. 주의 사항
- •에셋 사전 로딩 필수: BundlePoolFactory는 AssetManager를 통해 에셋을 가져옴. 에셋이 캐시에 없으면 실패함.
- •name은 에셋 키이자 풀 키: 오타/대소문자 차이가 있으면 다른 풀로 분리되어 메모리 낭비 발생.
- •메인 스레드 전용: 모든 API는 메인 스레드에서만 호출 가능.
10. 금지 사항
- •
IPoolFactory인터페이스 변경 금지 - •
AssetManager.Instance사용 금지 (static 메서드 사용) - •
DestroyInstance에서Destroy(instance)금지 (반드시instance.gameObject) - •
Resources/Addressables사용 금지
11. DoD (완료 정의)
- •
Runtime/PoolFactories/에 3개 파일 존재 (InspectorPoolFactory, BundlePoolFactory, BundlePool) - •
BundlePoolFactory가SimpleSingleton<BundlePoolFactory>상속 - •
BundlePoolFactory.GetPrefab<TAsset>(name)Generic API 제공 - •
BundlePool이 static facade로 존재하며 사용자 권장 API로 명시 - •
DestroyInstance는05-unity-object-destruction규약 준수 - • 모든 public API에 메인 스레드 강제
Reference
- •Parent:
skills/devian-unity/30-unity-components/skill.md - •Related:
02-pool-manager/SKILL.md(IPoolFactory 인터페이스 정의) - •Related:
01-singleton/SKILL.md(SimpleSingleton 베이스) - •Related:
../05-unity-object-destruction/skill.md(Destroy 규약) - •Related:
10-asset-manager/SKILL.md(AssetManager API)