Showing posts with label RPC. Show all posts
Showing posts with label RPC. Show all posts
Nahkampf

Tuesday, November 5, 2013

Nahkampf

In meinem Spiel soll es möglich sein den Gegner sobald man in einem gewissen Radius ist im Nahkampf zu treffen.


Hierfür habe ich meinem Playerobjekt ein Unterobjekt gegeben welches den Nahkampfbereich darstellt.


Sobald sich mein Gegner (die grün dargestellte Kapsel in der Mitte des blauen Rechteckes) in diesem Bereich befindet und ich die linke Maustaste drücke, wird dem Gegner ein geringer Teil der Lebenspunkte abgezogen.

if(networkView.isMine)
{
   if(Input.GetKeyDown(KeyCode.Mouse0))
   { 
      if(nahkampfColliderManager.EnemyInCollider == true)
      {
          networkView.RPC("NahkampfRPC", uLink.RPCMode.Others, "test"); 
          healthPointsEnemyLocal-= Screen.width/3*0.95f/15;             
      } 
   }
}
  
Das ganze geschieht aufgrund der if-Abfrage: if(networkView.isMine){}; nur beim eigenen Client. Damit Client Nr.2 mitbekommt, dass er geschlagen wird, kommt das Aufrufen der "NahkampfRPC"-Funktion zum Einsatz, welche durch einen RPC ausgelöst wird. Diese wird an alle anderen Clients und an den Server gesendet jedoch nicht an sich selbst.
Bei den anderen Clients wird nun folgendes passieren:

[RPC]
void fernkampfRPC(string test)
{
    healthPointsEnemyLocal-=Screen.width/3*0.95f/15;
}

Beim Gegner werden die lokalen Lebenspunkte abgezogen. So wird sowohl bei Client Nr.1 als auch bei Client Nr.2 der gleiche Lebenspunktebalken gestaucht und die Lebenspunkte sinken.

Das soll später natürlich nicht bei jedem Klicken der Maus erfolgen, sonst wäre derjenige der schneller klicken kann der Gewinner und das Spiel wäre nach wenigen Sekunden beendet. Es muss einen Timer und eventuell einen Rückschlag geben, sodass man nur in bestimmten Abständen zuschlagen kann. Dadurch wird man automatisch andere Wege zum Sieg bevorzugen.

Lebenspunkte

Tuesday, October 29, 2013

Lebenspunkte

In diesem Post werde ich euch erklären und zeigen, wie mein Lebenspunktesystem funktioniert.


Grob gesagt gibt es zwei Variablen welche die Lebenspunkte organisieren, jedoch den gleichen Wert besitzen. Ihr fragt euch jetzt bestimmt: Wieso zwei Variablen mit dem gleichen Wert? Da reicht doch eine?! Das stimmt nicht ganz, das dachte ich am Anfang nämlich auch. Hier meine Erläuterung:

1. public static float healthPointsEnemy;
2. public static float healthPointsEnemyLocal;

Wie die Variablennamen schon sagen speichert die eine die Lebenspunkte des Gegners, die andere hat den gleichen Wert, wird aber für das lokale Anzeigen der gegnerischen Lebenspunkte benötigt.

Wird nun Client Nr.1 von Client Nr.2 geschlagen, so wird bei Client Nr.1 die Variable healthPointsEnemyLocal verringert. Durch einen RPC (Remote Procedure Call - hiermit kann man Funktionen auslösen, welche z.B. nicht beim eigenen Client passieren - mehr dazu hier) wird beim Gegner die Variable healthPointsEnemy verringert.

Um das ganze nun schön anzuzeigen werden die weißen Balken, welche ihr im Bild unten seht, entsprechend der Lebenspunkte gestreckt oder gestaucht.

Erster Healthbar Entwurf
Die Breite eines Balkens in meinem Spiel beträgt: healthPointsEnemyLocal.
Der Wert der Variable healthPointsEnemyLocal beträgt Screen.width/3*0.95f.
So wird gewährleistet, dass bei jeder Bildschirmgröße das Verhältnis der Lebenspunkte gleich bleibt.

Nun wäre es noch wichtig zu wissen welcher Balken zu welchem Spieler gehört. Denn der erste Spieler der sich zum Server verbindet startet auf der linken Seite, der zweite auf der Rechten. Dann sollten die Lebenspunkte des ersten Spielers logischerweise nicht auf der rechten Seite angezeigt werden.

Hierfür erhält eine Variable enemyIn beim Start den Wert false.

enemyIn = false;

Sobald diese Variable den Wert erhalten hat, wird die Abfrage

if(enemyIn==false){};

ausgelöst und bewirkt das Auslösen eines RPC für die Funktion SyncEnemyVar.

networkView.RPC("SyncEnemyVar", uLink.RPCMode.Others, "enemyIn");

Die SyncEnemyVar-Funktion verändert wiederum den Wert der Variable check von false auf true.

check = true;

Sobald check true ist, wird wieder eine Funktion durch einen RPC ausgelöst,

if(check==true)
{
   networkView.RPC("SyncEnemyVar2",uLink.RPCMode.Others,"enemyIn");
}

welche bewirkt, dass enemyIn true wird und einen weiteren RPC mit der Funktion "setCheckFalse" auslöst.

enemyIn = true;
networkView.RPC("setCheckFalse",uLink.RPCMode.All,"enemyIn");

Was diese tut verrät schon der Name.

Somit ist beim zweiten Spieler die Variable enemyIn true und wir können ihre Werte für das zuteilen der Balken nutzen.
Wenn die Variable enemyIn true ist, hat sich der Gegner zuerst mit dem Server verbunden und der eigene Character steht links. Somit ist mein Balken mit der Größe healthPointsEnemy auf der rechten Seite und der Balken mit der Größe healthPointsEnemyLocal auf der linken Seite.

Vermutlich hat das den ein oder anderen von euch etwas verwirrt :) jedoch ist dies eine von vielen Möglichkeit ein Lebenspunktesystem zu bauen und bei genauerem Hinschauen recht einfach nachzuvollziehen!

uLink - Server und Client

Saturday, October 19, 2013

uLink - Server und Client

Nach Rücksprache mit meinem Dozenten habe ich mich für die Netzwerklösung "uLink"  von MuchDifferent entschieden.


Der Vorteil daran war, dass mein eigener Laptop oder Rechner einen Server darstellen kann, sodass ich keine auftauchenden Verzögerungen bei meiner Prüfung haben werde, da ich innerhalb eines Netzwerkes arbeiten kann. Zudem kann ich Server- und Clientbasiert programmieren was in manchen Situationen bestimmt hilfreich werden kann.
Außerdem gibt es für uLink eine für mich gut nachvollziehbare Dokumentation mit Tutorials und einiges an Material im Web zu finden.

Ich habe also damit angefangen, wie bei Photon auch, die ersten Dokumentationen zu lesen und mir ein Grundgerüst aufzubauen. Bald hat auch schon mein Server funktioniert, zu welchem sich meine Clients verbinden konnten. 
Um euch auch einmal einen kleinen Einblick in die Programmierung zu geben, seht ihr hier das GUI-System, mit welchem ich entweder einen Server darstellen oder mich zum Server verbinden kann:

void OnGUI()
{
    // Checking if you are connected to the server or not
    if (uLink.Network.peerType == uLink.NetworkPeerType.Disconnected)
    {
        // Show fields to insert ip address and port
        serverIP = GUI.TextField(new Rect(120, 10, 100, 20), serverIP);
        serverPort = int.Parse(GUI.TextField(new
        Rect(230, 10, 40, 20), serverPort.ToString()));
        if (GUI.Button(new Rect(10, 10, 100, 30), "Connect"))
        {
            //This code is run on the client
            uLink.Network.Connect(serverIP, serverPort);
            Debug.Log("Did send call to server");
        }
        if (GUI.Button(new Rect(10, 50, 100, 30), "Start Server"))
        {
            //This code is run on the server
            uLink.Network.InitializeServer(32, serverPort);
        }
    }
}

Falls das jemanden genauer interessiert, hier der Link zur Website mit MuchDifferent-eigenen Tutorials. Dort findet man unter anderem ein PDF welches den Einstieg ausführlich erklärt.
Das ganze sieht im Spiel dann so aus:

GUI - Server starten oder Client verbinden

In den ersten Schritten wird zudem gezeigt wie man definiert was passieren soll wenn sich ein Client beispielsweise vom Server trennt oder die Verbindung abbricht:

    void uLink_OnPlayerDisconnected(uLink.NetworkPlayer player)
    {
        uLink.Network.DestroyPlayerObjects(player);
        uLink.Network.RemoveRPCs(player);
    }

In diesem Fall werden alle "netzwerkverbundenen" Objekte, welche zum getrennten Client gehören und natürlich dessen hinterlassenen RPCs zerstört. RPCs sind Funktionen mit denen man grob gesagt zwischen Clients und Server kommunizieren kann. Die werden im Laufe meiner Arbeit mit Sicherheit noch des öfteren auftauchen!