Autor Wątek: Multiplayer w Unity  (Przeczytany 4548 razy)

Offline MateuszS

  • Użytkownik

# Maj 23, 2014, 00:26:09
Witam.
Przeglądnąłem trochę forum jednak tak gdzieś w okolicy 4 strony postanowiłem jednak napisać temat. Jestem studentem informatyki, chciałbym jako pracę inżynierską zrobić coś w Unity (takie wstępne założenie). Chodzi o jakąś prostą grę, czy też prezentację silnika ale Multiplayer (klient-serwer). Mam kilka pytań:
1. Wiem że istnieje moduł Network w Unity, za pomocą którego można napisać taką aplikację. Ale to chyba sprawdzi się tylko dla klienta? No bo załóżmy że sobie serwer zechcę postawić na jakimś dedyku. Serwer nie potrzebuje znać mapy, renderować ją itd. On tylko przekazuje pakiety między klientami. I tu jest pytanie - czy jako serwera mogę użyć już dowolnej biblioteki, choćby Qt do C++ w celu wyłapywania tych pakietów lecących od klienta?
2. Czy po tym kursie, da się coś sensownego już napisać? Dogłębnie go analizowałem ostatni tydzień ale nie wiem czy gość nie pominął jakiegoś bardzo istotnego mechanizmu, który mi ułatwi pracę? Na pewno nie wspomniał niz o Network.
http://www.unity3dstudent.com/category/modules/

Offline Mr. Spam

  • Miłośnik przetworów mięsnych

Offline Rethil

  • Użytkownik

# Maj 23, 2014, 12:26:43
@1 Krótka odpowiedź: tak- dowolny program da rade.
Długa odpowiedź: musisz obsłużyć komunikację sieciową. W takim przypadku po stronie klienta najlepiej użyć socketów. Pisałem o tym również w innych watkach - są gotowe darmowe (dopóki to się nie rozrośnie poza określoną liczbę CCU, a tobie to nie grozi przy inżynierce) rozwiązania do tego np. Photon Server lub SmartFox Server. Z tego drugiego nie korzystałem dlatego najczęściej polecam Photona. Jeśli to ma być tylko przekazywanie pakietów pomiędzy klientami możesz również zerknąć na rozwiązanie w chmurze Photon Unity Networking. Nie wiem czy będzie akurat pasowało do twojej pracy inżynierskiej, ale w praktyce działa lepiej niż samodzielne pisanie aplikacji serwera, szczególnie jeśli nie masz o tym pojęcia:P

@2 Nie przepadam za kursami z tej strony. Są jakieś dziwne:P Na początek na pewno są lepsze niż nic, ale nie przykładaj do nich za dużej wagi. A szczególnie nie przykładaj wagi do wywoływania funkcji przez SendMessage. Oczywiście, jak wszystko, rozeznanie w Unity przychodzi z czasem.

A tak na marginesie Networking w Unity działa słabo i jest to co najmniej pokraczne rozwiązanie. W nowej wersji już zapowiedzieli zmiany, no ale obecnie lepiej jest korzystać z zewnętrzny pluginow niż z tego co jest wbudowane.

Offline MateuszS

  • Użytkownik

# Maj 23, 2014, 14:13:07
Napisałem kilka w życiu aplikacji klient-serwer, myślę dałbym radę coś takiego napisać (wiadomo jest to trochę większa skala). Czyli zamiast Network, użyć po prostu wbudowanej w C# klasy socketów a po stronie serwera, któryś z podanych przez Ciebie systemów (ew. swój)?

Dzięki za uwagi dot. kursu. Czy w takim razie polecasz jakiś od siebie, który nie promuje jakiś antywzorców itd. ? Znalazłem też książkę http://helion.pl/ksiazki/projektowanie-gier-w-srodowisku-unity-3-x-will-goldstone,prgun3.htm ale jakoś mnie nie przekonują książki od nich.

Offline Rethil

  • Użytkownik

# Maj 23, 2014, 15:18:35
@Aplikacje serwer klient - nie do końca. Rozwiązania które podałem są kompleksowe posiadają swoje wtyczki do Unity i obsługują całą komunikację same, ty zajmujesz się tylko logiką. Socketów używasz wtedy kiedy sam chcesz napisać własną komunikację serwer klient i piszesz własną aplikacje serwera.

@Kursy - sprawa jest ciężka, bo ja preferuję naukę "trzaskaj kod aż się nauczysz". Oczywiście przebrnąłem przez kilka kursów (najlepsze były jakieś video tutki, chyba Tornado Twins, ale nie pamiętam bo było to dawno,  jeszcze na Unity 3) i książek, ale wszystkie są imo słabe. Książki zanim wychodzą są przeterminowane nie mówiąc o polskich tłumaczeniach. Generalnie Unity jest prostym silnikiem i należy gry na nim oparte traktować jak każdą aplikacje .NET tylko bez wielowątkowości i opartą na starym Mono. Ma specyficzne ramy, o których dobrze wiedzieć (MonoBehaviours i serializacja) i zapoznać się z wzorcami projektowymi przeznaczonymi (a raczej dostosowanymi) dla Unity. Możesz zerknąć na http://unitypatterns.com/ przy czym większość problemów z jakimi się spotkasz będziesz musiał rozwiązać sam i żaden kurs ci w tym nie pomoże i raczej cię do tego nie przygotuje.

//Edit: Zapomniałem o jednym- Unity Techonologies robi teraz własna serie video tutoriali. Są one kręcone na żywo z udziałem publiki (mozesz uczestniczyć sam w takim treningu) a dla tych co przegapia termin (oraz dla celów archiwalnych) są dostępne na YT.
« Ostatnia zmiana: Maj 23, 2014, 15:24:00 wysłana przez Rethil »

Offline MateuszS

  • Użytkownik

# Maj 23, 2014, 17:46:25
Dzięki za wyczerpującą odpowiedź. To co mnie "uderzyło" w Unity na początku to to że skrypty (kod) dodajemy jakby dla poszczególnych obiektów i zastanawiałem się to gdzie w takim razie są jakieś klasy ogólne, kontrolery, np. multiplayera, statystyk. Chyba zastosuję się do Twoich rad i po prostu będę próbował coś wyklepać.

PS. Btw, wiesz jak zrobić żeby nałożyć na cube inną teksturę z każdej strony? Wyczytałem w necie że trzeba osobne Meshe zrobić ale nie mogę znaleźć żadnego video tutka na ten temat.
« Ostatnia zmiana: Maj 23, 2014, 21:29:59 wysłana przez MateuszS »

Offline Rethil

  • Użytkownik

# Maj 23, 2014, 21:50:28
Meshe robisz i teksturujesz np. w Blenderze, a potem importujesz do Unity jako fbx. Natomiast osobna tekstura na każdą ściankę? Najlepiej jakbyś połączył tekstury na każdą ściankę w atlas i zmapował UV'ki odpowiednio. To niestety nie wypali jeśli masz dynamiczne tekstury np. pobierasz zdjęcia znajomych z FB i chcesz je nałożyć na kostkę. Wtedy albo modyfikujesz teksturę wejściową, albo tworzysz materiał wczytujący różne tekstury i w zależności od UV samplujesz inne tekstury wejściowe. Oba rozwiązania upierdliwe:P Największym overkillem ale i najłatwiejszym sposobem jest nałożenie kilku materiałów na kostkę i każdemu z nich danie jednej tekstury.

Offline MateuszS

  • Użytkownik

# Maj 23, 2014, 23:22:13
Skomplikowane ale rozwiązałem to nakładając Plane'y na każdą ściankę.

Offline MateuszS

  • Użytkownik

# Maj 25, 2014, 19:54:43
Mam takie proste pytanie:

Mam kod odpowiadający za dystans gracza od włącznika światła

if(Vector3.Distance(GameObject.Find("Player").position, transform.position) <= dist) {
//costam
}

A co w przypadku gdy graczy będzie kilku i będą się pojawiać w trakcie gry? To działa poprawnie chyba tylko dla jednego gracza.
« Ostatnia zmiana: Maj 25, 2014, 21:45:30 wysłana przez MateuszS »

Offline Rokuzo

  • Użytkownik
    • Masz na sprzedaż klucze do cs go?

# Maj 26, 2014, 09:17:37
Spróbuj z dwoma albo trzema graczami to się przekonasz :)
W necie można znaleźć wiele dobrych tutoriali do Unity3D.

Offline Rethil

  • Użytkownik

# Maj 26, 2014, 10:39:22
To jest kolejny problem z możliwościami Unity. To że możesz wyszukiwać obiekty po nazwie nie znaczy że powinieneś to robić. Jeśli chcesz żeby to działało tylko dla gracza lokalnego to podczas tworzenia obiektu gracza lokalnego na scenie zapisz refkę do niego, a później się odwołuj do niej. Jeśli ma to działać dla wszystkich graczy, to przy tworzeniu obiektu dla każdego z nich uzupełniaj listę graczy i później sprawdzając dystans iteruj po niej.

P.S. Samo wyszukiwanie obiektu po nazwie jest bardzo czasochłonne, dlatego nie należy tego wywoływać co chwilę. Jeśli obiekt jest stały (czyli nie niszczysz go i nie tworzysz nowego o tej samej nazwie) lub zmienia się rzadko (np. w określonej sytuacji takiej jak śmierć gracza) to lepiej albo podczas tworzenia przypisać ten obiekt do zmiennej i z tego korzystać, albo jeśli koniecznie musisz korzystać z wyszukiwania (choć osobiście nie znam przykładu takiej sytuacji, oprócz złego designu) to wynik tego wyszukiwania wstaw do zmiennej. W skrócie- korzystaj jak najrzadziej.

P.P.S Najczęściej w przypadkach kiedy wyszukujesz coś na scenie to i tak interesują cię obiekty z konkretnymi komponentami (np. nie każdy Player, a tylko taki który ma podpięty skrypt LocalPlayer). Wtedy lepiej jest korzystać z funkcji FindObjectOfType lub z wersji agregującej wszystkie takie obiekty w tablicę FindObjectsOfType. Zasada taka sama jak z poprzednia funkcją - korzystaj jak najrzadziej.

Offline MateuszS

  • Użytkownik

# Maj 26, 2014, 18:13:59
1. Dzięki. Ale w takim razie przy tworzeniu playera muszę dodać go do jakiejś tablicy z której muszą móc korzystać różne obiekty. Muszę mieć do niej dostęp. Wiem że mogę użyć SendMessage żeby wywołać jakiegoś gettera tej tablicy ale ponoć nie wolno tej f używać. Ten problem jest ogólniejszy bo też chcemy mieć pewne klasy, które nie dotyczą żadnych obiektów na scenie (np klasa do obsługi multika, jakiś danych) a jeżeli nie przeciągniemy skryptu do jakiegoś obiektu to on się nie wykona

2. Drugie pytanie. Mam zrobiony przycisk włączania światła. Niestety nie mogę go oteksturować z jednej strony więc musiałem otoczyć go (Cube'a) Plane'ami i nałożyć na niego teksturę. Mam taką hierarchię

Switch (empty object) - rodzic
--Cube (przycisk)
--Plane (6 plane'ów z każdej strony Cube'a)

Ale jest problem, ponieważ gdy dodam skrypt do Switcha to niestety nie działa. Muszę dodać skrypt do Pane'a żeby działał. No ale przecież Switch jest rodzicem więc powinno działać dla wszystkich rodziców. Ale tak nie jest ;/
« Ostatnia zmiana: Maj 26, 2014, 19:05:13 wysłana przez MateuszS »

Offline Rethil

  • Użytkownik

  • +1
# Maj 26, 2014, 22:50:11
@1 Jeśli chcecie mieć klasy stricte pod dane to możecie albo zrobić jeden skrypt zbiorczy, który będzie trzymał refki do obiektów klas z danymi (vide: Singleton na MonoBehaviour), albo każda z tych klas może być być singletonem. Ja najczęściej robię tak, że tworze sobie obiekt na pierwszej scenie i podpinam tam wszystkie skrypty, które są "ogólne", czyli nie maja reprezentacji graficznej. Oczywiście są lepsze metody do tworzenia takich obiektów, ale to trochę bardziej skomplikowane bo czasem pojawiają się problemy z serializacją lub traci się możliwość zmiany pewnych parametrów z poziomu edytora (rzeczy które cię nie interesują na tym etapie nauki silnika:P). Jak potrzebujecie się odwołać do takiego obiektu to wystawcie sobie refkę do niego jako statyczną właściwość (publiczny getter, prywatny setter) i ustawiajcie ją w Awake(). Do tego dorzucacie DontDestroyOnLoad i sprawa załatwiona:)

@2 Problem nosi znamiona błędu typu "oj, namieszałeś stary":P Najpewniej nie da się go rozwiązać i bez przeglądnięcia twojego projektu lub samozaparcia w zrozumieniu tego co napisałeś. Czasami takie błędy wynikają z tego, że coś źle ustawiłeś albo założyłeś że coś działa inaczej niż w rzeczywistości. Przejrzyj dokumentacje jeszcze raz, posprawdzaj colidery, transformaty.

Offline MateuszS

  • Użytkownik

# Maj 27, 2014, 01:58:52
Taka scenka. Nie wiem czy skrypty załącza (w załączniku). Bede wdzieczny jesli rzucisz okiem