범주 내 수준 오브젝트 정리

고유한 사용자 정의 범주를 생성해 Explorer 패널에서 게임 수준의 오브젝트를 잘 정리해 둘 수 있습니다. 이러한 새 범주는 Explorer 뷰 및 Layers 뷰 둘 다의 필터 컨트롤과 Explorer 뷰의 트리 뷰에 표시됩니다.

예를 들어 다음 이미지는 "Entities", "Units", "Lights" 및 "Triggers"와 같은 기본 범주 옆에 "Enemies" 및 "Targets"와 같은 사용자 정의 범주를 보여줍니다.

새 범주를 만드는 방법:

범주는 프로젝트 폴더 내의 in .object_filter 리소스 파일에서 정의됩니다. Explorer 패널에 표시하려는 각각의 새 범주에 대해 아래 표시된 SJSON 형식을 따르는 새 텍스트 파일을 만든 다음 .object_filter 확장자를 지정해야 합니다.

범주 필터를 다시 적용하는 방법

범주를 생성하거나 수정하는 경우 Explorer 패널에 변경 사항을 표시하기 위해 Stingray 편집기를 다시 시작할 필요가 없습니다. 대신, F5 키를 눌러 프로젝트의 소스 폴더에서 리소스를 갱신합니다.

.object_filter 리소스 형식

위에 표시된 "Enemies"범주를 만드는 데 다음 .object_filter 예제가 사용되었습니다.

category_display_name = "Enemies"
category_type_name = "enemies"
evaluation_priority = 10.0
ui_order = 0.0
is_type = """
    -- params: (level_object, engine_object)
    if level_object._unit ~= nil then
        if Unit.has_data(level_object._unit, "is_enemy") then
            return Unit.get_data(level_object._unit, "is_enemy")
        end
    end
    return false
"""

다음 매개변수를 설정할 수 있습니다.

category_display_name

Explorer 패널에 표시되는 범주 이름입니다.

category_type_name

범주 유형의 내부 이름입니다. 핵심 리소스의 기본 범주를 비롯하여 프로젝트에 사용되는 모든 .object_filter 정의 간에 이 이름이 고유해야 합니다.

evaluation_priority

필터의 우선순위를 지정합니다. 수준의 오브젝트가 두 개 이상의 범주에 대한 필터 함수와 일치하는 경우 해당 오브젝트 해석 우선순위 값이 가장 높은 범주에 배치됩니다.

ui_order

Explorer 트리 뷰에서 이 범주의 정렬 순서를 지정합니다. 위에서 아래로 정렬되므로 숫자가 클수록 범주는 목록 아래에 배치됩니다. ui_order 값이 동일한 범주는 사전순으로 정렬됩니다.

이 필드는 선택적입니다. 이 값을 지정하지 않으면 범주가 목록의 맨 끝에 배치되고 ui_order 값이 지정되지 않은 다른 범주와 사전순으로 정렬됩니다.

필터 목록의 범주는 항상 사전순으로만 정렬됩니다.

is_type

오브젝트를 이 범주에 배치해야 할지 여부를 결정하기 위해 수준의 각 오브젝트에 대해 호출되는 Lua 함수입니다. Lua 코드는 다음과 같이 따옴표 3개로 묶어야 합니다. """. 자세한 내용은 다음 섹션을 참조하십시오.

필터 함수 작성

각 범주에는 편집기에서 수준의 각 오브젝트에 대해 호출하는 is_type 함수가 포함되어 있어야 합니다. is_type 함수의 기능은 편집기에서 전달하는 단일 오브젝트 수준을 이 범주에 포함할지 여부를 결정하는 것입니다.

편집기에ㅅ는 이 함수에 다음과 같은 두 가지 매개변수를 전달합니다.

이 함수는 전달된 함수를 이 범주 내에 포함해야 하는 경우 true를 반환하고 그렇지 않은 경우 false를 반환합니다.

예: 스크립트 데이터별로 필터링

위의 예에서 필터 함수는 다음과 같이 특정 유형의 스크립트 데이터 집합이 있는 유닛에 대해서만 true를 반환했습니다.

if level_object._unit ~= nil then
    if Unit.has_data(level_object._unit, "is_enemy") then
        return Unit.get_data(level_object._unit, "is_enemy")
    end
end
return false

이 코드를 사용하여 오브젝트 유형을 식별하는 여러 스크립트 데이터로 유닛에 태그를 지정해 게임 유닛을 범주로 나눌 수 있습니다. 예를 들어 설정하려는 범주에 따라 장면 오브젝트, 소품, 차량 또는 캐릭터에 대해 스크립트 데이터 값을 다르게 설정할 수 있습니다.

유닛 리소스에 대한 스크립트 데이터는 Unit Editor에서 설정할 수 있습니다.

예: 리소스 이름별 필터링

리소스 이름을 기준으로 오브젝트를 범주로 정리할 수 있습니다. 예를 들어, 다음 함수는 유닛 리소스가 지정된 값 목록의 값 중 하나와 일치하는 오브젝트에 대해서만 True를 반환합니다.

local resource_names = {
    "content/models/character/character",
    "content/models/props/target"
}
if level_object._unit ~= nil then
    for _, name in pairs(resource_names) do
        if stingray.Unit.is_a(level_object._unit, name) then return true end
    end
end

예: 편집기 유닛 이름별 필터링

편집기에서 생성한 유닛에 이름을 할당하는 방식을 잘 정의한 경우 이러한 명명 방식을 활용해 오브젝트를 범주로 정리할 수 있습니다. 예를 들어, 다음 함수는 이름이 문자열 enemy_로 시작하는 유닛에 대해서만 true를 반환합니다.

if level_object.name:find("^enemy_") then return true end
return false

예: 동적 데이터별로 필터링

오브젝트의 정적 특성별로 필터링하도록 제한되지는 않습니다. 수준 편집기의 현재 상태에 대한 동적 측면을 고려해 필터를 만들 수 있습니다.

지형을 편집하는 과정에서 변경될 수 있는 데이터를 필터링 시 사용하는 경우 데이터가 변경되면 F5 키를 눌러 점주 필터링을 다시 적용해야 한다는 점만 주의하면 됩니다.

예를 들어, 다음 함수는 편집기에서 현재 선택된 모든 오브젝트를 수집합니다. 따라서 수준 디자이너가 범주에 임의 오브젝트 집합을 즉시 추가할 수 있습니다.

if level_object._unit ~= nil then
    if LevelEditing.selection:includes(level_object.id) then return true end
end
return false

이 방법을 달리 사용하면 다른 목록에서 끌어내기 위해 카메라의 현재 절두체 내에 있는 모든 오브젝트 또는 편집기에서 현재 숨겨진 모든 오브젝트를 그룹화할 수 있습니다.

예: 수준 배치별 필터링

3D 장면에서 리소스를 위치별로 정리할 수 있습니다. 예를 들어, 다음 함수는 참조 위치가 10미터 이내인 모든 유닛을 포함합니다.

reference_point = stingray.Vector3(0,0,0)
distance_threshold = 10
if level_object._unit ~= nil then
    local position = level_object:local_position()
    if stingray.Vector3.distance(reference_point, position) < distance_threshold then return true end
end
return false

이 예에서는 기준점이 원점이지만 뷰포트의 카메라 위치, 선택한 오브젝트 또는 마우스의 장면 위치에 따라 선택한 유닛과 같은 다른 점을 사용할 수 있습니다.

유닛이 해당 영역의 장면에 추가될 때마다 자동으로 범주에 추가됩니다. 그러나 기존 유닛을 해당 영역으로 이동하면 F5 키를 눌러 필터를 다시 적용해 변경 사항을 반영해야 합니다.

관련 항목