This is an old revision of the document!


5. Multiplayer dedicated server

Cerinte

Realizarea unui joc multiplayer de tip whack-a-mole / colectare:

  • Creati o scena care sa genereze random obiecte pe harta, sincronizate in retea. Host-ul sau server-ul este cel care are autoritate, asadar are 'dreptul' de a realiza spawn-ul acestor obiecte
  • Jocul incepe atunci cand exista cel putin 2 jucatori conectati
  • Fiecare jucator va avea health, afisati acesta in joc printr-un health bar (ex. world-space canvas)
  • Jucatorii sunt animati si se pot deplasa folosind input standard de la mouse/tastatura pentru a atinge obiectele
  • In momentul in care un obiect este atins, jucatorul care l-a atins primeste scor, iar obiectul este distrus
  • In scena apar la anumite intervale de timp zone de damage
    • Decideti voi cum si unde apar zonele, va recomandam sa apara la locatii random din ce in ce mai des dupa ce incepe o sesiune de joc
    • Aceste zone vor aplica damage unitatilor
    • In mod ideal, precum este si in referinta video, aceste zone sunt marcate in prealabil cu cateva secunde pentru a informa jucatorii de pericol si a le da timp sa se deplaseze din acea zona
    • Jocul se incheie atunci cand ramane in viata un singur client
  • Exista un leaderboard afisat pe TAB care afiseaza scorul curent al tuturor jucatorilor conectati
  • Jocul poate functiona in mod client-server (aveti nevoie de 3 instante/build-uri, unul pentru server, 2 pentru clienti) sau in mod host-client (aveti nevoie de 2 instante/build-uri, unul care va fi atat server cat si client, si un alt client)

Bonus: Click-and-move folosind cursorul

Exemplu: In acest mini-game dintr-un mod de tower defense din Warcraft 3 se poate observa o scena in care apar in mod constant obiecte colectabile (coins), precum si o unitate controlata de player (minutele 5:05 → 5:20). Video referinta. Daca ar fi sa implementati un joculet similar, va trebui sa aveti 2 astfel de unitati spawn-ate in scena, controlabile in mod independent.

Documentatie video

Documentatie text

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 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:

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;
    }
}

unde clasa Player reprezinta datele stocate despre player. Spre exemplu se pot stoca date legate de pozitie, rotatie sau id de utilizator.

public struct Player
{
    public ushort ID;
    public float X, Y, Z;
    public float rotX, rotY, rotZ;
}

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
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;
    }
pjv/laboratoare/2024/a09.1734343947.txt.gz · Last modified: 2024/12/16 12:12 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