컬링 그룹은 사용자 시스템을 Unity의 컬링 및 LOD 파이프라인으로 통합하는 방법을 제공합니다. 이 API는 예를 들어 다음과 같은 여러 용도로 사용할 수 있습니다.
API는 사용자가 바운딩 구체의 배열을 제공하도록 하여 작동합니다. 그러면 특정 카메라에 대한 구체의 상대적인 가시성이 LOD 레벨 숫자처럼 처리할 수 있는 ‘거리 밴드’ 값과 함께 계산됩니다.
컬링 그룹을 사용하여 작업하기 위해 필요한 컴포넌트나 비주얼 툴은 없으며, 스크립트를 통해서만 접근 가능합니다.
컬링 그룹은 ‘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 콜백 필드를 사용하는 것입니다. 이 필드를 컬링 그룹 이벤트 구조를 인수로 사용하는 함수로 설정해야 합니다. 그러면 컬링이 완료된 후에 상태가 변경된 각 구체에 대해 이 함수가 호출됩니다. 컬링 그룹 이벤트 구조의 수를 통해 구체의 이전 및 새로운 스테이트에 대해 알 수 있습니다.
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);
}
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를 통해 검색해서 가져온 정보는 컬링 그룹이 사용한 카메라가 실제로 컬링을 수행할 때만 업데이트됨을 기억해야 합니다.
컬링 그룹을 프로젝트에 적용할 수 있는 방법을 고려할 때는 컬링 그룹 디자인의 다음과 같은 측면을 고려해야 합니다.
컬링 그룹이 가시성을 계산하는 모든 영역은 바운딩 구체, 즉 포지션(구체의 중심) 및 반지름 값에 따라 정의됩니다. 퍼포먼스와 관련한 이유로, 다른 바운딩 셰이프는 지원되지 않습니다. 즉, 실제로는 컬링하는 데 관심이 있는 오브젝트를 완전히 둘러싸는 구체를 정의합니다. 더 정확하게 맞아야 하는 경우 다중 구체를 사용하여 오브젝트의 여러 부분을 포함하고 모든 구체의 가시성 상태에 따라 결정을 내리는 방법을 고려해 보아야 합니다.
가시성을 평가하기 위해서는 컬링 그룹이 어느 카메라에서 가시성을 계산해야 하는지 알아야 합니다. 현재 컬링 그룹 하나당 카메라 한 대만 원됩니다. 여러 카메라의 가시성을 계산해야 하는 경우 카메라 한대당 컬링 그룹을 하나씩 사용하고 결과를 합쳐야 합니다.
컬링 그룹은 절두체 컬링과 정적 오클루전 컬링만 기반으로 가시성을 계산합니다. 동적 오브젝트는 잠재적인 오클루션 요인으로 고려되지 않습니다.
컬링 그룹은 특정 레퍼런스 포인트(예를 들어 카메라 또는 0플레이어의 포지션)와 각 구체에서 가장 가까운 포인트의 거리를 계산할 수 있습니다. 이 거리값은 직접 제공되지 않고, 대신 사용자가 별개의 ‘거리 밴드’ 정수 결과를 계산하기 위해 제공하는 여러 임계값을 사용하여 수량화됩니다. 목적은 이런 거리 밴드를 ‘가까운 거리’, ‘중거리’, ‘먼 거리’ 등으로 해석하도록 하는 것입니다.
컬링 그룹은 오브젝트가 한 밴드에 있다가 다른 밴드로 이동할 때 콜백을 제공하여 해당 오브젝트의 동작을 CPU 리소스를 덜 사용하는 동작으로 변경하는 등의 작업을 수행할 수 있는 기회를 부여합니다.
마지막 거리 밴드를 넘어선 구체는 보이지 않는 것으로 간주되므로, 아주 멀리 있는 오브젝트를 완전히 비활성화하는 컬링 구현을 쉽게 구성할 수 있습니다. 이 동작을 원치 않는 경우 최종 임계값이 무한한 거리에 있도록 설정하면 됩니다.
컬링 그룹 하나에 레퍼런스 포인트 하나만 지원됩니다.
컬링 그룹 API는 씬에 변경 사항을 적용한 후 곧바로 바운딩 구체의 새로운 가시성 상태를 요청할 수 있는 기능을 제공하지 않습니다. 퍼포먼스와 관련한 이유로, 컬링 그룹은 카메라 전체에 대해 컬링을 실행하는 중에만 새로운 가시성 정보를 계산합니다. 이 포인트에 콜백이나 컬링 그룹 쿼리 API를 통해 정보를 사용할 수 있게 됩니다. 즉, 실제로는 컬링 그룹에 비동기식으로 접근해야 합니다.
컬링 그룹에 제공하는 바운딩 구체 배열은 복사되지 않고 컬링 그룹에 의해 레퍼런스됩니다. 따라서 바운드 스피어 설정에 전달하는 배열에 대한 레퍼런스를 유지해야 하며, 바운드 스피어 설정을 다시 호출하지 않아도 이 배열의 콘텐츠를 수정할 수 있습니다. 동일한 구체 집합에 대해 (예를 들어 여러 카메라에 대해) 가시성과 거리를 계산하는 여러 컬링 그룹이 필요한 경우 모든 컬링 그룹이 동일한 바운딩 구체 배열 인스턴스를 공유하도록 하는 것이 효율적입니다.