Ta funkcja Scene Graph jest obecnie w stanie eksperymentalnym. W ustawieniach projektu zaznacz pole, aby włączyć ustawienie Funkcje eksperymentalne Scene Graph w celu uzyskania dostępu do tych funkcji eksperymentalnych w systemie Scene Graph.
Jeśli projekt zawiera jakąkolwiek funkcję eksperymentalną Scene Graph, zostanie ona wychwycona podczas procesu weryfikacji w Portalu Twórcy. Otrzymasz powiadomienie o zasobach ograniczających możliwość opublikowania wyspy. Wyłącz funkcje eksperymentalne w ustawieniach projektu, aby opublikować wyspę.
Narzędzie Scene Graph ma wbudowaną we wszystkie jednostki i komponenty funkcję, która tworzy w Scene Graph pojedyncze zdarzenia lub łańcuch zdarzeń nazywane zdarzeniami sceny (Scene Event). Zdarzenia sceny to protokoły komunikacyjne umożliwiające różnym częściom Scene Graph komunikowanie się ze sobą poprzez zastępowanie i definiowanie nowych zachowań dla jednostek i komponentów.
Zdarzenia sceny można wykorzystywać w projektach wielokrotnie. Można je też rozszerzać, dodając dodatkowe zdarzenia lub modyfikując zachowanie jednostek i komponentów w łańcuchu zdarzeń, aby uzyskać nieco inny efekt.
Na zdarzenie sceny może reagować wiele komponentów, a zdarzenia mogą być wysyłane w górę lub w dół hierarchii Scene Graph. Można wyobrazić je sobie jako wiadomości wysyłane przez Scene Graph, na które każdy komponent ma możliwość odpowiedzieć.
Jeśli na przykład skonfigurujesz cmentarz za pomocą Scene Graph, możesz użyć zdarzeń sceny, aby zdefiniować łańcuch zdarzeń, który rozpocznie się, gdy bramy cmentarza skonfigurowane przy użyciu siatki statycznej się otworzą. Otwarcie bram może stanowić punkt rozpoczęcia łańcucha zdarzeń, które będą powodowały wyłonienie się zza nagrobków efektów cząsteczkowych emitujących duchy oraz odtworzenie upiornej muzyki.
Może to być jedno zdarzenie sceny zastosowane na cmentarzu wielokrotnie lub jego ulepszona wersja, która pozwoli skorzystać z podstawowych funkcji zdarzenia sceny – otwieranie siatki statycznej jakiegoś rodzaju drzwi i wywołanie w ten sposób szeregu zdarzeń następczych.
Zdarzenia sceny mają na celu oddzielenie poszczególnych części Scene Graph od siebie, umożliwiając im komunikowanie się za pomocą komunikatów, zamiast tworzenia powiązań bezpośrednich.
Sposób działania zdarzeń sceny
Verse służy do rozsyłania zdarzeń w Scene Graph do określonych jednostek i komponentów. Aby obsłużyć zdarzenie sceny w komponencie, zastąp istniejącą funkcję OnReceive(scene_event):logic w komponencie. Każde zdarzenie sceny, które przechodzi przez komponent, wywoła tę funkcję, umożliwiając zareagowanie na zdarzenie.
Zdarzeniem sceny jest dowolna klasa implementująca interfejs scene_event. Zdarzenia sceny można wysyłać na jeden z trzech sposobów: SendUp, SendDown lub SendDirect.
SendUp
SendUp powoduje wysłanie zdarzenia do jednostki docelowej i jej jednostki nadrzędnej. Następnie jednostka nadrzędna przekaże takie zdarzenie własnej jednostce nadrzędnej, aż dotrze ono do poziomu jednostki symulacji nadrzędnej w stosunku do wszystkich jednostek w świecie.
Nadawca nie wie dokładnie, który odbiorca obsłuży zdarzenie i czy w ogóle zareaguje na zdarzenie. Ten rodzaj wysyłania doskonale nadaje się do wysyłania danych telemetrycznych, sygnalizowania różnych kwestii systemom wyższego poziomu lub przekazywania różnego rodzaju żądań, które mogą, ale nie muszą być obsługiwane.
Wyobraź sobie na przykład, że uderzasz mieczem w stopę postaci, która jest zakorzeniona głęboko w hierarchii. Noga może w żaden sposób nie obsłużyć obrażeń, dlatego zdarzenie propagowane jest, aż do podstawy postaci, gdzie umieszczono komponent damage_receiever_component, który może odebrać zdarzenie zadania obrażeń i przetworzyć trafienie.
Na poniższym diagramie jednostka nadrzędna to zdarzenie oznaczone jako 1, które zostaje aktywowane w na poziomie pierwszej zielonej jednostki. Wywołanie SendUp rozpoczyna się na poziomie jednostki nadrzędnej w hierarchii i przekazuje zdarzenie w górę, aż do jednostki symulacji.
SendDown
Jednostki symulacji można użyć również jako katalizatora, wysyłając serię zmian w dół drzewa jednostek. Wywołanie SendDown wysyła zdarzenie do jednostki docelowej i wszystkich jej jednostek podrzędnych. Każda jednostka podrzędna przekazuje następnie zdarzenie do własnych jednostek podrzędnych.
Ten sposób sprawdza się w sytuacji, gdy wystąpiło zdarzenie globalne, a każdy element sceny powinien mieć możliwość zareagowania na nie.
SendDirect
SendDirect wysyła zdarzenie bezpośrednio do jednostki docelowej, ale nie przekazuje zdarzenia jednostkom nadrzędnym ani podrzędnym. Umożliwia komunikację bezpośrednio z konkretną jednostką lub konkretnym komponentem, jak na poniższym diagramie.
Pochłanianie zdarzeń
Gdy zdarzenie jest przesyłane w górę lub w dół hierarchii jednostek, poszczególne komponenty mogą zdecydować, że nie będą reagować na zdarzenie. Komponent oznacza zdarzenie jako ukończone i nie wysyła zdarzenia do swoich jednostek podrzędnych lub nadrzędnych, pełniąc tym samym funkcję wyłącznika.
Pochłanianie zdarzeń pozwala kontrolować zakres efektu zdarzenia. Działa to na dwa sposoby:
Pozwala stosować zdarzenia istotne tylko dla jednej jednostki, a nie jej jednostek podrzędnych czy nadrzędnych.
Pozwala unikać wysyłania istotnego zdarzenia bezpośrednio do jednostek podrzędnych lub nadrzędnych.
Unikając wysyłania zdarzenia do jednostki podrzędnej lub nadrzędnej, możesz zdecydować, co dane zdarzenie oznacza dla jednostek nadrzędnych i podrzędnych jednostki. Dzięki temu możesz ręcznie wysłać do nich inne zdarzenie, aby zyskać większą kontrolę nad sposobem reagowania tych jednostek na zdarzenie początkowe.
Załóżmy na przykład, że jednostka odbiera zdarzenie zadania obrażeń za pośrednictwem wywołania SendDown. Komponent jednej jednostki może zareagować, zmniejszając wartość zdrowia, bez dalszego przesyłania tego zdarzenia w ciągu hierarchii jednostek, ponieważ jednostki podrzędne nie muszą dodatkowo przetwarzać takich obrażeń.
Jeśli jednak nad jednostką odbierającą w hierarchii znajduje się system punktowania, łańcuch elementów nadrzędnych jednostki będzie musiał wysłać informację o obrażeniach, aby przyznać graczowi medal za zadawanie wrogom obrażeń. W tej sytuacji można zastosować wywołanie SendUp w odniesieniu do jednostki odbierającej ze zdarzeniem specjalnym, które wysyła wynik obrażeń do komponentu nadrzędnego nasłuchującego informacji o punktacji.
Pochłanianie zdarzeń w trakcie wykonywania wywołań SendUp i SendDown
Zdarzenia mogą być pochłaniane podczas propagacji zdarzeń wyzwalanej użyciem wywołania SendUp lub SendDown poprzez zwrócenie wartości true z implementacji OnReceive(SceneEvent:scene_event):logic komponentu.
Jeśli dowolny komponent w jednostce zdecyduje się pochłonąć zdarzenie w trakcie wykonywania wywołania SendUp, wszystkie komponenty w danej jednostce i tak wykonają odpowiednie wywołania zwrotne OnRecieve. Następnie propagacja zostanie zatrzymana i nie nastąpi przekazanie zdarzenia do jednostki nadrzędnej w stosunku do bieżącej jednostki.
Jeśli dowolny komponent w jednostce zdecyduje się pochłonąć zdarzenie w trakcie wykonywania wywołania SendDown, wszystkie komponenty w danej jednostce i tak wykonają odpowiednie wywołania zwrotne OnRecieve. Wówczas nie nastąpi przekazanie zdarzenia do jednostek podrzędnych w stosunku do bieżącej jednostki. Jednak zdarzenie nadal będzie przekazywane pozostałym jednostkom na tym samym poziomie.
Na poniższym diagramie można zauważyć, że zdarzenie sceny 4 jest propagowane w dół łańcucha zdarzeń, podczas gdy zdarzenie sceny 3 nie jest.
Tworzenie zdarzenia sceny
Przed utworzeniem zdarzeń sceny trzeba wykonać kilka czynności związanych z początkową konfiguracją i opracowaniem sekwencji. Utwórz wymienione poniżej zasoby, aby uzupełnić komponenty siatki drzewami i efektami cząsteczkowymi, które pozwolą uzyskać właściwy efekt. Po zapisaniu zasobów efektów cząsteczkowych są one automatycznie zapisywane w pliku Verse o nazwie Assets.digest.verse jako obiekty Verse, do których możesz tworzyć odwołania w swoim kodzie.
Aby błyskawica zaczynała się w losowym punkcie na niebie nad jednostką i kończyła na jednostce Scene Graph znajdującej się na ziemi, zmodyfikuj VFX błyskawicy w następujący sposób:
W opcji Konfiguracja emitera wiązki > Początek wiązki wybierz ustawienie Dodaj wektor do pozycji, dla opcji Pozycja wybierz ustawienie SimulationPosition, dla opcji Wektor wybierz ustawienie Losowy wektor zakresu, definiując dla opcji Minimum wartość (-200.0, -200.0, 1000), a dla opcji Maksimum wartość (200.0, 200.0, 2000.0).
W opcji Konfiguracja emitera wiązki > Koniec wiązki wybierz ustawienie SimulationPosition.
Teraz błyskawica będzie zaczynała się gdzieś na niebie nad jednostką i kończyła na jednostce, do której dołączony jest komponent
component_system_component.Drzewa i trawa wykonane przy użyciu siatki statycznej
Wymodeluj własne drzewa za pomocą trybu modelowania.
Dodaj te zasoby do jednostek, a następnie rozmieść wiele jednostek pełniących funkcję celów błyskawicy po całym obszarze Scene Graph, w miejscach, w które mogą trafić pioruny. Każda z jednostek pełniących funkcję celu błyskawicy ma komponent błyskawicy particle_system_component gotowy do odbierania instrukcji definiowanych w zdarzeniu sceny. Te czynności konfiguracyjne wystarczą.
Jednostki mogą być zagnieżdżone w gotowcu lub całkowicie oddzielne i rozmieszczone w obszarze sceny.
Przenieś zasoby z pakietu Zawartość początkowa UE, aby stworzyć efekt wizualny ognia. Możesz też stworzyć efekt błyskawicy i ognia w UE, a następnie przenieść te zasoby do swojego projektu UEFN.
Stwórz wszystkie zasoby przed dodaniem jednostek do sceny. Dzięki temu wszystkie utworzone zasoby siatki statycznej pojawią się w menu komponentów siatki.
Po umieszczeniu jednostek zastanów się nad sekwencją zdarzeń, które spowodują pożar lasu, a następnie przemyśl nazwy zdarzeń opisujące, za co odpowiada dane zdarzenie. Następnie postępuj zgodnie sekcją Kodowanie zachowania w samouczku dotyczącym języka Verse.
Konwencje nazewnictwa zdarzeń sceny
Nazwa zdarzenia sceny może składać się z dowolnej liczby znaków. Nazwa powinna precyzyjnie opisywać zdarzenie i jasno wskazywać jego cel, na przykład damage_taken_event, health_power_up_event itd.
W sekwencji zdarzeń pożaru lasu występują dwa główne zdarzenia:
Uderzenie pioruna
Rozprzestrzenianie ognia
Aby opisać sposób działania tych zdarzeń, nadaj zdarzeniu błyskawicy nazwę uderzone_by_lightning_event, a zdarzeniu rozprzestrzeniania nazwę fire_propagation_event.
Sekwencja zdarzeń
Tworząc zdarzenie sceny, potraktuj je jako interfejs, którego efekty propagowane są w górę i w dół hierarchii jednostek oraz komponentów. Ponadto zdarzenia sceny mogą być wykorzystywane przez inne osoby, dlatego zastanów się, w jaki sposób inny twórca mógłby rozwinąć twoje zdarzenie lub wykorzystać je we własnym projekcie Scene Graph.
Zdarzenie sceny, które tworzysz, będzie zgłaszać główne zdarzenia, które mają miejsce przed rozpoczęciem innego zdarzenia powiązanego ze zdarzeniem nadrzędnym. Zatem sekwencja zdarzeń jest następująca:
W świecie występuje zdarzenie sceny o nazwie
struck_by_lightning_event.Jednostki raportują, czy zostały trafione przez zdarzenie
struck_by_lightning_event. Jednostki trafione przez piorun aktywują zdarzeniefire_propagation_event.Zdarzenie
fire_propagation_eventwymusza na innych jednostkach zadecydowanie, czy znajdują się wystarczająco blisko zdarzeniafire_propagation_event, aby również zająć się ogniem.Zdarzenie
fire_propagation_eventrozprzestrzenia się na inne komponenty siatki.
Zdarzenie fire_propagation_event jest wykonywane do momentu, aż każdy komponent siatki, który uzna, że znajduje się wystarczająco blisko zdarzenia fire_propagation_event, zapali się. Po uruchomieniu w scenie efekt powinien przypominać rzeczywisty prawdziwy pożar lasu.
Rozbudowywanie sekwencji
Zdarzenie struck_by_lightning_event powoduje wystąpienie zdarzenia fire_propagation_event, jednak dodatkowo grę można rozbudować o nowe elementy powodujące rozprzestrzenianie pożaru. Załóżmy na przykład, że dodajesz zdarzenie explosive_event, które w momencie wybuchu wysyła zdarzenie fire_propagation_event.
Inną ciekawą cechą zdarzeń sceny jest to, że jednostki obsługujące zdarzenie fire_propagation_event nie muszą wiedzieć, co spowodowało pożar, a jedynie to, że coś wymusza na nich decyzję, czy zająć się ogniem. Pozwala to zwiększyć czytelność kodu z dwóch powodów:
W świecie występuje zdarzenie sceny o nazwie
struck_by_lightning_event.Łatwiej jest zmienić sposób zachowania zdarzenia
strike_by_lightning_eventbez naruszania jednostek, które interesuje jedynie zdarzeniefire_propagation_event.Zdarzenie
explosive_eventłatwiej napisać, ponieważ elementy palne interesuje wyłącznie zdarzeniefire_propagation_event.
Kodowanie zachowania
Gdy Scene Graph będzie zawierać wszystkie wymagane jednostki, użyj poniższego kodu, aby utworzyć zdarzenie sceny, które rozpoczyna się uderzeniem pioruna powodującym zajęcie się drzew ogniem zadającym obrażenia.
Plik Assets.digest.verse automatycznie wyszukuje obiekty Verse, aby utworzyć do nich odwołania w scenie. Do utworzonych efektów cząsteczkowych tworzy się odwołania w module 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):
Krok 1: Utworzenie komponentu Scene Graph
Aby utworzyć zdarzenie sceny w UEFN, otwórz menu Verse na pasku menu i wybierz Eksplorator Verse z menu rozwijanego. W edytorze otworzy się panel Eksploratora Verse zawierający listę plików Verse powiązanych z projektem.
Utwórz nowy plik Verse, wykonując następujące czynności:
Kliknij prawym przyciskiem myszy nazwę projektu u szczytu listy.
Wybierz opcję Dodaj nowy plik Verse do projektu z menu rozwijanego. Zostanie otwarte okno tworzenia skryptu Verse.
Z listy plików Verse wybierz opcję Komponent Scene Graph i nadaj mu nazwę fire_event_component.
Kliknij opcję Utwórz. Plik zostanie otwarty automatycznie w edytorze Visual Studio Code (VS Code) i będzie zawierał szablonowe interfejsy API niezbędne do utworzenia nowego zachowania komponentu.
Gdy wszystko będzie gotowe do przetestowania skryptu, otwórz menu Verse i z menu rozwijanego wybierz opcję Skompiluj kod Verse. Następnie wybierz przycisk Verse, aby wykonać kod.
Krok 2: Dodanie bibliotek Verse
Rozpocznij zdarzenie sceny od opracowania sekwencji zdarzeń i warunków, które powodują uderzenie pioruna. Po zdefiniowaniu zdarzenia błyskawicy rozbuduj zdarzenie pożaru lasu, definiując właściwości obrażeń zadawanych przez ogień, protokoły rozprzestrzeniania ognia i protokoły gaszenia ognia.
Dodaj poniższe biblioteki do utworzonego komponentu, aby umożliwić wykorzystanie matematyki przestrzennej do ustalania lokalizacji błyskawicy i ognia, tworzenia współbieżności i obsługi innych funkcji Verse.
Verseusing { /Verse.org/SpatialMath } using { /Verse.org/Random } using { /Verse.org/Concurrency } using { /Verse.org/Simulation } using { /Verse.org/SceneGraph }
Krok 3: Zdefiniowanie klasy zdarzenia błyskawicy
Ta klasa zdarzenia określa lokalizację źródła błyskawicy, lokalizację trafienia pioruna oraz promień obrażeń DamageRadius lokalizacji trafienia.
Utwórz klasę zdarzenia o nazwie
struck_by_lightning_event := class(scene_event):. Klasa ta definiuje właściwości zdarzenia sceny w wyrażeniach stałych, które opisują miejsce wystąpienia zdarzenia pioruna w scenie, wykorzystując wektor do przekazania danych lokalizacji i promienia obrażeń pioruna przy użyciu wartościfloat.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
Krok 4: Utworzenie komponentu pogody i dodanie edytowalnych właściwości przy użyciu zmiennych
Użyj edytowalnych właściwości i zmiennych, aby ustalić, czy błyskawica pojawia się w scenie, zdefiniować losowe trafienia piorunów i odstęp czasu między uderzeniami pioruna, a także promień, w jakim uderzenie pioruna zadaje obrażenia.
Zdefiniuj sposób zachowania błyskawicy, dodając właściwości
editabledo klasy komponentu o nazwielightning_weather_component := component ():. We właściwościach edytowalnych zdefiniuj minimalną i maksymalną wartość czasu między uderzeniami pioruna oraz wyrażony w centymetrach promień, w którym zadają one obrażenia.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
Krok 5: Definiowanie zdarzenia błyskawicy
Za pomocą metody sprawdź efekt VFX błyskawicy i na podstawie jego właściwości początku i końca wiązki określ, jak blisko efektu VFX znajdują się komponenty siatki, a także roześlij tę informację w górę i w dół hierarchii zdarzeń.
Utwórz warunkowy blok
methodOnSimulate.VerseOnSimulate<override>()<suspends>:void=Utwórz i dodaj blok
loop, który losowo odtwarza i wstrzymuje komponent błyskawicy, za pomocą stałej wykorzystującej minimalne i maksymalne wartości opóźnienia dla czasu odtwarzania.Verseloop: # Sleep for a random delay before next lightning strike RandomDelay := GetRandomFloat(MinRandomLightningDelaySeconds, MaxRandomLightningDelaySeconds) Sleep(MaxRandomLightningDelaySecondsDodaj wyrażenie
if, które wykorzystuje jednostkę symulacji do wyszukania innych jednostek w całej symulacji, ponieważ wszystkie inne jednostki są podrzędne względem jednostki symulacji. Dzięki temu można losowo wybrać jednostkę, która ma być trafiona piorunem, zamiast wyszukiwania takich jednostek w scenie przy użyciu kolizji.Verse# Randomly hit an entity in the world with lightning if (SimEntity := Entity.GetSimulationEntity[]):Następnie kod musi wskazać cel, w który trafi piorun.
Dodaj wyrażenie
then, które rozgłasza żądanie zostania celem pioruna w dół hierarchii jednostek podrzędnych względem SimEntity. Następnie dodaj wyrażenie warunkoweif, które reaguje na to rozgłoszenie i powoduje, że wszystkie jednostki, które mogą zareagować, wysyłają zdarzenie z powrotem do SimEntity. Następnie musisz znaleźć źródło błyskawicy, ponieważ emiter wiązki używa dwupunktowej lokalizacji uwzględniającej początek i koniec wiązki.VerseLightningTargets := for (EntityWithLightning : SimEntity.FindDescendantEntitiesWithComponent(particle_system_component)): EntityWithLightning if: LightningTargets.Length > 0 RandomIndex := GetRandomInt(0, LightningTargets.Length - 1) RandomEntity := LightningTargets[RandomIndex]Wywołaj
LightningVFXComponentw losowej lokalizacji za pomocą instrukcji if. Następnie dodaj wyrażenie then, które odtwarza efekt cząsteczkowy wiązki w lokalizacji zgodnej z ustawieniami lokalizacji źródłowej i docelowej.Jednostka
lightning_entitywykorzystuje ustawienie Konfiguracja emitera wiązki > Początek wiązki w celu odtworzenia zdarzenia błyskawicy w losowych punktach na niebie.LightningVFXComponentwykorzystuje następnie opcję cząsteczek wiązki Konfiguracja emitera wiązki > Koniec wiązki, aby określić, w którym miejscu w scenie pojawi się koniec wiązki. W tej opcji wybrane jest ustawienie Pozycja symulacji, które wykorzystuje koordynaty końcowe efektu cząsteczkowego jednostkilightning_entity.Następnie utwórz i zdefiniuj obrażenia zadawane przez zdarzenie
struck_by_lightning_event, wykorzystując dane źródłowe i docelowe, aby zlokalizować miejsce wystąpienia obrażeń na docelowym komponencie siatki za pomocą ustawieniaDamageRadius, które opisuje obszar, w jakim obrażenia od pioruna będą zadawane. To zdarzenie zostanie wysłane do jednostki symulacji, aby dodać losowy czas trwania błyskawicy, dlatego łańcuch zdarzeń zakończ zdarzeniemSimulationEntity.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
Krok 6: Definiowanie zdarzenia pożaru
Utwórz klasy zdarzeń, które będą definiować wartość obrażeń od ognia oraz to, czy ogień powinien się rozprzestrzeniać po scenie w oparciu o zadawane przez niego obrażenia.
Utwórz dwie klasy. Klasę
fire_damage_eventoraz klasęfire_propagation_event, która sprawdza wartośćDamageAmounti odtwarza efekt cząsteczkowy ognia, gdy wartość zmiennopozycyjnaDamageAmountosiągnie próg.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.0Utwórz klasę
flammable_component, która określa, czy siatka jest palna, oraz definiuje edytowalne właściwości, które można ustawić tak, by powodowały zajęcie się siatek w scenie ogniem.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.0Do zdarzenia
directional_eventnależy dodać zmienną warunkową, która decyduje o tym, czy efekt VFX pożaru jest lub powinien być odtwarzany.Verse# Is it on fire? var IsOnFire:logic = falseFunkcja
IsCloseEnoughToBurningEntityToIgniteokreśla, czy ogień jest wystarczająco blisko, aby wyzwolić kolejne zdarzenia VFX pożaru.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.FireRadiusCentimetersFunkcja
IsCloseEnoughToLightningToIgniteokreśla, czy piorun uderzył na tyle blisko, aby spowodować zajęcie się siatki płomieniem.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.DamageRadiusCentimetersFunkcja OnRecieve określa, które siatki zajmą się ogniem, gdy funkcja IsCloseEnoughToBurningEntityToIgnite ustali bliskość propagacji ognia, a zmienna IsCloseEnoughToLightningToIgnite określi odległość między miejscem uderzenia pioruna a siatką.
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() falseMetoda
Ignitesłuży do automatycznego odtwarzania efektu za pomocą instrukcji warunkowej if, która wyszukuje system cząsteczkowy ognia. Instrukcjathendefiniuje, czy to prawda, że komponent odtwarza efekt VFX pożaru.Dodaj do metody zadania asynchroniczne, aby sprawdzać dostępność systemu cząsteczkowego ognia Fire_NS, by po wywołaniu ogień był spawnowany i się rozprzestrzeniał.
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
Krok 7: Definiowanie końca zdarzenia pożaru
Następnie utworzysz szereg metod, które określają, kiedy komponenty siatki stają w płomieniach, kiedy płomienie wygasają, jakie obrażenia zadaje ogień oraz kiedy spowodować rozprzestrzenienie się ognia.
Najpierw utwórz metodę gaszenia
Extinguish, która zatrzymuje efekt pożaru, wyszukując komponenty odtwarzające efekt pożaru za pomocą instrukcji warunkowych, aby odszukać system cząsteczkowy ognia i usunąć efekt.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()Utwórz metodę
OnFire, która wykorzystuje pętlę odpowiedzialną za monitorowanieFireDamagei wysyła zdarzenie w dół łańcucha jednostek w kierunku jego końca, powodując zatrzymanie odtwarzania zdarzenia.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)Na koniec utwórz metodę
FirePropagation, która wykorzystuje blokloopdo uzyskania efektu rozprzestrzeniania się ognia w dół łańcucha jednostek i sprawia, że ogień wygasa po dotarciu do jednostki symulacji.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)
Gdy kod będzie gotowy, skompiluj go i dodaj odpowiednie jednostki do Scene Graph, aby umożliwić obsługę efektów uderzenia pioruna i pożaru lasu. Następnie dodaj flammable_component do jednostek w scenie, które powinny zająć się ogniem. Pod jednostką symulacji musi znajdować się jednostka najwyższego poziomu zawierająca komponent lightning_weather_component, który kontroluje pogodę.
Po zaktualizowaniu wszystkich jednostek przy użyciu odpowiednich zdarzeń sceny uruchom sesję edycji na żywo, aby zobaczyć, jak kod działa w scenie.
Rezultat
Skopiuj kod i wklej go do projektu, aby zobaczyć zdarzenie sceny w akcji.
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