Differences

This shows you the differences between two versions of the page.

Link to this comparison view

pjv:laboratoare:08 [2019/02/01 17:45]
alexandru.gradinaru
pjv:laboratoare:08 [2020/01/15 16:51] (current)
alexandru.gradinaru
Line 1: Line 1:
-===== Multiplayer =====+====== Multiplayer ​(bonus) ======
  
 Exista mai multe metode de a face un joc controlabil de mai multi jucatori in acelasi timp: Exista mai multe metode de a face un joc controlabil de mai multi jucatori in acelasi timp:
Line 5: Line 5:
   * Network: jucatorii joaca pe dispozitive diferite, existand un server sau unul din juctori preluand si rolul de server (host) iar restul fiind clienti   * Network: jucatorii joaca pe dispozitive diferite, existand un server sau unul din juctori preluand si rolul de server (host) iar restul fiind clienti
  
-==== Non-network ==== +===== Non-network ​===== 
-..+<​hidden>​https://​answers.unity.com/​questions/​1293382/​instance-a-scene-twice-two-worlds-two-cameras-etc.html</​hidden>​ 
 +Pentru jocuri locale de multiplayer se foloseste in general o tehnica de split-screen:​ folosirea mai multor camere care se afiseaza impart viewport-ul intantei locale a jocului [[https://​docs.unity3d.com/​ScriptReference/​Camera-rect.html]].  
 + 
 +{{ :​pjv:​laboratoare:​inspectorcamera35.png?​200 |}} 
 + 
 +Astfel, pentru un split-screen vertical se pot folosi doua camere cu valorile urmatoare pentru ViewPort Rect (x, y, width, height) 
 + 
 +<​code>​ 
 +Camera 1 : (0, 0, 0.5, 1) ► left 
 +Camera 2 : (0.5, 0, 0.5, 1) ► right 
 +</​code>​ 
 +{{ :​pjv:​laboratoare:​camera_horizontal_splitscreen.png?​600 |}} 
 +iar pentru pentru un split-screen orizontal 
 +<​code>​ 
 +Camera 1 : (0, 0.5, 1, 0.5) ► top 
 +Camera 2: (0, 0, 1, 0.5) ► bottom 
 +</​code>​ 
 +{{ :​pjv:​laboratoare:​camera_vertical_splitscreen.png?​600 |}} 
 + 
 +Controlul jucatorilor va trebui sa se codeze separat prin definirea de axe sau taste specifice fiecarui jucator. 
 + 
 +Daca se doreste implementarea unui GUI personalizat/​diferit pentru fiecare jucator, se pot folosi masti de camera ([[https://​docs.unity3d.com/​ScriptReference/​Camera-cullingMask.html|culling masks]]). 
 +Se vor plasa toate obiecte Jucatorului 1 intr-un layer separat (de ex Player1Layer),​ si obiectele jucatorului 2 in alt layer (Player2Layer) si se va asigura ca pentru fiecare camera sunt selectate layer-urile corecte (se vor exclude pentru camera 1 layer-ul cu Player2, si pentru camera 2 layer-ul cu Player 1). 
 + 
 +{{ :​pjv:​laboratoare:​layer-cullingmask.png?​200 |}} 
  
  
-==== Network ====+===== Network ​=====
  
 Exista mai multe moduri de a programa un joc in retea. In general se foloseste un server separat programat special, la care se conecteaza clientii sub diverse forme. In functie de necesitati, se folosesc diverse metode de implementare a comunicarii,​ persistentei si a spatiului: Exista mai multe moduri de a programa un joc in retea. In general se foloseste un server separat programat special, la care se conecteaza clientii sub diverse forme. In functie de necesitati, se folosesc diverse metode de implementare a comunicarii,​ persistentei si a spatiului:
Line 30: Line 55:
   * [[https://​www.smartfoxserver.com|SmartFoxServer]]   * [[https://​www.smartfoxserver.com|SmartFoxServer]]
   * [[https://​improbable.io/​games/​spatialos-gdk-unity|SpatialOS]]   * [[https://​improbable.io/​games/​spatialos-gdk-unity|SpatialOS]]
 +  * [[https://​darkriftnetworking.com/​DarkRift2|DarkRift]]
   * si altele ..   * si altele ..
  
-=== Unity HLAPI Networking ===+==== Unity HLAPI Networking ​====
  
 Pentru a folosi functionalitatea implicita oferita de Unity in materie de networking, va trebui in primul rand sa initializat un script ''​Network Manager'',​ care se gaseste ca si componenta in meniu. Pentru a folosi functionalitatea implicita oferita de Unity in materie de networking, va trebui in primul rand sa initializat un script ''​Network Manager'',​ care se gaseste ca si componenta in meniu.
Line 41: Line 67:
   * adresa si portul serverului   * adresa si portul serverului
   * referinta la Player - PlayerPrefab - aceasta referinta este de preferat sa nu fie deja in scena, intrucat se poate face spawn automat in anumite puncte, deci poate fi un prefab din library   * referinta la Player - PlayerPrefab - aceasta referinta este de preferat sa nu fie deja in scena, intrucat se poate face spawn automat in anumite puncte, deci poate fi un prefab din library
 +
 +<note important>​Optiunea de Run in background, folosita pentru a putea rula mai multe instante pe aceeasi masina, poate creea probleme pe dispozitive mobile!</​note>​
  
 Pentru a adauga o referinta la un obiect in layerul de networking, acesta trebuie sa aiba cateva componenta importante: Pentru a adauga o referinta la un obiect in layerul de networking, acesta trebuie sa aiba cateva componenta importante:
Line 57: Line 85:
  
 Parcurgand pasii de mai sus va permite deja sa porniti un joc cu mai multi clienti si un server, care sa functioneze si sa sincronizeze miscarile jucatorilor. Parcurgand pasii de mai sus va permite deja sa porniti un joc cu mai multi clienti si un server, care sa functioneze si sa sincronizeze miscarile jucatorilor.
- 
-=== Unity Network Lobby === 
  
 === Network Scripting === === Network Scripting ===
Line 66: Line 92:
   * anumite obiecte nu pot fi folosite decat de un client la un moment dat (inclusiv camera spre ex)   * anumite obiecte nu pot fi folosite decat de un client la un moment dat (inclusiv camera spre ex)
   * input-ul trebuie sa afecteze in general doar client-ul local (deci jucatorul curent nu si altii din retea)   * input-ul trebuie sa afecteze in general doar client-ul local (deci jucatorul curent nu si altii din retea)
 +  * anumite prelucrari trebuie efectuate doar pe server
  
 Astfel, exista definite in pachetul UnityEngine.Networking,​ flag-urile urmatoare: Astfel, exista definite in pachetul UnityEngine.Networking,​ flag-urile urmatoare:
   * isLocalPlayer - true, daca este vorba despre obiectul de pe clientul local   * isLocalPlayer - true, daca este vorba despre obiectul de pe clientul local
   * hasAuthority - true, daca a fost instantiata sau preluata de obiectul de pe clientul local   * hasAuthority - true, daca a fost instantiata sau preluata de obiectul de pe clientul local
 +  * isServer - true, daca scriptul ruleaza instanta curenta pe server
  
 Astfel, in cazul unui script de PlayerController,​ trebuie sa ne asiguram ca actiunile sunt facute doar pentru clientul local. O metoda usoara, este prin stergerea efectiva a obiectelor/​componentelor atunci cand acestea nu sunt locale. Sau, verific ca fiecare actiune sa fie facuta doar local. Astfel, in cazul unui script de PlayerController,​ trebuie sa ne asiguram ca actiunile sunt facute doar pentru clientul local. O metoda usoara, este prin stergerea efectiva a obiectelor/​componentelor atunci cand acestea nu sunt locale. Sau, verific ca fiecare actiune sa fie facuta doar local.
Line 121: Line 149:
 {{ :​pjv:​laboratoare:​unetmanagerspawninfo.png?​500 |}} {{ :​pjv:​laboratoare:​unetmanagerspawninfo.png?​500 |}}
  
-Astfel, in cazul in care obiectele nu fac parte efectiv din player, cum ar fi cele de PickUp, sau arme care se pot schimba etc. pentru care putem folosi flag-ul de hasAuthority:​+Astfel, in cazul in care obiectele nu fac parte efectiv din player, cum ar fi cele de PickUp, sau arme care se pot schimba etc. putem folosi flag-ul de hasAuthority:​
  
 <​code>​ <​code>​
Line 232: Line 260:
 </​code>​ </​code>​
  
 +=== Unity Network Lobby ===
 +...
 +
 +==== DarkRift ====
 +
 +[[https://​darkriftnetworking.com/​DarkRift2|DarkRift 2]] este un server dedicat, modular, care implementeaza protocoale de comunicare ca TCP, UDP, dar si cu extensii pentru WebSocket sau RUDP.
 +Pentru integrarea cu Unity, se poate folosi pachetul din Asset Store [[https://​assetstore.unity.com/​packages/​tools/​network/​darkrift-networking-2-95309|DarkRift Networking 2]]
 +
 +Folosind un server dedicat trebuie gestionate mai multe elemente:
 +  * conexiunile si lista curenta de clienti conectati
 +  * datele stocate despre player
 +  * mesajele de update
 +
 +DarkRift foloseste un sistem modular, bazat pe plugin-uri C#, pentru implementarea serverului.
 +Astfel, putem defini un plugin in felul urmator:
 +<​code>​
 +public class NetPlugin : Plugin
 +{
 +
 +    Dictionary<​IClient,​ Player> players = new Dictionary<​IClient,​ Player>​();​
 +
 +    public override bool ThreadSafe => false;
 +
 +    public override Version Version => new Version(1, 2, 5);
 +
 +    public NetPlugin(PluginLoadData pluginLoadData) : base(pluginLoadData)
 +    {
 +        ClientManager.ClientConnected += ClientConnected;​
 +        ClientManager.ClientDisconnected += ClientDisconnected;​
 +    }
 +}
 +</​code>​
 +unde clasa Player reprezinta datele stocate despre player. Spre exemplu se pot stoca date legate de pozitie, rotatie sau id de utilizator.
 +<​code>​
 +public struct Player
 +{
 +    public ushort ID;
 +    public float X, Y, Z;
 +    public float rotX, rotY, rotZ;
 +}
 +</​code>​
 +
 +In momentul in care se conecteaza un client, trebuie realizate urmatoarele lucruri:
 +  * instantierea Player-ului in server
 +  * notificarea tuturor celorlalti clienti conectati de conectarea unui nou player
 +  * trimiterea de informatii despre ceilalti clienti, clientului nou conectat
 +  * ascultarea de mesaje de actualizare
 +
 +<code c#>
 +void ClientConnected(object sender, ClientConnectedEventArgs e)
 +    {
 +        //new player instance
 +        Player newPlayer = new Player();
 +        newPlayer.ID = e.Client.ID;​
 +        newPlayer.X = 0;
 +        newPlayer.Y = 3;
 +        newPlayer.Z = 0;
 +        newPlayer.rotZ = 0;
 +        newPlayer.rotY = 0;
 +        newPlayer.rotZ = 0;
 +
 +        using (DarkRiftWriter newPlayerWriter = DarkRiftWriter.Create())
 +        {
 +            newPlayerWriter.Write(newPlayer.ID);​
 +            newPlayerWriter.Write(newPlayer.X);​
 +            newPlayerWriter.Write(newPlayer.Y);​
 +            newPlayerWriter.Write(newPlayer.Z);​
 +            newPlayerWriter.Write(newPlayer.rotX);​
 +            newPlayerWriter.Write(newPlayer.rotY);​
 +            newPlayerWriter.Write(newPlayer.rotZ);​
 +
 +            //notify other clients
 +            using (Message newPlayerMessage = Message.Create(0,​ newPlayerWriter))
 +            {
 +                foreach (IClient client in ClientManager.GetAllClients().Where(x => x != e.Client))
 +                    client.SendMessage(newPlayerMessage,​ SendMode.Reliable);​
 +            }
 +        }
 +
 +        players.Add(e.Client,​ newPlayer);
 +
 +        using (DarkRiftWriter playerWriter = DarkRiftWriter.Create())
 +        {
 +            foreach (Player player in players.Values)
 +            {
 +                playerWriter.Write(player.ID);​
 +                playerWriter.Write(player.X);​
 +                playerWriter.Write(player.Y);​
 +                playerWriter.Write(player.Z);​
 +                playerWriter.Write(player.rotX);​
 +                playerWriter.Write(player.rotY);​
 +                playerWriter.Write(player.rotZ);​
 +            }
 +            ​
 +            //send all other players data to new client
 +            using (Message playerMessage = Message.Create(0,​ playerWriter))
 +                e.Client.SendMessage(playerMessage,​ SendMode.Reliable);​
 +        }
 +
 +        e.Client.MessageReceived += MovementMessageReceived;​
 +    }
 +</​code>​
  
-=== Steam ===+==== Steam ====
 .. ..
  
-=== UPlay ===+==== UPlay ====
 .. ..
  
-=== Photon Server ===+==== Photon Server ​====
 .. ..
  
-=== Spatial OS ===+==== Spatial OS ====
 .. ..
  
  
-=== SmartFox ===+==== SmartFox ​====
 ... ...
  
 +===== Cerinte =====
 +
 +Realizarea unui joc multiplayer (network)
 +
 +  * Realizarea unui client si a unui server de networking prin oricare varianta descrisa in laborator (sau altele)
 +  * Clientii (players) trebuie sa vada miscarile si animatiile celorlalti clienti
 +  * Clientii trebuie sa poata interactiona intre ei si cu mediul:
 +    * coliziuni cu mediul (vizibile de catre toti clientii)
 +    * coliziunile dintre playeri afecteaza doar playerii implicati (de ex impuscarea/​lovirea unui alt player ii va lua damage doar acelui player, si se va actualiza interfata grafica doar pentru playerul respectiv)
  
pjv/laboratoare/08.1549035957.txt.gz · Last modified: 2019/02/01 17:45 by alexandru.gradinaru
CC Attribution-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0