이 씬 그래프 기능은 실험단계 상태입니다. 프로젝트 세팅에서 실험단계 씬 그래프 기능을 활성화하는 체크 박스를 선택하여 씬 그래프 내에서 이 실험단계 기능에 액세스할 수 있습니다.
프로젝트에 실험단계 씬 그래프 기능이 포함된 경우 크리에이터 포털의 유효성 검사 프로세스에서 발견되어, 섬 퍼블리싱을 제한하는 에셋에 대한 알림을 받게 됩니다. 섬을 퍼블리싱하려면 프로젝트 세팅에서 실험단계 기능을 비활성화하세요.
씬 그래프에는 단일 이벤트나 이벤트 체인을 씬 그래프에 생성하는 씬 이벤트(Scene Event)라는 기능이 모든 엔티티 및 컴포넌트에 내장되어 있습니다. 씬 이벤트는 통신 프로토콜로, 엔티티 및 컴포넌트에 새로운 행동을 오버라이드 및 정의하여 씬 그래프의 여러 부분이 서로 통신할 수 있게 합니다.
씬 이벤트는 여러 프로젝트에서 재사용할 수 있으며,이벤트 체인에서 이벤트를 추가하거나, 엔티티 및 컴포넌트가 약간 다르게 행동하도록 미세조정하여 확장할 수 있습니다.
다수의 컴포넌트가 하나의 씬 이벤트에 응답할 수 있으며, 씬 그래프 계층구조의 위나 아래로 이벤트를 전송할 수 있습니다. 씬 이벤트는 씬 그래프 전체에 전달되는 메시지로, 각 컴포넌트에 메시지에 응답할 기회를 준다고 생각하면 이해하는 데 도움이 됩니다.
예를 들어 씬 그래프를 사용하여 묘지를 구성하는 경우, 씬 이벤트를 사용하여 스태틱 메시 묘지 출입문이 활짝 열릴 때 시작되는 이벤트 체인을 정의할 수 있습니다. 출입문이 열리는 것이 이벤트 체인의 시작점 역할을 하여, 유령 파티클 이펙트가 묘비 뒤에서 튀어나오고 음산한 음악이 재생되도록 할 수 있습니다.
묘지에서 씬 이벤트를 여러 번 사용할 수도 있고, 일종의 스태틱 메시 문이 열려 일련의 이벤트가 뒤따르는 씬 이벤트의 기본 기능을 사용할 수 있도록 이벤트를 미세조정할 수도 있습니다.
씬 이벤트의 핵심은 씬 그래프를 여러 부분을 각각 분리하여, 서로 직접 바인딩하는 대신 메시지를 통해 통신할 수 있도록 하는 것입니다.
씬 이벤트 작동 방식
Verse는 씬 그래프의 이벤트를 특정 엔티티 및 컴포넌트에 브로드캐스트하는 데 사용됩니다. component에서 씬 이벤트를 처리하려면 component의 기존 OnReceive(scene_event):logic 함수를 오버라이드합니다. 그러면 컴포넌트를 통과하는 모든 씬 이벤트가 이 함수를 호출하여 이벤트에 응답할 수 있도록 합니다.
씬 이벤트는 scene_event 인터페이스를 구현하는 모든 클래스입니다. 씬 이벤트는 SendUp, SendDown 또는 SendDirect라는 3가지 방식 중 하나로 전송할 수 있습니다.
SendUp
SendUp은 타기팅된 엔티티와 그 부모로 이벤트를 전송합니다. 그런 다음 부모 엔티티는 해당 이벤트를 자신의 부모에게 전달하며, 월드 내 엔티티들의 부모로 지정된 시뮬레이션 엔티티에 도달할 때까지 이 작업이 반복됩니다.
전송자는 정확히 어떤 수신자가 이벤트를 처리할지, 또는 무언가가 이벤트에 응답할지 여부를 전혀 모릅니다. 이러한 유형의 전송은 원격 측정 전송, 상위 시스템에 신호 전달, 또는 처리될 수도 있고 처리되지 않을 수도 있는 다양한 유형의 요청에 적합합니다.
예를 들어, 검으로 캐릭터의 발을 타격하는데 발이 계층구조의 하위에 위치해 있다고 생각해 보세요. 다리는 피해를 어떤 방식으로도 처리하지 못하므로, 이벤트는 캐릭터의 베이스까지 위로 전파됩니다. 캐릭터의 베이스에는 피해 이벤트를 수신하고 히트를 처리할 수 있는 damage_receiever_component를 배치해 두었습니다.
아래 다이어그램에서 부모 엔티티는 1번 라벨이 지정된 이벤트로, 첫 번째 녹색 엔티티에서 발동합니다. SendUp 호출은 계층구조 내 부모 엔티티에서 시작되어 이벤트를 시뮬레이션 엔티티를 향해 위로 전송합니다.
SendDown
또는, 시뮬레이션 엔티티를 촉매제로 사용하여 일련의 변경사항을 엔티티 트리 아래로 전송할 수 있습니다. SendDown은 타기팅된 엔티티와 그의 모든 자손으로 이벤트를 전송합니다. 그런 다음 각 자손은 해당 이벤트를 자신의 자손으로 전달합니다.
이 방식은 글로벌 이벤트가 발생했으며 씬의 모든 요소가 여기에 응답할 기회를 가져야 하는 상황에서 사용할 수 있습니다.
SendDirect
SendDirect는 이벤트를 타기팅된 엔티티로 직접 전송하지만, 부모나 자손에게는 이벤트를 전달하지 않습니다. 이 방식은 아래 다이어그램에 나와 있는 것처럼, 특정 엔티티 또는 컴포넌트를 타기팅하는 데 사용됩니다.
이벤트 소비하기
이벤트가 엔티티 계층구조에서 위나 아래로 전송되는 경우, 개별 컴포넌트는 이벤트에 응답하지 않도록 설정할 수 있습니다. 해당 컴포넌트는 이벤트를 완료로 표시하고 자손이나 부모에게 이벤트를 전송하지 않으므로 기본적으로 끄기 스위치 역할을 합니다.
이벤트 소비는 이벤트가 영향을 미치는 범위를 제어할 수 있으며, 다음 두 가지 방식으로 작동합니다.
이벤트를 하나의 엔티티에만 관련짓고 엔티티의 자식이나 부모에는 관련짓지 않기
관련 이벤트를 엔티티의 자손 또는 부모에 직접 전송하지 않기
이벤트를 자손이나 부모에 전달하지 않음으로써, 이 이벤트가 엔티티의 부모나 자손에게 어떤 의미가 있는지 결정할 수 있습니다. 그리고 해당 엔티티가 초기 이벤트에 응답하는 방식을 보다 세밀하게 제어하기 위해 다른 이벤트를 수동으로 전송할 수 있습니다.
예를 들어, 엔티티가 SendDown을 통해 피해 이벤트를 수신한다고 가정해 보겠습니다. 자손 엔티티가 피해를 받을 필요가 없으므로, 하나의 엔티티에 있는 한 컴포넌트가 체력을 소모하여 여기에 응답하도록 설정할 수 있으며, 이 이벤트를 엔티티 계층구조를 통해 더는 전송하지 않습니다.
하지만 득점 시스템이 수신 엔티티 위에 배치된 경우, 적에게 피해를 준 플레이어에게 메달을 수여하기 위해 엔티티의 부모 체인이 피해 정보를 전송해야 할 수 있습니다. 이러한 상황에서 특수한 이벤트가 있는 수신 엔티티에 SendUp 호출을 사용할 수 있습니다. 특수한 이벤트는 득점 정보를 수신하는 부모 컴포넌트에 피해 점수를 전송하는 이벤트입니다.
SendUp 및 SendDown 중 이벤트 소비
SendUp 또는 SendDown으로 트리거된 이벤트 전파 중에, 컴포넌트의 OnReceive(SceneEvent:scene_event):logic 구현에서 true를 반환하여 이벤트를 소비할 수 있습니다.
한 엔티티의 어떤 컴포넌트가 SendUp 중에 이벤트를 소비하기로 한 경우, 해당 엔티티의 모든 컴포넌트는 여전히 각각의 OnRecieve 콜백을 호출합니다. 그러면 전파가 중단되어 엔티티의 부모로 전달되지 않습니다.
한 엔티티의 어떤 컴포넌트가 SendDown 중에 이벤트를 소비하기로 한 경우, 해당 엔티티의 모든 컴포넌트는 여전히 각각의 OnRecieve 콜백을 호출합니다. 이벤트는 엔티티의 자손으로 전달되지 않습니다. 하지만 이벤트는 동일 수준의 나머지 엔티티로는 계속 전달됩니다.
아래 다이어그램에서 씬 이벤트 4가 이벤트 체인 아래로 계속 전달되는 반면, 씬 이벤트 3은 전달되지 않는 모습을 확인할 수 있습니다.
씬 이벤트 생성하기
씬 이벤트를 생성하기 전에 몇 가지 초기 구성과 시퀀스 작업을 해야 합니다. 아래에 나열된 에셋을 빌드하여 메시 컴포넌트를 나무로 채우고, 파티클 이펙트를 적절한 이펙트로 채우세요. 파티클 이펙트 에셋을 저장하면 Assets.digest.verse라는 Verse 파일에 코드에서 참조할 수 있는 Verse 오브젝트로 자동 저장됩니다.
번개가 엔티티 위 하늘의 랜덤 지점에서 시작되어 지면의 씬 그래프 엔티티에서 끝나도록 하려면 번개 VFX를 다음과 같이 수정합니다.
빔 이미터 구성(Beam Emitter Setup) > 빔 시작(Beam Start)을 위치에 벡터 추가(Add Vector to Position)로 설정하고, 위치(Position)를 SimulationPosition으로 설정하고, 벡터(Vector)를 랜덤 범위 벡터(Random Range Vector)로 설정하되 최소(Minimum)를 (-200.0, -200.0, 1000)으로, 최대(Maximum)를 (200.0, 200.0, 2000.0)으로 설정합니다.
빔 이미터 구성 > 빔 끝(Beam End)을 SimulationPosition으로 설정합니다.
이제 번개가 엔티티 위 하늘 어딘가에서 시작되어
particle_system_component가 어태치된 엔티티에서 끝납니다.스태틱 메시 나무 및 잔디
모델링 모드로 자신만의 나무를 모델링합니다.
이러한 에셋을 엔티티에 추가한 후 번개가 칠 수 있는 씬 그래프 곳곳에 다수의 번개 타깃 엔티티를 배치합니다. 이러한 각 번개 타깃 엔티티에는 씬 이벤트에서 정의하는 인스트럭션을 수신할 준비가 된 번개 particle_system_component가 있습니다. 추가 구성은 필요하지 않습니다.
엔티티는 프리팹에서 중첩시킬 수도 있고, 완전히 분리하여 씬에 분산시킬 수도 있습니다.
UE 시작용 콘텐츠 팩에서 에셋을 마이그레이션하여 불 VFX를 만들거나, UE에서 번개 및 불 VFX를 만든 후 해당 에셋을 UEFN 프로젝트로 마이그레이션할 수 있습니다.
씬에 엔티티를 추가하기 전에 모든 에셋을 만들어야 제작한 모든 스태틱 메시 에셋이 메시 컴포넌트 메뉴에 나타납니다.
엔티티가 준비되면 산불을 일으킬 이벤트의 시퀀스에 대해 생각해 본 다음, 이벤트가 어떤 작업을 수행하는지 설명해 주는 이벤트 이름을 생각해 보세요. 그 후 행동 코딩하기 섹션의 Verse 튜토리얼을 따라 진행합니다.
씬 이벤트 명명 규칙
씬 이벤트를 명명할 때는 문자를 원하는 수만큼 사용할 수 있습니다. 명칭은 damage_taken_event, health_power_up_event 등과 같이 이벤트를 설명하고, 이벤트의 의도를 명료하게 보여줄 수 있어야 합니다.
산불 이벤트 시퀀스에는 다음과 같은 2개의 주요 이벤트가 있습니다.
낙뢰
불 확산
이벤트가 어떤 작업을 수행하는지 설명하기 위해, 번개 이벤트를 struck_by_lightning_event로, 불 확산 이벤트를 fire_propagation_event로 명명합니다.
이벤트 시퀀스
씬 이벤트를 생성할 때는 이벤트를 엔티티 및 컴포넌트 계층구조의 위아래로 영향을 미치는 인터페이스로 간주해야 합니다. 또한 씬 이벤트는 다른 사람이 사용할 수도 있으므로, 다른 개발자가 어떻게 자신의 씬 그래프에서 이 이벤트를 바탕으로 빌드하거나 이 이벤트를 사용할 수 있을지 고려해야 합니다.
빌드 중인 씬 이벤트는 부모 이벤트와 관련된 다른 이벤트가 시작되기 전에 발생하는 주요 이벤트를 보고합니다. 따라서 이벤트 시퀀스는 다음과 같습니다.
월드에서
struck_by_lightning_event라는 씬 이벤트가 발생합니다.엔티티가
struck_by_lightning_event에 의해 번개에 맞았는지 여부를 보고합니다. 번개에 맞은 엔티티가fire_propagation_event를 트리거합니다.fire_propagation_event는 다른 엔티티들이 불이 옮겨붙을 정도로fire_propagation_event와 충분히 가까운지 여부를 결정하도록 합니다.fire_propagation_event가 다른 메시 컴포넌트로 확산됩니다.
fire_propagation_event는 fire_propagation_event와 충분히 가깝다고 결정한 모든 메시 컴포넌트에 불이 옮겨붙을 때까지 계속 실행됩니다. 씬에서 실행 시 이 과정은 실제 산불과 유사합니다.
시퀀스 확장하기
struck_by_lightning_event가 fire_propagation_event를 발동시키는 동안, 불을 전파하는 새로운 요소를 추가하여 게임을 확장할 수 있습니다. 예를 들어 폭발 시 fire_propagation_event를 전송하는 explosive_event를 추가해 볼 수 있습니다.
씬 이벤트에 관한 또 다른 흥미로운 점은 fire_propagation_event를 처리하는 엔티티가 불의 발생 원인을 파악할 필요 없이, 무언가로 인해 자신에게 불이 붙어야 할지 여부를 고려해야 한다는 사실만 알면 된다는 것입니다. 따라서 다음 두 가지 이유로 인해 코드를 유지하기가 더 쉽습니다.
월드에서
struck_by_lightning_event라는 씬 이벤트가 발생합니다.fire_propagation_event만 고려하는 엔티티를 분해하지 않고struck_by_lightning_event의 행동 방식을 변경하면 되므로 더 쉽습니다.가연성 요소는
fire_propagation_event만 고려하므로explosive_event를 작성하는 것이 더 쉽습니다.
행동 코딩하기
모든 필수 엔티티를 갖춘 씬 그래프가 완성되었다면, 아래 코드를 사용하여 번개가 내리치는 것으로 시작해 나무에 불이 나고 불 피해를 입히는 씬 이벤트를 생성하세요.
Assets.digest.verse는 Verse 오브젝트를 자동으로 검색하여 씬에서 참조합니다. 생성한 파티클 이펙트는 VFX 모듈 아래에서 참조됩니다.
VFX := module:
Fire_NS<scoped {/InvalidDomain/Scene_Events_Test}> := class<final><public>(particle_system_component):
Lightning_NS<scoped {/InvalidDomain/Scene_Events_Test}> := class<final><public>(particle_system_component):
1단계: 씬 그래프 컴포넌트 생성
UEFN에서 씬 이벤트를 생성하려면 메뉴 바에서 Verse 메뉴를 열고 드롭다운 메뉴에서 Verse 익스플로러(Verse Explorer)를 선택합니다. Verse 익스플로러 패널은 에디터에서 열리며, 여기에는 프로젝트와 연관된 Verse 파일 목록이 포함되어 있습니다.
다음 단계를 따라 새 Verse 파일을 생성합니다.
목록 상단의 프로젝트 이름을 우클릭합니다.
드롭다운 메뉴에서 프로젝트에 새로운 Verse 파일 추가(Add new Verse file to project)를 선택합니다. Verse 스크립트 생성 창이 열립니다.
Verse 파일 목록에서 씬 그래프 컴포넌트(Scene Graph Component)를 선택하고 파일을 fire_event_component로 명명합니다.
생성(Create)을 클릭합니다. 파일이 Visual Studio Code(VS Code)에서 자동으로 열리며, 파일에는 새 컴포넌트 행동을 생성하는 데 필요한 보일러플레이트 API가 포함되어 있습니다.
스크립트를 테스트할 준비가 되면 Verse 메뉴를 열고 드롭다운 메뉴에서 Verse 코드 빌드(Build Verse Code)를 선택합니다. 그런 다음 Verse 버튼을 선택하여 코드를 실행합니다.
2단계: Verse 라이브러리 추가
먼저 번개를 일으키는 이벤트 시퀀스 및 조건을 빌드하는 것으로 씬 이벤트를 시작합니다. 번개 이벤트를 정의한 후에는 불 피해, 불 확산 프로토콜, 불 끄기 프로토콜의 프로퍼티를 정의하여 산불 이벤트를 빌드합니다.
번개 및 불의 위치에 공간 수학을 사용하고, 동시실행을 생성하고, 다른 Verse 기능을 활용할 수 있도록 컴포넌트에 다음 라이브러리를 추가합니다.
Verseusing { /Verse.org/SpatialMath } using { /Verse.org/Random } using { /Verse.org/Concurrency } using { /Verse.org/Simulation } using { /Verse.org/SceneGraph }
3단계: 번개 이벤트 클래스 정의
이 이벤트 클래스는 번개의 소스 위치, 번개 히트 위치, 히트 위치의 DamageRadius를 결정합니다.
struck_by_lightning_event := class(scene_event):로 명명된 이벤트 클래스를 생성합니다. 이 클래스는 위치 정보에 벡터를, 낙뢰 피해 반경에float값을 사용하여 씬에서 번개 이벤트가 발생하는 위치를 설명하는 constant 표현식에서 씬 이벤트의 프로퍼티를 정의합니다.Verse# Event to indicate an entity is struck by lightning struck_by_lightning_event<public> := class(scene_event): # Lightning hit location HitLocation:vector3 = vector3{} # Lightning damage radius DamageRadiusCentimeters:float = 100.0
4단계: 날씨 컴포넌트 생성 및 편집 가능한 프로퍼티와 변수 추가
편집 가능한 프로퍼티와 변수를 사용하여 씬에 번개가 표시되는지 여부, 랜덤 낙뢰, 낙뢰 간 시간 간격, 낙뢰 피해 반경을 설정합니다.
lightning_weather_component := component ():로 명명된 컴포넌트 클래스에editable프로퍼티를 추가하여 번개의 행동 방식을 정의합니다. 낙뢰 간 시간 간격과 해당 낙뢰의 피해 반경(cm)에 대한 편집 가능한 프로퍼티에 최소 및 최대 양을 대략적으로 설정합니다.Verse# Component that lives on an entity, and randomly creates lightning strikes lightning_weather_component<public> := class<final_super>(component): # Minimum random time between lightning strikes @editable MinRandomLightningDelaySeconds:float = 10.0 # Maximum random time between lightning strikes @editable MaxRandomLightningDelaySeconds:float = 60.0
5단계: 번개 이벤트 정의
메서드를 사용하여 번개 VFX를 확인하고, 시작 및 끝 빔 프로퍼티를 사용하여 메시 컴포넌트가 이 VFX와 얼마나 가까운지 결정한 뒤 이 정보를 이벤트의 위아래로 브로드캐스트합니다.
OnSimulate조건부메서드를 생성합니다.VerseOnSimulate<override>()<suspends>:void=재생 시간에 최소 및 최대 딜레이 값을 사용하는 상수를 통해 번개 컴포넌트를 랜덤으로 재생 및 중지하는
loop를 생성하여 추가합니다.Verseloop: # Sleep for a random delay before next lightning strike RandomDelay := GetRandomFloat(MinRandomLightningDelaySeconds, MaxRandomLightningDelaySeconds) Sleep(MaxRandomLightningDelaySeconds다른 모든 엔티티는 시뮬레이션 엔티티의 자손이므로, 시뮬레이션 엔티티를 사용하여 시뮬레이션 내 다른 엔티티를 찾는
if표현식을 추가합니다. 이 방식은 콜리전을 사용하여 씬 내 엔티티를 찾는 대신 랜덤 엔티티를 선택하여 번개를 맞게 할 수 있습니다.Verse# Randomly hit an entity in the world with lightning if (SimEntity := Entity.GetSimulationEntity[]):다음으로, 코드는 번개를 맞을 타깃을 제공해야 합니다.
then표현식을 추가하여 번개 타깃이 SimEntity의 아래가 되도록 하는 요청을 브로드캐스트합니다. 그런 다음 이 브로드캐스트에 응답하여, 응답 가능한 모든 엔티티가 SimEntity를 향해 이벤트를 다시 위로 전송하도록 하는 조건부if표현식을 추가합니다. 다음으로 번개의 소스를 찾아야 합니다. 이는 빔 이미터가 빔의 시작과 끝에 두 지점의 위치를 사용하기 때문입니다.VerseLightningTargets := for (EntityWithLightning : SimEntity.FindDescendantEntitiesWithComponent(particle_system_component)): EntityWithLightning if: LightningTargets.Length > 0 RandomIndex := GetRandomInt(0, LightningTargets.Length - 1) RandomEntity := LightningTargets[RandomIndex]if 문을 사용하여 랜덤 위치에
LightningVFXComponent를 호출합니다. 그런 다음 소스 및 타깃 위치로 설정된 위치에서 빔 파티클 이펙트를 재생하는 then 표현식을 추가합니다.lightning_entity는 빔 이미터 구성 > 빔 시작을 사용하여 하늘의 랜덤 지점에서 번개 이벤트를 재생합니다. 그런 다음LightningVFXComponent가 빔 파티클 옵션(빔 이미터 구성 > 빔 끝)을 사용하여 씬에 빔 파티클의 끝이 나타날 위치를 결정합니다. 이 세팅은lightning_entity에 파티클 이펙트의 끝 좌표를 사용하는 시뮬레이션 위치로 설정됩니다.이후
struck_by_lightning_event로 입히는 피해를 생성 및 정의합니다. 이때 소스 및 타깃 데이터를 사용하여 메시 컴포넌트 타깃에서 피해가 발생하는 위치를 찾고,DamageRadius를 사용하여 번개 피해의 영향을 받는 영역을 설명합니다. 이 이벤트는 랜덤 번개 지속 시간을 추가하기 위해 시뮬레이션 엔티티를 향해 아래로 전송되므로,SimulationEntity.SendDown(Event)로 이벤트 체인을 종료합니다.Verseif (VFX := RandomEntity.GetComponent[particle_system_component]): RandomDurationOfStrike := GetRandomFloat(MinRandomLightningDurationSeconds, MaxRandomLightningDurationSeconds) VFX.Play() Sleep(RandomDurationOfStrike) VFX.Stop() else: Print("Could not find particle_system_component on this entity") Event := struck_by_lightning_event: HitLocation := Entity.GetGlobalTransform().Translation
6단계: 불 이벤트 정의
불이 입히는 피해량과 씬 내 불 피해에 기반한 불 전파 여부를 정의하는 이벤트 클래스를 생성합니다.
2개의 클래스
fire_damage_event클래스와fire_propagation_event클래스를 생성합니다. 이러한 클래스는 입히는DamageAmount를 확인하여DamageAmount가 float 한계치에 도달하면 불 파티클을 재생합니다.Verse# Event indicating an entity was damaged by fire fire_damage_event<public> := class(scene_event): BurningEntity:entity = entity{} DamageAmount:float = 100.0 # Event indicating an entity propagates fire fire_propagation_event<public> := class(fire_damage_event): FireRadiusCentimeters:float = 100.0메시가 가연성인지 결정하는
flammable_component클래스를 생성하고, 씬 내 메시에 불이 옮겨붙도록 설정할 수 있는 편집 가능 프로퍼티를 생성합니다.Verse# Component that makes something flammable flammable_component<public> := class<final_super>(component): # Fire damage amount applied every second @editable FireDamageAmount:float = 10.0 # Fire tries to propagate on this interval @editable FirePropagationIntervalSeconds:float = 10.0불 VFX가 재생 중인지 또는 재생되어야 하는지 여부를 결정하는 조건부 변수가
flammable_event에 추가됩니다.Verse# Is it on fire? var IsOnFire:logic = falseIsCloseEnoughToBurningEntityToIgnite함수는 불이 추가 불 VFX 이벤트를 트리거할 만큼 충분히 가까운지 여부를 결정합니다.Verse# Is this component close enough to the source of a fire propagation event to burst into flames? IsCloseEnoughToBurningEntityToIgnite(FirePropogationEvent:fire_propagation_event)<decides><transacts>:void = EntityLocation := Entity.GetGlobalTransform().Translation FirePropogationLocation := FirePropogationEvent.BurningEntity.GetGlobalTransform().Translation DistanceToFire := Distance(EntityLocation, FirePropogationLocation) DistanceToFire <= FirePropagationEvent.FireRadiusCentimetersIsCloseEnoughToLightningToIgnite함수는 낙뢰가 메시에 불이 붙을 만큼 충분히 가까웠는지 여부를 결정합니다.Verse# Is this component close enough to a lightning strike to burst into flames? IsCloseEnoughToLightningToIgnite(LightningEvent:struck_by_lightning_event)<decides><transacts>:void = EntityLocation := Entity.GetGlobalTransform().Translation LightningStrikeLocation := LightningEvent.HitLocation DistanceToFire := Distance(EntityLocation, LightningStrikeLocation) DistanceToFire <= LightningEvent.DamageRadiusCentimetersOnRecieve 함수는 IsCloseEnoughToBurningEntityToIgnite 함수가 불 전파의 근접성을 결정하면 어떤 메시에 불이 옮겨붙을지 결정하고, IsCloseEnoughToLightningToIgnite 변수는 메시에 대한 낙뢰의 근접성을 결정합니다.
Verse# Receive scene events OnReceive<override>(SceneEvent:scene_event):logic = # Burst into flames if lightning hit close enough if (LightningEvent := struck_by_lightning_event[SceneEvent], IsCloseEnoughToLightningToIgnite[LightningEvent]): Ignite() # Burst into flames if something close enough is burning if (FireEvent := fire_propagation_event[SceneEvent], IsCloseEnoughToBurningEntityToIgnite[FireEvent]): Ignite() falseIgnite 메서드는 불 파티클 시스템을 검색하는 if 조건문을 통해 이펙트를 자동으로 재생하는 데 사용됩니다.then문은 컴포넌트가 불 VFX를 재생하는 것이 true인지 여부를 정의합니다.불 파티클 시스템 Fire_NS를 확인하는 메서드에 비동기 작업을 추가하여 호출 시 불이 생성 및 확산되도록 합니다.
Verse# Burst into flames Ignite():void = if (not IsOnFire?): set IsOnFire = true # Add a new fire VFX component FireVFX := VFX.Fire_NS{Entity := Entity} Entity.AddComponents(array{FireVFX}) # Spawn async tasks to implement the state of being on fire
7단계: 불 이벤트 종료 정의
다음으로는 메시 컴포넌트에 불이 타오르는 시점, 불이 꺼지는 시점, 불로 인한 피해, 불이 확산되도록 할 시점을 결정하는 일련의 메서드를 생성합니다.
이제 불 이펙트를 멈추는
Extinguish 메서드를 생성합니다. 이 메서드는 조건문을 사용하여 불 이펙트를 재생하는 컴포넌트를 검색하고 불 파티클 시스템을 찾아 이펙트를 제거합니다.Verse# Put out the flames Extinguish():void= if (IsOnFire?): set IsOnFire = false # Remove the fire VFX component if (FireVFX := Entity.GetComponent[particle_system_component]): FireVFX.RemoveFromEntity()OnFire 메서드를 생성합니다. 이 메서드는FireDamage를 모니터링하는 루프를 사용하고, 이벤트 끝을 향해 엔티티 체인 아래로 이벤트를 전송하여 이벤트 재생을 멈추게 합니다.Verse# Suspends function called when we're on fire OnFire()<suspends>:void= # Damage self every second loop: # Fill out a fire damage event - replace this with whatever properties should go here FireDamage := fire_damage_event: DamageAmount := FireDamageAmount Entity.SendDown(FireDamage) Sleep(1.0)마지막으로
FirePropagation 메서드를 생성합니다. 이 메서드는루프를 사용하여 불을 엔티티 체인 아래로 전파하고 시뮬레이션 엔티티에 도달하면 불이 꺼지게 합니다.Verse# Propagate fire to other entities FirePropagation()<suspends>:void= loop: Sleep(FirePropagationIntervalSeconds) if: SimulationEntity := Entity.GetSimulationEntity[] FirePropagationEvent := fire_propagation_event{ BurningEntity := Entity } then: # Broadcast fire propagation event down from simulation entity SimulationEntity.SendDown(FirePropagationEvent)
코드가 완성되면 코드를 컴파일하고, 낙뢰 및 산불 이펙트를 뒷받침해 줄 적절한 엔티티를 씬 그래프에 추가합니다. 그런 다음 씬의 엔티티에 불이 옮겨붙을 flammable_component를 추가합니다. 시뮬레이션 엔티티 아래에는 날씨를 제어하는 lightning_weather_component가 있는 최상위 엔티티가 필요합니다.
모든 엔티티가 적절한 씬 이벤트로 업데이트되면 라이브 편집 세션을 시작하여 씬에서 코드가 작동하는지 확인합니다.
결과
복사한 코드를 프로젝트에 붙여 넣어 씬 이벤트가 작동하는지 확인합니다.
lightning.verse
using { /Verse.org }
using { /Verse.org/Native }
using { /Verse.org/Random }
using { /Verse.org/SceneGraph }
using { /Verse.org/Simulation }
using { /Verse.org/SpatialMath }
# Event to indicate an entity is struck by lightning
struck_by_lightning_event<public> := class(scene_event):
fire.verse
using { /Verse.org }
using { /Verse.org/Native }
using { /Verse.org/SceneGraph }
using { /Verse.org/Simulation }
using { /Verse.org/SpatialMath }
# Event indicating an entity was damage by fire
fire_damage_event<public> := class(scene_event):
BurningEntity:entity = entity{}
DamageAmount:float = 100.0