Udostępnij za pośrednictwem


Mesh Visual Scripting best practices for networking (Najlepsze rozwiązania dotyczące tworzenia skryptów wizualnych usługi Mesh dla sieci)

Omówienie

W usłudze Mesh większość właściwości sceny jest domyślnie automatycznie współużytkowane przez wszystkich klientów połączonych z tym samym pomieszczeniem. Na przykład pozycja i obrót obiektu sceny, stan włączony składnika lub tekst TextMeshPro.

Zgodnie z zasadą kciuka właściwości składnika i zmienne obiektu, które mają następujące typy wartości, są domyślnie automatycznie udostępniane:

Typy kolekcji (listy i zestawy) i odwołania do obiektów sceny nie są udostępniane.

Węzły skryptu wizualnego, które uzyskują dostęp do właściwości lub modyfikują je w usłudze Mesh, są oznaczone etykietą wskazującą, czy są one "współużytkowane przez wszystkich klientów" lub "Lokalne dla tego klienta":

______________

Zmienne obiektu są domyślnie współużytkowane, a także jeśli zadeklarowane zostały z jednym z typów wartości wymienionych powyżej:

______________

Usługa Mesh nie obsługuje zmiennych sceny, ale można użyć autonomicznych składników Zmiennych w środowisku do stash zmiennych, które mogą być udostępniane niezależnie od dowolnego składnika maszyny skryptu .

Jeśli nie chcesz automatycznego udostępniania właściwości lub zmiennych obiektów, możesz dodać składnik Zakres skryptu lokalnego do sceny. Spowoduje to, że wszystkie właściwości sceny i zmienne skryptu na tym obiekcie gry i dowolny z jego obiektów potomnych są lokalne.

______________

Porada: Możesz zobaczyć kilka przykładów użycia składnika Zakres skryptu lokalnego w rozdziale 3 naszego samouczka mesh 101, który koncentruje się na skryptach wizualnych.

W przypadku zmiennych skryptu lokalnego, których używasz tylko na jednej maszynie skryptów, najlepiej użyć zmiennych programu Graph, które nigdy nie są współużytkowane przez klientów przez usługę Mesh.

Udostępnianie za pośrednictwem tworzenia skryptów wizualnych usługi Mesh daje następujące gwarancje:

  • Gwarantowana spójność ostateczna: wszyscy klienci w końcu dotrą do tego samego stanu udostępnionego.

  • Gwarantowana niepodzielność poszczególnych składników: wszystkie aktualizacje właściwości tego samego składnika sceny (lub tego samego składnika Zmiennych ) w tej samej aktualizacji zostaną zastosowane niepodziecznie na każdym kliencie.

Jednak:

  • Brak gwarancji kolejności: aktualizacje zastosowane przez jednego klienta do kilku różnych składników sceny mogą być dostarczane w różnych zamówieniach na różnych klientach.

  • Brak gwarancji osi czasu: siatka będzie starała się jak najlepiej replikować zmiany stanu na klientach tak szybko, jak to możliwe, ale warunki sieciowe mogą opóźnić nadejście każdej danej aktualizacji stanu na niektórych lub wszystkich klientach.

  • Brak gwarancji stopnia szczegółowości: każdy klient może nie widzieć wszystkich aktualizacji przyrostowych w stanie udostępnionym. Może się tak zdarzyć, gdy warunki sieciowe wymuszają aktualizację limitu szybkości serwera usługi Mesh. Dzieje się tak również, gdy klient późno dołącza do pokoju.

Stan jest współużytkowany — zdarzenia nie są udostępniane

Nie można wysyłać ani odbierać jawnych komunikatów sieciowych za pomocą skryptów wizualnych usługi Mesh. Może to być zaskakujące na początku, ale pomaga w ustanowieniu paradygmatu sieciowego, który ułatwia jednolite obsługę zmian w czasie wykonywania, a także późne sprzężenie. Zamiast komunikatów stan współużytkowany we właściwościach sceny i zmiennych skryptu.

Skrypty mogą reagować na udostępnione aktualizacje stanu w jednolity sposób niezależnie od tego, czy te aktualizacje były przez skrypt lokalny lub użytkownika, przez innego klienta, który udostępnia środowisko w tym samym pomieszczeniu, lub przez innych klientów, którzy byli już w pokoju, zanim jeszcze dołączyłeś do niego samodzielnie.

Nie można jawnie wysyłać komunikatów sieciowych oznacza, że musisz zacząć myśleć o stanie udostępnionym, który pobiera aktualizacje zamiast zdarzeń udostępnionych , które powodują aktualizacje stanu. Zdarzenia udostępnione są konsekwencją aktualizacji stanu współużytkowanego, a nie odwrotnego.

Na szczęście obsługa skryptów wizualnych usługi Mesh ułatwia działanie skryptów wizualnych na aktualizacje stanu. Użyj węzła Zdarzenia zmienionego stanem i połącz swoje dane wejściowe po lewej stronie z dowolną zmienną skryptu lub właściwością składnika, którą chcesz obserwować pod kątem zmian, a węzeł zdarzenia wyzwoli skrypt (połączony z prawą stroną) za każdym razem, gdy którakolwiek ze zmiennych lub właściwości połączonych z nią zmieni ich wartość.

______________

Działa to z stanem udostępnionym, a także ze stanem lokalnym. Zdarzenie On State Changed będzie wyzwalane niezależnie od tego, czy zmienne lub właściwości, które obserwuje, zostały zmienione przez klienta lokalnego, przez klienta zdalnego, a nawet przez klienta zdalnego, zanim klient lokalny nawet dołączył do pokoju.

Korzystanie ze stanu Włączone zmienione w celu reagowania na zmiany stanu jest wydajne: nie ma bezczynności przepustowości ani kosztów wydajności. W ten sposób można pasywnie nasłuchiwać aktualizacji stanu bez negatywnego wpływu na szybkość ramki lub wykorzystanie przepustowości środowiska.

Późne sprzężenie

Późne sprzężenie występuje, gdy klient dołącza do pokoju, który ma już innych klientów połączonych z nim.

Przy późnym sprzężeniu usługa Mesh otrzymuje bieżący stan pokoju z serwera — na przykład, który znajduje się już w pokoju i gdzie znajdują się ich awatary — i szybko przygotowuje lokalną wersję środowiska udostępnionego klienta, tak aby był zgodny ze stanem udostępnionym przez wszystkich w pokoju.

W dużej mierze tworzenie skryptów wizualnych usługi Mesh działa tak samo. Wszystkie współużytkowane właściwości składnika i zmienne skryptu wizualnego, które zostały zmienione w pomieszczeniu przed dołączeniem klienta, zostaną zaktualizowane lokalnie w celu dopasowania do stanu udostępnionego, a następnie wszystkie węzły zdarzeń w stanie Zmieniony stan obserwujące te właściwości lub zmienne są wyzwalane.

Opóźnieni sprzężeni nie odtwarzają udostępnionych zdarzeń — otrzymują stan udostępniania.

Z punktu widzenia klienta lokalnego środowisko zawsze ewoluuje z początkowego stanu, który miał tuż po załadowaniu sceny przekazanej do usługi Mesh. W przypadku późnego sprzężenia pierwsza zmiana stanu może być większa niż to, co się stanie, gdy użytkownik lokalny wchodzi w interakcję z pokojem w bieżącej sesji, ale jest to dokładnie to samo w zasadzie.

Wszystko to dzieje się, gdy środowisko ładuje się, zanim nawet zniknie z czarnego. Gdy tylko użytkownik może zobaczyć środowisko i wchodzić z nim w interakcje, późne sprzężenie jest już gotowe.

Ustaw stan lokalny na stan udostępniony

Bardzo często "stan udostępniony", który użytkownik może obserwować w środowisku, jest w rzeczywistości kombinacją stanu współużytkowanego bezpośrednio przez usługę Mesh i stan lokalny, który został ustanowiony przez skrypty wizualne w odpowiedzi na zdarzenie, które miało miejsce w pomieszczeniu. Na przykład gdy użytkownik przerzuca przełącznik w środowisku (stan udostępniony), skrypt wizualny może zmienić kolor skybox (stan lokalny). Możesz zastosować zmianę lokalną (zaktualizować kolor skybox) bezpośrednio w odpowiedzi na interakcję użytkownika z przełącznikiem. Jednak nawet jeśli zdarzenie interakcji występuje na wszystkich klientach obecnie w pokoju, każdy klient, który dołącza do pokoju później, nie otrzyma tego zdarzenia po prostu dlatego, że nie było tam, gdy tak się stało. Zamiast tego należy ustawić , aby stan lokalny był zgodny ze stanem udostępnionym w następujący sposób:

  1. Gdy użytkownik wchodzi w interakcję (na przykład przerzuca przełącznik), włącz to zdarzenie lokalne , które aktualizuje zmienną udostępnioną (na przykład stan włączania/wyłączania przełącznika).
  2. Użyj opcji W stanie Zmieniono , aby obserwować zmienną udostępnioną.
  3. Po wyzwoleniu zdarzenia On State Changed (ponieważ zmienna udostępniona zmieniła jej wartość), zastosuj dowolną zmianę lokalną (na przykład zaktualizuj kolor skrzynki skybox).

W ten sposób stan lokalny (kolor skrzynki skybox) jest następujący po stanie udostępnionym (stan przełącznika). Co jest miłe w tym przypadku, że działa bez zmian dla klienta lokalnego, który przewrócił przełącznik, dla wszystkich innych klientów zdalnych, którzy znajdują się w pokoju w tym samym czasie, i dla wszystkich przyszłych klientów, którzy dołączą do pokoju później.

Ustaw stan lokalny na stan udostępniony: Najlepsze rozwiązania

Zdarzenia lokalne: na przykład węzeł zdarzenia Zmiany stanu obserwujący właściwość Is Selected Locally składnika Treść z możliwością interakcji z siatką:

  • 🆗 Może zmienić stan lokalny, który jest prywatny dla klienta. Te zmiany stanu pozostaną ściśle na kliencie lokalnym i znikną, gdy klient opuści sesję.
  • 🆗 Może zmienić stan udostępniony.
  • Nie można zmienić stanu lokalnego tak, aby był spójny między klientami. Lokalne zdarzenie jest wykonywane tylko na jednym kliencie, więc aktualizacje niezbędne do zapewnienia spójności stanu lokalnego na klientach po prostu nie będą wykonywane na żadnym innym kliencie.

Zdarzenia udostępnione: na przykład węzeł zdarzenia Wyzwól wprowadź dołączony do współużytkowanego zderzacza wyzwalacza fizyki:

  • 🆗 Może zmienić stan lokalny na chwilowe skutki: na przykład efekt cząstek lub krótki efekt dźwiękowy. Tylko klienci znajdujący się w pokoju, gdy wystąpi zdarzenie udostępnione, będą mogli zobaczyć efekt lokalny; wszyscy klienci, którzy dołączają do pokoju później, nie będą.
  • Nie można zmienić stanu lokalnego tak, aby był spójny między klientami. Zdarzenie udostępnione jest wykonywane tylko na klientach, którzy są obecni w czasie jego wystąpienia, ale nie będzie odtwarzane dla klientów, którzy dołączają do sesji później.
  • Nie może zmieniać stanu współużytkowanego. Ponieważ zdarzenie udostępnione jest wykonywane na wszystkich klientach, wszystko, co robi, jest wykonywane przez wszystkich klientów bardzo blisko w czasie. W zależności od charakteru zmiany może się powtarzać kilka razy (na przykład licznik wyników może być zwiększany o więcej niż jeden w odpowiedzi na pojedyncze zdarzenie).

W obszarze Stan zmienione zdarzenia, które obserwują stan współużytkowany we współużytkowanych zmiennych lub właściwościach składników udostępnionych:

  • 🆗 Może zmienić stan lokalny tak, aby był spójny ze stanem udostępnionym między klientami. Aby to działało dobrze w powtarzalny i spójny sposób dla wszystkich klientów, należy przetłumaczyć każdą możliwą nową wartość obserwowanego stanu udostępnionego na stan lokalny, a nie tylko kilka przejścia stanu wybranego wiśniowo (na przykład Czy wybrano staje się prawdziwe).

Ustaw stan lokalny na stan udostępniony: przykład

W tym przykładzie w tym środowisku istnieją dwa przyciski interaktywne: jeden oznaczony etykietą "Star", drugi z etykietą "Sponge". Wybranie jednego z przycisków ma wykonać dwie czynności:

  • Zapisz odpowiednią etykietę w zmiennej ciągu udostępnionej o nazwie ObjectKind.
  • Zapisz odwołanie do odpowiedniego obiektu sceny w lokalnej zmiennej referencyjnej GameObject o nazwie ObjectRef.

Poniżej przedstawiono dwa przepływy skryptów— jeden dla każdego przycisku. Każda z nich nasłuchuje udostępnionej właściwości Is Selected jednego przycisku składnika Mesh Interactable Body i aktualizuje objectKind i ObjectRef w zależności od wybranego przycisku:

______________

Wszystko wydaje się działać dobrze, ale tylko dla użytkowników, którzy są już w pokoju, gdy wybrano jeden z przycisków. Każdy użytkownik, który dołącza do sesji później, znajdzie niespójny stan w lokalnej wersji środowiska udostępnionego: Tylko ObjectKind jest poprawnie ustawiony zgodnie z ostatnio wybranym przyciskiem, ale ObjectRef pozostaje null.

Co jest nie tak z tymi dwoma przepływami skryptów?

Najpierw zwróć uwagę, że te przepływy skryptów są wyzwalane przez zdarzenie udostępnione, ponieważ oba te przepływy nasłuchują współużytkowanej właściwości Is Selected . Wydaje się to mieć sens, ponieważ jest to jedyny sposób na zaktualizowanie lokalnej zmiennej ObjectRef na wszystkich klientach.

Jednak:

  • Zdarzenia udostępnione nie mogą zmieniać stanu udostępnionego, ale te przepływy skryptu aktualizują udostępnioną zmienną ObjectKind .
  • Zdarzenia udostępnione nie mogą zmieniać stanu lokalnego tak, aby były spójne na klientach , ale te przepływy skryptu aktualizują lokalną zmienną ObjectRef , którą zamierzamy być spójni na wszystkich klientach, podobnie jak ObjectKind.

Więc sposób, w jaki jest obecnie skonfigurowany, w rzeczywistości nie powinniśmy robić żadnej z rzeczy, które potrzebujemy przycisków do zrobienia.

Jedynym oczywistym sposobem wyjścia z tego problemu jest uczynienie zdarzeń wyzwalających te przepływy lokalnie. Możemy to zrobić, wykonując polecenie W węźle Zdarzenia zmienionego stanu zaobserwuj właściwość Is Selected Locally zamiast Is Selected (Czy wybrano lokalnie zamiast jest zaznaczona).

Gdy zdarzenie jest teraz lokalne, oznacza to...

  • Zdarzenia lokalne mogą zmieniać stan udostępniony, dzięki czemu możemy teraz bezpiecznie zaktualizować udostępnioną zmienną ObjectKind , a jej wartość będzie automatycznie współdzielona między klientami przez wbudowaną sieć usługi Mesh Visual Scripting.
  • Zdarzenia lokalne nie mogą zmieniać stanu lokalnego tak, aby były spójne między klientami , więc nadal nie można zaktualizować lokalnej zmiennej ObjectRef w tych przepływach skryptu. Będziemy musieli znaleźć inny sposób.

W ten sposób dwa przepływy skryptu będą wyglądać po tych zmianach:

______________

Co możemy zrobić, aby ustawić lokalną zmienną ObjectRef , aby zachować spójność z tą wartością? Na szczęście te dwa przepływy skryptów już ustanowią udostępniony stan, który możemy obserwować: udostępnioną zmienną ObjectKind . Wystarczy użyć zdarzenia On State Changed , które obserwuje tę zmienną i aktualizuje lokalną zmienną ObjectRef w zależności od jej wartości:

______________

Jest to dobry sposób, aby to zrobić, ponieważ zdarzenia w stanie zmienionym stanu, które obserwują stan udostępniony, mogą zmienić stan lokalny na spójny z nim. Będzie to działać dla klienta, który nacisnął przycisk, dla wszystkich innych klientów znajdujących się w tym samym pomieszczeniu w tym samym czasie i dla wszystkich klientów, którzy dołączą do sesji później.

Pułapki dotyczące sieci

Aktualizacje udostępnione o wysokiej częstotliwości

Prawie cały stan sceny jest domyślnie współużytkowany przez skrypty wizualne usługi Mesh. Jest to doskonałe rozwiązanie do udostępniania, ale może również wkraść się przypadkowo i spowodować niepotrzebne obciążenie sieci. Na przykład poniższy przepływ skryptu spowoduje zalanie sieci nadmiarowymi aktualizacjami do rotacji przekształcenia. Jednak ponieważ wszyscy klienci wykonują go w tym samym czasie, żadna z aktualizacji zdalnych nigdy nie będzie miała rzeczywistego wpływu na dowolnego klienta lokalnie:

______________

W takim przypadku prawdopodobnie należy użyć zakresu skryptu lokalnego, aby składnik Transform był lokalny dla każdego klienta. Ponadto prawdopodobnie należy użyć składnika Animator , a nie przepływu skryptu on Update , aby rozpocząć od.

Panel Diagnostyka skryptów wizualnych usługi Mesh i Analizator wydajności zawartości (CPA) w zestawie narzędzi Mesh Toolkit 5.2411 wyświetla ostrzeżenie "Aktualizacja udostępniona o wysokiej częstotliwości" dla tego rodzaju konstrukcji.

Po uruchomieniu na każdym kliencie

Możesz być kuszony, aby myśleć o zdarzeniu On Start jako coś, co jest uruchamiane podczas uruchamiania sesji, ale jest on rzeczywiście wyzwalany na każdym kliencie, lokalnie, po dołączeniu do sesji. Doskonale nadaje się do inicjowania stanu lokalnego:

______________

Jednak podczas próby użycia opcji Przy uruchamianiu w celu zainicjowania stanu udostępnionego okaże się, że stan udostępniony zostanie przypadkowo zainicjowany ponownie dla wszystkich, gdy ktoś dołączy do sesji:

______________

Panel Diagnostyka skryptów wizualnych usługi Mesh (od zestawu narzędzi Mesh Toolkit 5.2410) i content Analizator wydajności (CPA) (od zestawu narzędzi Mesh Toolkit 5.2411) wyświetla ostrzeżenie "Udostępniona aktualizacja dołączania do sesji" po wykryciu tego.

Udostępnianie jest wpisywane — ale przypisanie zmiennej nie jest

Ze względów bezpieczeństwa i bezpieczeństwa zmienne udostępnionego skryptu wizualnego są silnie typizowane. Oznacza to, że typ wybrany w składniku Zmienne dla zadeklarowanych zmiennych skryptu definiuje dokładny typ wartości, który zostanie zsynchronizowany między klientami.

Niestety, skrypty wizualne aparatu Unity całkowicie ignorują zadeklarowany typ zmiennej podczas aktualizowania jej wartości. Na przykład łatwo jest przypadkowo przechowywać wartość typu Float w zmiennej, która została zadeklarowana dla typu Liczba całkowita. W kliencie lokalnym skrypty wizualne nie zauważą tego błędu, ponieważ skrypty wizualne automatycznie przekonwertują błędny zmiennoprzecinkowy do oczekiwanej liczby całkowitej w razie potrzeby. Jednak jeśli chodzi o synchronizację tej wartości między klientami, tworzenie skryptów wizualnych usługi Mesh nie może przyjąć tych samych swobód: gwarancja "spójności ostatecznej" uniemożliwia dowolną konwersję wartości w locie, a zagadnienia dotyczące bezpieczeństwa i zabezpieczeń sprawiają, że nie można zaakceptować innego typu wartości od klienta zdalnego niż to, co zostało zadeklarowane dla zmiennej.

Rozważmy na przykład tę deklarację zmiennej udostępnionej o nazwie MyIntegerVar:

______________

Oto przepływ skryptu, który aktualizuje tę zmienną:

______________

Co może pójść nie tak? Niestety, węzeł skryptu zakresu losowego | używany w tym przykładzie ma dwie odmiany: jeden, który generuje losową wartość całkowitą, i jeden, który generuje losową wartość zmiennoprzecinkową. Różnica między tymi dwoma węzłami skryptu w panelu selektora węzłów jest subtelna:

______________

Jeśli więc przypadkowo wybierzesz w nim niewłaściwy węzeł skryptu zakresu losowego | , skrypt może przypadkowo przechowywać wartość zmienną typu Liczba całkowita, ale błędna wartość zmienna zmiennoprzecinkowa nie zostanie zreplikowana do innych klientów.

Należy pamiętać, że jest to potencjalny powód, dla którego utworzona zmienna udostępniona może wydawać się przestać być współużytkowana. Przyszłe wersje skryptów wizualnych usługi Mesh mogą ostrzegać o błędzie skryptu tego rodzaju, gdy mogą go wykryć.

Następne kroki