스파스 텍스처
비동기 텍스처 업로드

컬링그룹 API

컬링 그룹은 사용자 시스템을 Unity의 컬링 및 LOD 파이프라인으로 통합하는 방법을 제공합니다. 이 API는 예를 들어 다음과 같은 여러 용도로 사용할 수 있습니다.

  • 군중을 시뮬레이션하면서 현재 실제로 보이는 캐릭터에 대해서만 전체 게임 오브젝트 포함
  • Graphics.DrawProcedural 기반 GPU 파티클 시스템을 빌드하되 벽 뒤에 있는 파티클 시스템의 렌더링 건너뜀
  • 플레이어가 적이 뷰에 갑자기 ‘튀어’ 나오는 것을 보지 못하도록 적을 스폰하기 위해 카메라에서 숨기는 스폰 포인트 추적
  • 캐릭터가 가까울 때는 전체 품질 애니메이션과 AI 계산을 사용하고 멀리 있을 때는 품질이 더 낮고 더 저렴한 동작으로 전환
  • 10,000개의 마커 포인트를 씬에 포함하고 플레이어와 포인트의 거리가 1m 이내가 될 때 효율적으로 알아냄

API는 사용자가 바운딩 구체의 배열을 제공하도록 하여 작동합니다. 그러면 특정 카메라에 대한 구체의 상대적인 가시성이 LOD 레벨 숫자처럼 처리할 수 있는 ‘거리 밴드’ 값과 함께 계산됩니다.

컬링그룹(CullingGroup) 시작

컬링 그룹을 사용하여 작업하기 위해 필요한 컴포넌트나 비주얼 툴은 없으며, 스크립트를 통해서만 접근 가능합니다.

컬링 그룹은 ‘new’ 연산자를 사용하여 구성할 수 있습니다.

CullingGroup group = new CullingGroup();

컬링 그룹이 가시성 계산을 수행하도록 하려면 이 그룹이 사용해야 하는 카메라를 지정해야 합니다.

group.targetCamera = Camera.main;

구체의 포지션과 반지름을 사용하여 바운드 스피어 구조의 배열을 만들고 채운 후 배열에 실제로 있는 구체의 수와 함께 바운드 스피어 설정에 전달합니다. 구체 수는 배열의 길이와 같지 않아도 되며, 사실 처음에는 배열에 실제로 있는 구체 수가 매우 적은 경우에도 앞으로 한 번에 보유하게 될 가장 많은 구체를 모두 포함할 수 있을 정도로 큰 배열을 만드는 것이 좋습니다. 그러면 구체를 추가하거나 제거함에 따라 배열 크기를 조절하기 위해 리소스를 많이 사용해야 하는 상황이 발생하지 않도록 할 수 있습니다.

BoundingSphere[] spheres = new BoundingSphere[1000];
spheres[0] = new BoundingSphere(Vector3.zero, 1f);
group.SetBoundingSpheres(spheres);
group.SetBoundingSphereCount(1);

이 포인트에 컬링 그룹은 단일 구체의 가시성을 프레임마다 계산하기 시작합니다.

컬링 그룹을 지우고 이 그룹이 사용하는 메모리를 모두 비우려면 스탠다드 .NET IDisposable 메커니즘을 사용하여 컬링 그룹을 폐기해야 합니다.

group.Dispose();
group = null;

onStateChanged 콜백을 통해 결과 받기

구체의 가시성 또는 거리 상태 변경에 대응하는 가장 효율적인 방법은 onStateChanged 콜백 필드를 사용하는 것입니다. 이 필드를 컬링 그룹 이벤트 구조를 인수로 사용하는 함수로 설정해야 합니다. 그러면 컬링이 완료된 후에 상태가 변경된 각 구체에 대해 이 함수가 호출됩니다. 컬링 그룹 이벤트 구조의 수를 통해 구체의 이전 및 새로운 스테이트에 대해 알 수 있습니다.

group.onStateChanged = StateChangedMethod;

private void StateChangedMethod(CullingGroupEvent evt)
{
    if(evt.hasBecomeVisible)
        Debug.LogFormat("Sphere {0} has become visible!", evt.index);
    if(evt.hasBecomeInvisible)
        Debug.LogFormat("Sphere {0} has become invisible!", evt.index);
}

컬링그룹(CullingGroup) 쿼리 API를 통한 결과 받기

OnStateChanged 대리자 외에, 컬링 그룹은 바운딩 구체 배열에서구체의 최근 가시성 및 거리 결과를 검색해서 가져오는 데 사용되는 API도 제공합니다. 단일 구체의 상태를 확인하려면 IsVisible 및 GetDistance 메서드를 사용해야 합니다.

bool sphereIsVisible = group.IsVisible(0);
int sphereDistanceBand = group.GetDistance(0);

다중 구체의 상태를 확인하려면 퀘리 인덱스 메서드를 사용할 수 있습니다. 메서드는 주어진 가시성이나 거리 상태와 일치하는 구체를 찾기 위해 구체의 연속적인 범위를 스캔합니다.

// Allocate an array to hold the resulting sphere indices - the size of the array determines the maximum spheres checked per call
int[] resultIndices = new int[1000];
// Also set up an int for storing the actual number of results that have been placed into the array
int numResults = 0;

// Find all spheres that are visible
numResults = group.QueryIndices(true, resultIndices, 0);
// Find all spheres that are in distance band 1
numResults = group.QueryIndices(1, resultIndices, 0);
// Find all spheres that are hidden in distance band 2, skipping the first 100
numResults = group.QueryIndices(false, 2, resultIndices, 100);

쿼리 API를 통해 검색해서 가져온 정보는 컬링 그룹이 사용한 카메라가 실제로 컬링을 수행할 때만 업데이트됨을 기억해야 합니다.

CullingGroup API 베스트 프랙티스

컬링 그룹을 프로젝트에 적용할 수 있는 방법을 고려할 때는 컬링 그룹 디자인의 다음과 같은 측면을 고려해야 합니다.

가시성 사용

컬링 그룹이 가시성을 계산하는 모든 영역은 바운딩 구체, 즉 포지션(구체의 중심) 및 반지름 값에 따라 정의됩니다. 퍼포먼스와 관련한 이유로, 다른 바운딩 셰이프는 지원되지 않습니다. 즉, 실제로는 컬링하는 데 관심이 있는 오브젝트를 완전히 둘러싸는 구체를 정의합니다. 더 정확하게 맞아야 하는 경우 다중 구체를 사용하여 오브젝트의 여러 부분을 포함하고 모든 구체의 가시성 상태에 따라 결정을 내리는 방법을 고려해 보아야 합니다.

가시성을 평가하기 위해서는 컬링 그룹이 어느 카메라에서 가시성을 계산해야 하는지 알아야 합니다. 현재 컬링 그룹 하나당 카메라 한 대만 원됩니다. 여러 카메라의 가시성을 계산해야 하는 경우 카메라 한대당 컬링 그룹을 하나씩 사용하고 결과를 합쳐야 합니다.

컬링 그룹은 절두체 컬링과 정적 오클루전 컬링만 기반으로 가시성을 계산합니다. 동적 오브젝트는 잠재적인 오클루션 요인으로 고려되지 않습니다.

거리 사용

컬링 그룹은 특정 레퍼런스 포인트(예를 들어 카메라 또는 0플레이어의 포지션)와 각 구체에서 가장 가까운 포인트의 거리를 계산할 수 있습니다. 이 거리값은 직접 제공되지 않고, 대신 사용자가 별개의 ‘거리 밴드’ 정수 결과를 계산하기 위해 제공하는 여러 임계값을 사용하여 수량화됩니다. 목적은 이런 거리 밴드를 ‘가까운 거리’, ‘중거리’, ‘먼 거리’ 등으로 해석하도록 하는 것입니다.

컬링 그룹은 오브젝트가 한 밴드에 있다가 다른 밴드로 이동할 때 콜백을 제공하여 해당 오브젝트의 동작을 CPU 리소스를 덜 사용하는 동작으로 변경하는 등의 작업을 수행할 수 있는 기회를 부여합니다.

마지막 거리 밴드를 넘어선 구체는 보이지 않는 것으로 간주되므로, 아주 멀리 있는 오브젝트를 완전히 비활성화하는 컬링 구현을 쉽게 구성할 수 있습니다. 동작을 원치 않는 경우 최종 임계값이 무한한 거리에 있도록 설정하면 됩니다.

컬링 그룹 하나에 레퍼런스 포인트 하나만 지원됩니다.

성능과 디자인

컬링 그룹 API는 씬에 변경 사항을 적용한 후 곧바로 바운딩 구체의 새로운 가시성 상태를 요청할 수 있는 기능을 제공하지 않습니다. 퍼포먼스와 관련한 이유로, 컬링 그룹은 카메라 전체에 대해 컬링을 실행하는 중에만 새로운 가시성 정보를 계산합니다. 이 포인트에 콜백이나 컬링 그룹 쿼리 API를 통해 정보를 사용할 수 있게 됩니다. 즉, 실제로는 컬링 그룹에 비동기식으로 접근해야 합니다.

컬링 그룹에 제공하는 바운딩 구체 배열은 복사되지 않고 컬링 그룹에 의해 레퍼런스됩니다. 따라서 바운드 스피어 설정에 전달하는 배열에 대한 레퍼런스를 유지해야 하며, 바운드 스피어 설정을 다시 호출하지 않아도 이 배열의 콘텐츠를 수정할 수 있습니다. 동일한 구체 집합에 대해 (예를 들어 여러 카메라에 대해) 가시성과 거리를 계산하는 여러 컬링 그룹이 필요한 경우 모든 컬링 그룹이 동일한 바운딩 구체 배열 인스턴스를 공유하도록 하는 것이 효율적입니다.

스파스 텍스처
비동기 텍스처 업로드