Jak naprawić Player Location Desync w UEFN i Unreal Engine Multiplayer
Koszmar Multiplayer Transform Desync
Każdy deweloper gier multiplayer prędzej czy później staje przed momentem, w którym jego netcode zaczyna kłamać. Tworzysz skrypt, w którym gracz siada na krześle, krzesło porusza się po mapie i na serwerze wszystko wygląda idealnie. Jednak po uruchomieniu drugiego klienta iluzja pryska. Klient A widzi siebie idealnie na krześle. Klient B widzi poruszające się krzesło, podczas gdy Klient A unosi się zamrożony w powietrzu w punkcie startowym.
To zjawisko — uefn player location desync — to dobrze udokumentowany problem występujący przy używaniu player inputs do wyzwalania komend MoveTo na propach z podpiętymi (attached) graczami. Serwer rejestruje poprawną lokalizację absolutną, ale simulated proxies (reprezentacje gracza na innych klientach) nie dziedziczą zaktualizowanego transformu od swojego rodzica.
Niezależnie od tego, czy tworzysz w Unreal Editor for Fortnite (UEFN), czy projektujesz samodzielny dedicated server w Unreal Engine 5, zrozumienie, dlaczego replication attachmentów zawodzi, jest kluczowe. W tym tutorialu przeanalizujemy mechanikę Network Dormancy, powody, dla których attachmenty psują client-side prediction, oraz sposoby na wymuszenie poprawnego stanu świata w replication graph.
Dlaczego Attachmenty psują Network Updates
Aby naprawić desync, musisz zrozumieć, jak Unreal Engine hierarchicznie obsługuje actor replication.
Kiedy character actor przypina się do propa, jego transform staje się relatywny względem rodzica. Aby oszczędzać pasmo, Unreal Engine agresywnie korzysta z koncepcji Network Dormancy.
Gdy gracz siedzi i przestaje generować movement input, serwer może oznaczyć aktora gracza jako dormant (uśpiony). Serwer zakłada: "Gracz nie porusza się samodzielnie, więc nie muszę wysyłać dla niego aktualizacji. Wyślę tylko aktualizacje dla poruszającego się krzesła".
Matematyka stojąca za Desync
- Server Tick Rate: Zazwyczaj 30Hz w UEFN.
- Prop NetUpdateFrequency: Często domyślnie 100 aktualizacji na sekundę.
- Character MinNetUpdateFrequency: Może spaść do 2.0 przy braku inputu.
Przy MoveTo krzesło aktualizuje się z częstotliwością 30Hz. Ponieważ jednak gracz jest dormant, inni klienci nigdy nie otrzymują RPC (Remote Procedure Call) nakazującego aktualizację relatywnej pozycji gracza. Wynik? Potężny desync wizualny.
Krok 1: Obejście w UEFN Verse
Zejście z krzesła naprawia problem, ponieważ zmiana movement mode z Custom na Walking wymusza na serwerze wyczyszczenie (flush) Network Dormancy.
Możemy odtworzyć ten „flush” programowo w Verse za pomocą mikro-teleportacji, aby obudzić replication graph.
# [Kod Verse jak w oryginale]
Wywołując TeleportTo na te same współrzędne, oszukujemy silnik C++, by aktywował flagę TeleportPhysics, co całkowicie resetuje client-side prediction dla tego aktora.
Krok 2: Natywna poprawka w Unreal Engine C++
Jeśli masz dostęp do kodu źródłowego, możesz bezpośrednio użyć API networkingowego do zarządzania dormancy.
// Przykład C++
// [Kod C++ jak w oryginale]
Krok 3: Persystencja stanu w Backendzie
Naprawa desyncu to połowa sukcesu. Jeśli Twoja gra ma trwały świat, musisz zapisać poprawne współrzędne server-authoritative. Budowa własnego backendu zajmuje tygodnie. horizOn oferuje Backend-as-a-Service stworzony dla deweloperów gier.
5 Dobrych Praktyk
- Nigdy nie ufaj stanowi attachmentu klienta: Używaj RPC server-authoritative.
- Zarządzaj NetDormancy ręcznie: Wywołuj
FlushNetDormancypodczas ruchu. - Płytkie hierarchie: Unikaj wielopoziomowych attachmentów.
- RPC dla krytycznych zmian: Używaj NetMulticast przy wsiadaniu/wysiadaniu.
- Waliduj transformy przy wysiadaniu: Sprawdzaj pozycję na serwerze po opuszczeniu propa.
Podsumowanie
Desyncki w multiplayerze to często efekt agresywnej optymalizacji. Rozumiejąc Network Dormancy, możesz wymusić aktualizacje przez Verse lub C++. Przejmij kontrolę nad replication graph.
Chcesz skalować swój backend? Wypróbuj horizOn za darmo.