UNFinder
UNFinder – 고성능 Unity 오브젝트 조회 SDK
현재 버전 : 2.0.1
UNFinder는 Unity를 위한 고성능 오브젝트 조회 프레임워크입니다.
GameObject.Find스타일의 이름 조회, 컴포넌트 접근, 타입/태그 기반 필터 쿼리를 인덱스 기반으로 처리합니다.
FNV-1a 해싱, 순수 C# 버킷, 풀링 기반 쿼리 파이프라인을 결합하여
네이티브 브리지 비용과 런타임 할당을 줄입니다. 빌드 시점에 트래커와 씬 레지스트리를 자동으로 삽입하며,
런타임에는 오브젝트를 이름·타입·태그 버킷으로 인덱싱하여 씬 전체 스캔 없이 조회합니다.
https://github.com/NightWish-0827/UNFinder.git?path=/com.nightwishlab.unfinder
UPM에서 git URL로 패키지를 추가하시면 됩니다.
주요 기능
O(1) 이름 조회
UN.Find(name)은 해시된 이름 버킷을 우선 조회하고, 캐시 미스 시에만 네이티브 조회를 1회 수행하여 결과를 캐시에 기록합니다.
캐시 히트 경로는 순수 C# 메모리에서만 동작합니다.
쿼리 기반 타입/태그 필터링
UN.Query()는 With, Without, Tag, Scene 필터를 지원합니다.
후보 버킷 중 가장 작은 집합을 기준으로 순회하여 탐색 비용을 줄입니다.
저할당 런타임
쿼리 빌더와 쿼리 결과를 풀링하여, 프레임마다 반복 호출되는 핫 패스에서 불필요한 임시 할당을 줄입니다.
생명 주기 안전 캐시 무결성
전용 API(Rename, SetTag, AddComponent, NotifyComponentChanged, Destroy)를 통해
실제 Unity 오브젝트 상태와 인덱스를 항상 동기화합니다.
빌드 타임 자동 베이킹
빌드 시점에 [UNBake] 어트리뷰트가 지정된 컴포넌트를 가진 오브젝트에 숨김 트래커를 자동으로 부착합니다.
코드 사용법
오브젝트 & 컴포넌트 조회
// GameObject.Find("Player") 대체
GameObject player = UN.Find("Player");
// 컴포넌트 조회 + 캐싱
PlayerController controller = UN.FindComponent<PlayerController>("Player");
씬 지정 조회
Additive 씬처럼 이름·타입 충돌이 발생할 수 있는 환경에서 유용합니다.
Scene combatScene = SceneManager.GetSceneByName("Combat");
GameObject boss = UN.FindInScene(combatScene, "Boss");
BossController bossCtrl = UN.FindComponentInScene<BossController>(combatScene, "Boss");
동적 생성 & 제거
생성된 인스턴스는 즉시 레지스트리에 등록되며, 기본 "(Clone)" 접미사는 자동으로 제거됩니다.
GameObject enemyInstance =
UN.Instantiate(enemyPrefab, spawnPos, Quaternion.identity);
EnemyAI ai =
UN.Instantiate<EnemyAI>(enemyAIPrefab, spawnPos, Quaternion.identity);
UN.Destroy(enemyInstance);
UN.Destroy(ai);
이름·태그·컴포넌트 변경
인덱스에 영향을 주는 상태 변경은 UN API를 통해 처리하면 쿼리 정합성이 유지됩니다.
// 수동 등록
UN.Bind(dynamicObject, "DynamicBoss");
// 이름 변경 — 이름 버킷 동기화
UN.Rename(dynamicObject, "DynamicBoss_Phase2");
// 태그 변경 — 태그 인덱스 동기화
UN.SetTag(dynamicObject, "Respawn");
// 컴포넌트 추가 — 타입 인덱스 재구성
UN.AddComponent<FrozenState>(dynamicObject);
// Unity 기본 API로 컴포넌트를 변경한 경우 수동 통지
UN.NotifyComponentChanged(dynamicObject);
Fluent 쿼리 API
using var result = UN.Query()
.WithComponent<IDamageable>()
.WithoutComponent<IFrozen>()
.WithTag("Enemy")
.Execute();
foreach (var go in result)
{
// 결과 오브젝트 사용
}
씬 필터, 콜백 순회, 조기 종료, 첫 번째 매치 조회도 지원합니다.
// 씬 필터
using var sceneOnly = UN.Query()
.WithComponent<IEnemy>()
.WithScene(combatScene)
.Execute();
// 콜백 순회
UN.Query()
.WithComponent<ITickable>()
.ForEach(go => go.GetComponent<ITickable>().Tick(Time.deltaTime));
// 조기 종료 — false 반환 시 중단
UN.Query()
.WithComponent<IEnemy>()
.TryForEach(go =>
{
if (!go.activeInHierarchy) return true; // continue
return false; // break
});
// 첫 번째 매치
GameObject firstEnemy = UN.Query().WithComponent<IEnemy>().First();
쿼리 캐시 모드
동일 프레임에서 같은 조건의 쿼리 결과를 재사용합니다. 프레임 경계나 오브젝트 그래프 변경 시 자동으로 무효화됩니다.
using var result = UN.Query()
.WithComponent<IDamageable>()
.WithScene(combatScene)
.Cached()
.Execute();
사용 시 주의사항
메인 스레드 전용
UNFinder API는 Unity 메인 스레드에서만 호출해야 합니다.
인덱스 관련 상태는 UN API 사용 권장
go.name, go.tag를 직접 수정하면 인덱스 정합성이 깨질 수 있습니다.
UN.Rename, UN.SetTag를 사용하세요.
쿼리 결과는 using 사용 권장
UNQueryResult와 UNCachedQuery는 풀링 가능한 타입입니다.
using으로 즉시 반환하면 불필요한 할당을 방지할 수 있습니다.
using var result = UN.Query().WithComponent<IEnemy>().Execute();
메모리 트리밍 (선택)
대량 오브젝트 제거 또는 씬 전환 후 버킷 메모리를 수동으로 회수할 수 있습니다.
int trimmedBuckets = UN.TrimTypeBuckets();
성능 비교
씬 규모가 커질수록 네이티브 조회 API는 계층 순회 비용이 누적됩니다.
UNFinder는 인덱스 기반 조회와 버킷 기반 후보 축소로 씬 전체 스캔을 피합니다.
성능 검증은 최대한 보수적이고 객관적인 환경에서 진행됩니다.

| Unity 기본 API | UNFinder SDK | |
|---|---|---|
| 이름 조회 | 네이티브 C++ 브리지 + 계층 순회 | 해시 기반 C# 버킷 조회 |
| 타입/태그 필터 | 씬 전체 재탐색 | 인덱스 기반 쿼리 |
| 반복 호출 | 호출마다 순회 비용 누적 | 동일 프레임 캐시 재사용 가능 |
| 런타임 할당 | 호출마다 임시 객체 생성 | 풀 기반 쿼리/결과 객체 |