3 분 소요

UN (Unity-Native) Fast Object Finder SDK

Current Version : 2.0.0

UNFinder는 Unity를 위한 고성능 조회 및 쿼리 프레임워크.
이름 기반 조회(GameObject.Find 스타일), 컴포넌트 접근,
타입/태그 기반 필터링을 결정적 런타임 동작으로 가속함.

UNFinder는 FNV-1a 해싱, 순수 C# 버킷, 풀링 기반 쿼리 파이프라인을 결합해
네이티브 브리지 비용과 런타임 할당을 줄임.
또한 이름/태그/컴포넌트 변경 시 캐시 무결성을 유지하도록 라이프사이클 안전 API를 제공함.

빌드 과정에서 SDK는 숨겨진 트래커와 씬 레지스트리를 자동 삽입함.
런타임에서는 오브젝트를 이름/타입/태그 버킷으로 인덱싱하여 전체 씬 스캔 없이 조회함.

image

https://github.com/NightWish-0827/UNFinder.git?path=/com.nightwishlab.unfinder
UPM Add package from git URL


Table of Contents


Core Features

O(1) 이름 조회 경로

UN.Find(name)은 해시된 이름 버킷을 먼저 조회하고,
필요할 때만 네이티브 조회를 1회 지연 수행하여 캐시에 기록함.
캐시 히트 경로는 순수 C# 메모리에서 동작함.


쿼리 기반 타입/태그 필터링

UN.Query()With, Without, Tag, Scene 필터를 지원함.
엔진은 후보 버킷 중 가장 작은 집합을 기준으로 순회해 탐색 비용을 줄임.


저할당 런타임

UNFinder는 쿼리 빌더와 쿼리 결과를 풀링함.
프레임 반복 호출이 많은 핫패스에서 불필요한 임시 할당을 줄임.


라이프사이클 안전 캐시 무결성

전용 API(Rename, SetTag, AddComponent, NotifyComponentChanged, Destroy)를 통해
실제 Unity 오브젝트 상태와 인덱스를 동기화함.


빌드 타임 오토 베이킹

빌드 처리 시 [UNBake]가 지정된 컴포넌트를 하나 이상 가진 오브젝트에
숨김 트래커를 자동 부착함.


API Reference & Usage

API는 Unity에서 자주 사용하는 조회 패턴을 그대로 확장할 수 있도록 설계되었음.


Object & Component Lookup

// GameObject.Find("Player") 대체
GameObject player = UN.Find("Player");

// 컴포넌트 조회 + 캐싱
PlayerController controller = UN.FindComponent<PlayerController>("Player");

Scene-Aware Lookup

Additive 씬 환경처럼 이름/타입 충돌이 가능한 구조에서 유용함.

using UnityEngine.SceneManagement;

Scene combatScene = SceneManager.GetSceneByName("Combat");
GameObject boss = UN.FindInScene(combatScene, "Boss");
BossController bossCtrl = UN.FindComponentInScene<BossController>(combatScene, "Boss");

Dynamic Instantiation & Destroy

생성된 인스턴스는 즉시 등록되며 기본 "(Clone)" 접미사는 제거됨.
컴포넌트 오버로드도 지원함.

GameObject enemyInstance =
    UN.Instantiate(enemyPrefab, spawnPos, Quaternion.identity);

EnemyAI ai =
    UN.Instantiate<EnemyAI>(enemyAIPrefab, spawnPos, Quaternion.identity);

// Destroy 래퍼로 라이프사이클 동작을 명시적으로 유지
UN.Destroy(enemyInstance);
UN.Destroy(ai);

Rename, Binding, and State Sync

인덱스에 영향을 주는 가변 상태는 UN API를 통해 변경하는 것을 권장함.

// 수동 등록
UN.Bind(dynamicObject, "DynamicBoss");

// 이름 캐시 무결성을 유지하며 이름 변경
UN.Rename(dynamicObject, "DynamicBoss_Phase2");

// 태그 인덱스를 동기화하며 태그 변경
UN.SetTag(dynamicObject, "Respawn");

// 타입 인덱스 재빌드를 포함한 안전한 컴포넌트 추가
UN.AddComponent<FrozenState>(dynamicObject);

// Unity 기본 API로 컴포넌트를 바꿨다면 UNFinder에 변경 통지
UN.NotifyComponentChanged(dynamicObject);

Fluent Query 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));

// 조기 종료
bool completed = UN.Query()
    .WithComponent<IEnemy>()
    .TryForEach(go =>
    {
        if (!go.activeInHierarchy) return true; // continue
        return false;                            // break
    });

// 첫 번째 매치만 빠르게 조회
GameObject firstEnemy = UN.Query().WithComponent<IEnemy>().First();

Cached Query Mode

캐시 모드는 동일 프레임에서 동일 지문(fingerprint)의 쿼리 결과를 재사용함.
프레임 경계 또는 오브젝트 그래프 변경 시 자동 무효화됨.

using var result = UN.Query()
    .WithComponent<IDamageable>()
    .WithScene(combatScene)
    .Cached()
    .Execute();

Cached()는 의도적으로 Execute()만 노출하는 UNCachedQuery를 반환함.


Lifecycle & Callback Mechanism

UNFinder는 Unity의 빌드/런타임 콜백과 트래커 라이프사이클 훅을 통해 자동 동기화됨.

Build Phase
-----------
IProcessSceneWithReport.OnProcessScene
→ 씬 루트 스캔
→ [UNBake] 대상에 숨김 UNTracker 부착
→ 베이크된 트래커 참조를 가진 ~UN_AutoRegistry 생성

Bootstrapping Phase
-------------------
DefaultExecutionOrder(-32000)
→ UNSceneRegistry.Awake()
→ 베이크된 트래커 초기화
→ 이름/타입/태그 인덱스 등록

Runtime Mutation
----------------
UN.Bind / UN.Rename / UN.SetTag / UN.AddComponent / UN.Destroy
→ 캐시와 인덱스 동기화 유지

Destroy Phase
-------------
UNTracker.OnDestroy()
→ 이름/타입/태그 버킷에서 제거
→ Stale 참조 방지

Operational Notes

메인 스레드 전용

UNFinder API는 Unity 메인 스레드 사용을 전제로 설계되었음.
Worker Thread 또는 Job에서 호출하지 말 것.


가변 인덱스 상태는 UN API 우선

트래킹된 오브젝트에서 go.name, go.tag를 직접 수정하지 않는 것을 권장함.
UN.Rename, UN.SetTag를 사용하면 쿼리/인덱스 정합성이 유지됨.


Query 결과는 using 사용 권장

UNQueryResultUNCachedQuery는 풀링/해제 가능한 타입.
즉시 반환되도록 using을 사용하는 것을 권장함.

using var result = UN.Query().WithComponent<IEnemy>().Execute();

메모리 트리밍 (선택)

대량 파괴 웨이브나 씬 전환 후 버킷 메모리를 회수할 수 있음.

int trimmedBuckets = UN.TrimTypeBuckets();

Performance Comparison

씬 규모가 커질수록 네이티브 조회 API는 계층 순회 비용이 커지는 경향이 있음.
UNFinder는 인덱스 기반 조회와 버킷 기반 후보 축소로 전체 씬 스캔을 피함.

Code_Generated_Image (2)

Default Unity API

  • 네이티브 C++ 브리지 및 계층 순회 비용
  • 반복 호출이 누적될수록 총 순회 오버헤드 증가
  • 필터 중심 로직에서 씬 전체 재탐색이 반복됨

UNFinder SDK

  • 해시 기반 C# 이름 버킷 조회
  • 인덱스 기반 타입/태그 쿼리
  • 동일 프레임 재요청에 대한 쿼리 캐시 모드
  • 풀 기반 쿼리/결과 객체로 예측 가능한 런타임 동작

마치며

UNFinder는 조회 중심 게임플레이 코드를 인덱스 기반 런타임 워크플로우로 전환함.
기존 사용 패턴을 유지하면서도 더 결정적이고 확장 가능한 접근 경로를 제공함.


태그: C#, OpenSource, Unity

카테고리:

업데이트: