때로 프로젝트를 실행할 때 특정 유형의 모든 엔티티가 같은 방식으로 동작하도록, 즉 특정 이벤트 및 조건이 발생할 때 같은 동작으로 반응하도록 하고 싶은 경우가 있습니다. 예를 들어, 플레이어 컨트롤 유닛이 충분히 가까이 다가오면 문이 열리고, 라이트가 켜지거나 적들이 적대적인 상태가 되도록 하고 싶을 수 있습니다.
이는 엔티티를 프로젝트의 Lua 모듈 및 흐름 그래프와 연결해주는 script 구성요소 및 Flow 구성요소를 사용하여 보다 쉽게 수행할 수 있습니다. 해당 Lua 모듈 및 흐름 그래프는 엔티티의 수명에 걸쳐 발생하는 이벤트에 대한 반응, 그리고 엔티티가 취해야 하는 적절한 반응의 수행을 처리할 수 있습니다.
이 구성요소는 엔티티의 동작을 비교적 자립적으로 유지하는 데 도움을 주기 때문에 유용합니다. 덕분에 보다 쉽게 게임을 관리하고, 동작을 재사용할 수 있습니다. 예를 들어 수준에서 각 문의 상태를 확인하는 Lua 루틴을 게임의 기본 업데이트 루프에 포함시키는 대신 자동으로 호출되는 스크립트 구성요소 안에 문의 모든 동적 런타임 동작을 캡슐화할 수 있습니다. 그러면 특정 유형의 게임 오브젝트에 대한 핸들 로직을 기본 게임 플레이 스크립트 및 흐름 그래프에 덜 넣을 수 있고, 서로 다른 엔티티 간에, 그리고 여러 프로젝트에 걸쳐 동작을 보다 쉽게 공유할 수 있습니다.
흐름은 시작하기에 보다 쉽고, 프로토타입을 더 빠르게 설정할 수 있는 비주얼 언어이기 때문에 엔티티의 동작을 설정하기에 아주 좋습니다.
외부 흐름 편집기에서 엔티티의 흐름 그래프를 생성해야 합니다.
기본 메뉴에서 Window > External Flow Editor를 선택해 편집기를 실행합니다.
흐름 편집기가 열리면 File > New를 선택해 새 그래프를 시작합니다.
엔티티에 대해 원하는 동작으로 새 그래프를 설정합니다.
외부 흐름 편집기는 노드 추가 및 제거를 위한 동일한 컨트롤을 갖추고 있으며, Unit Flow 편집기와 똑같은 방식으로 작동합니다. Level Flow 및 Unit Flow에서 사용 가능한 동일한 노드 세트를 그래프에서 사용할 수 있습니다. 또한, 엔티티를 다룰 때 특히 유용한 몇 가지 노드도 있습니다. 아래 예를 참조하십시오.
File > Save를 선택해 그래프를 저장합니다. 이렇게 하면 프로젝트에 새 .flow_editor 리소스가 생성됩니다.
문을 나타내는 엔티티에 대한 흐름 그래프의 예가 여기에 나와 있습니다. 이 문은 사용자 정의 데이터 구성요소를 사용하여 잠겨 있어야 하는지 여부를 추적합니다. 문이 잠겨 있지 않고 카메라가 충분히 가까이 있는 경우 각 프레임마다 엔티티가 소유한 유닛에 대한 애니메이션을 재생함으로써 문이 자동으로 열립니다.
이 그래프는 몇 가지 유용한 점을 보여줍니다.
Event > Entity Spawned를 사용하여 생성 중인 이 그래프를 소유하고 있는 엔티티에 대한 반응으로 일부 로직을 트리거하는 방법.
Set Component Property 및 Get Component Property 노드를 사용하여 데이터 구성요소의 데이터를 설정하고 가져오는 방법(이 경우, 문이 열려 있는지 여부를 나타내는 부울 값).
Entity > Get Entity World Position 노드를 사용하여 변환 구성요소(있는 경우)에서 엔티티의 위치를 검색하는 방법.
노드의 엔티티 변수에 있는 특별한 My Entity 또는 (me) 값을 사용하여 이 그래프를 소유하고 있는 엔티티 인스턴스를 참조하는 방법.
Entity > Get Entity Unit 노드를 사용하여 엔티티의 유닛 구성요소(있는 경우)에 할당된 유닛 인스턴스를 가져오는 방법.
엔티티의 흐름이 Event > External In Event 가져오기에 대한 반응으로 일부 로직을 트리거할 수 있는 방법. 이 이벤트는 Level Flow 그래프에서, 또는 stingray.FlowComponent.trigger_flow_event() Lua 함수를 호출하여 트리거할 수 있습니다. 프로젝트의 Lua 코드에 있는 FlowComponent 관리자에 액세스하여 사용하는 자세한 방법은 게임 플레이 중 엔티티와 상호 작용도 참조하십시오.
편집기에서 엔티티에 대한 흐름 구성요소를 설정하는 방법:
Asset Browser 또는 Explorer 패널에서 엔티티를 선택합니다.
Property Editor에서 엔티티에 새 Flow 구성요소를 추가합니다.
새 흐름 구성요소의 Flow 특성이 흐름 그래프를 저장한 리소스를 가리키도록 설정합니다.
Lua는 흐름에 표시되는 것보다 많은 API 함수에 액세스할 수 있기 때문에 엔티티의 동작을 설정하는 데 아주 좋습니다.
스크립트 동작을 설정하는 것과 관련된 작업의 대부분은 Lua 모듈을 만드는 것입니다.
직접 만든 엔티티에 대한 동작 모듈의 작성을 시작하기 가장 좋은 방법은 core/components/templates/script_component.template에 있는 템플릿으로 시작하는 것입니다. 이 템플릿은 동작을 직접 빌드하기 위한 훌륭한 토대가 되며, 대부분의 경우 작동하는 데 문제가 없고, 몇 가지 어려운 것들을 대신 해결해 줍니다.
이 파일을 프로젝트에 복사하고 .lua 확장자를 사용하여 이름을 바꾸십시오.
템플릿을 편집하고, MyBehavior의 이름을 제어할 엔티티를 설명하는 고유한 이름으로 바꾸십시오.
템플릿에서 함수 구현을 마무리하거나, 필요에 맞게 변경하십시오.
유일한 절대적 요구사항은 모듈이 component라는 필드를 포함하는 오브젝트를 반환해야 한다는 것입니다. 그리고 이 component 필드는 name 필드를 포함하는 오브젝트를 참조해야 합니다.
component 오브젝트는 엔티티가 살아 있는 동안의 다른 시간에 스크립트 구성요소가 찾는 특정 함수를 포함할 수도 있습니다. (이러한 함수는 템플릿 스크립트에서 부분적으로 구현된 함수입니다.) 모듈에서 이러한 함수를 정의하는 경우에는 스크립트 구성요소가 지정된 시간에 해당 기능을 자동으로 호출합니다.
예를 들어 구성요소에 대해 spawned() 함수를 만들면 이 모듈과 연관된 스크립트 구성요소가 있는 엔티티가 생성될 때마다 해당 함수가 자동으로 호출됩니다. 따라서 엔티티에 대해 필요한 모든 초기화를 수행할 수 있는 기회가 생깁니다. 마찬가지로, update() 함수를 만들면 살아 있는 엔티티가 이 모듈과 연관되어 있는 동안 해당 함수가 각 프레임마다 조직적으로 호출됩니다.
스크립트 구성요소 모듈에서 설정할 수 있는 모든 함수에 대한 전체 목록, 그리고 각각에 전달되는 매개변수를 보려면 core/components/templates/script_component.template 파일을 참조하십시오.
이 스크립트를 작성할 때 염두에 두어야 할 가장 어려운 점은 모듈이 게임 표준 전체에서 이 스크립트와 연관된 모든 엔티티를 처리해야 한다는 것입니다. 각 엔티티에 대해 이 스크립트에서 정의하는 구성요소 오브젝트의 복사본을 따로 가지고 있을 필요는 없습니다. 게임 안에 이 Lua 오브젝트의 인스턴스는 하나뿐이기 때문입니다. 스크립트 모듈 자체는 관련 엔티티가 처음 생성될 때 한 번만 실행됩니다. 그다음에는 이 모듈에 있는 함수 중 하나를 호출해야 할 때마다(예: update() 기능) 한 번만 호출됩니다. 이러한 함수를 구현할 때는 구성요소가 해당 구성요소와 연관된 모든 엔티티 인스턴스에 대한 이벤트를 처리해야 한다는 점에 유의해야 합니다.
예를 들어 템플릿 파일을 보면 spawned() 및 unspawned()에 대해 미리 쓰여진 함수 정의가 구성요소를 현재 사용하고 있는 모든 엔티티에 대해 world_data 필드에 몇 가지 상태 정보를 캐시하는 것을 확인할 수 있습니다. update() 함수에 있는 이 캐시를 사용하여 업데이트가 필요한 모든 엔티티를 루프합니다.
어디에서든지 스크립트를 요구할 필요는 없습니다. 스크립트 구성요소는 게임 속에서 Lua 환경에 로드되는 것을 자동으로 처리합니다.
core/entities/vector_fields에서 몇 가지 다른 작업 예제를 볼 수도 있습니다. 이러한 스크립트 구성요소는 수준에서 입자를 흩날릴 수 있는 바람 효과를 설정합니다. 벡터 필드, 그리고 이러한 스크립트 구성요소가 사용되는 방법에 대한 추가적인 배경 정보를 원하는 경우 벡터 필드(바람) 효과 설정도 참조하십시오.
편집기에서 엔티티에 대한 스크립트 구성요소를 설정하는 방법
Asset Browser 또는 Explorer 패널에서 엔티티를 선택합니다.
Property Editor에서 엔티티에 새 Script 구성요소를 추가합니다.
스크립트 구성요소의 Script 특성이 Lua 모듈을 가리키도록 설정합니다.
프로젝트의 Lua 코드에서는 모듈에서 정의하는 구성요소 오브젝트에 직접 액세스할 수 없습니다. 하지만 stingray.EntityManager.script_component()를 호출하여 가져오는 stingray.ScriptComponent 관리자 API를 통해 구성요소와 상호 작용할 수 있습니다.
예를 들어 ScriptComponent.broadcast()를 사용하여 스크립트 구성요소 관리자가 해당 함수를 정의하는 모든 스크립트 구성요소에서 특정 함수를 자동으로 호출하도록 할 수 있습니다.
stingray.ScriptComponent 관리자는 표준에 있는 모든 스크립트 구성요소를 관리하는 책임을 맡고 있습니다. 따라서 특정 동작과 연관된 엔티티하고만 상호 작용하려는 경우에는 아마도 ScriptComponent.instance_ids_with_script() 또는 ScriptComponent.entities_with_script()를 호출하여 해당 목록을 필터링하기를 원할 것입니다.
필터링된 스크립트 구성요소 인스턴스 목록이 있으면 ScriptComponent.dispatch()를 호출하여 해당 동작 목록에 대해서만 관리자가 특정 함수를 호출하도록 할 수 있습니다.