Jump to content
Unity Insider Forum

UNET Authoritative Server - Wie Verbindung zu den Clients?


schoen08

Recommended Posts

Hallöchen,

 

ich probiere mich seit knapp 2 Wochen zum ersten Mal an einem Online Multiplayer. Jetzt habe ich gemerkt, dass es wohl besser ist wenn alle Spielerobjekte auf dem Server liegen (Physics und Collision Erkennung). Hab mir jetzt mehrere Artikel dazu durchgelesen und mir das jetzt so erklärt:

 

Das PlayerObject steuert die Spielerobjekte auf dem Server. Jeder Client fordert also den Server auf, ein neues Objekt auf dem Server zu erstellen - nur wie kann ich jetzt darauf vom Client zugreifen um es zu steuern? Oder habe ich etwas total falsch verstanden?

 

Ich Instantiate im Moment von meinen ClientControl Objektrn beim Verbinden zum Server über ein CMD den Spieler auf dem Server. Das funktioniert wunderbar, nur kann ich dann ja nicht mehr vom ClientControl auf genau dem richtigen Spieler auf dem Server zugreifen.

 

Danke für jede Hilfe!

Link zu diesem Kommentar
Auf anderen Seiten teilen

Die Clients senden direkte Befehle an den Server, mit UNet über Commands.

 

Der Server validiert die Eingaben nochmal, damit er nicht alles glaubt, was man ihm sagt.

Wichtig ist, dass du auf der Spielerseite dieselbe Simulation ausführst wie auf dem Server. Das nennt sich "Input Prediction" und sorgt dafür, dass der Spieler sich sofort bewegt, und nicht nach dem Input bei 150ms ping 300ms warten muss, bis was passiert.

Dann musst du abgleichen, ob der Client dasselbe raus gekriegt hat wie der Server. Wenn nicht, muss der Client korrigieren.

Wird recht komplex wenn man's richtig machen will, hab beim testweisen Implementieren ein paar Nachmittage verbraten.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Kurz umrissen, das PlayerObject (und damit den Spieler) bewegt man wohl indem man ein NetworkTransform dem Player Prefab hinzufügt. Das NetworkTransform sorgt dann selbst für die notwendige Synchronisation (RPC Calls) der Rotation und der Bewegungen des Spielers (inklusive Interpolation) von Client zum Server (oder umgekehrt). Das PlayerObject wird dann durch den NetworkManager aus der ihm zugewiesenen Player Prefab erzeugt (Ein Client verbindet sich zum Server und ruft NetworkServer.AddPlayerForConnection auf).

Link zu diesem Kommentar
Auf anderen Seiten teilen

Heyho erstmal vielen Dank für eure Antworten :).

 

Kurz umrissen, das PlayerObject (und damit den Spieler) bewegt man wohl indem man ein NetworkTransform dem Player Prefab hinzufügt. Das NetworkTransform sorgt dann selbst für die notwendige Synchronisation (RPC Calls) der Rotation und der Bewegungen des Spielers (inklusive Interpolation) von Client zum Server (oder umgekehrt). Das PlayerObject wird dann durch den NetworkManager aus der ihm zugewiesenen Player Prefab erzeugt (Ein Client verbindet sich zum Server und ruftNetworkServer.AddPlayerForConnection auf).

 

Das ist mir eigentlich schon klar - ich hatte den ganzen Multiplayer mit normalen Server/Client schon auch schon laufen. Allerdings besitzt dann jeder Client ja sein eigenes Spielerobjekt - und beim authoritative Server sollen alle Spielerobjekte ja auf dem Server laufen, und die Clients geben in ihren "Fake"-Spielern (die eigentlich nur die Controls sind) die Befehle für die Bewegung & Co an die Objekte auf dem Server. Dann kann auf dem Server die Physik Simulation stattfinden.

 

Wird recht komplex wenn man's richtig machen will, hab beim testweisen Implementieren ein paar Nachmittage verbraten.

 

Ohje ein paar Nachmittage! :D

 

Die Clients senden direkte Befehle an den Server, mit UNet über Commands.

 

Genau, und da ist bei mir momentan die Ahnungslosigkeit: Klar kann ich Befehle auf dem Server ausführen, aber wie weiß denn der Client noch, welches sein Spielerobjekt auf dem Server ist?

 

Momentane Situation:

Das PlayerPrefab was bei mir gespawned wird, nennt sich ClientControl und hat ein Network-Script welches beim Starten

 

public void SetUp(){
 if (isLocalPlayer) {
  CmdSpawnBoatOnServer();
		    }
}

 

aufruft. Und CmdSpawnBoatOnServer erstellt dann ein neues Spielerobjekt auf dem Server, was ich in Zukunft von diesem Client aus steuern möchte.

 

[Command]
public void CmdSpawnBoatOnServer(){

 serverBoat = (GameObject)Instantiate (boatPrefab, spawn.position, spawn.rotation);

}

 

Nur wird serverBoat auf den Clients nie gesetzt, weil sich die Objekte ja nur auf dem Server befinden. In meiner weiteren Vergehensweise wollte ich jetzt eben über Commands auf genau dem richtigen serverBoat das Boot Steuern und über die Positionen aller serverBoats die InputPrediction auf den Clients machen.

 

Ich hab da vielleicht auch einfach nur einen Knoten im Kopf ^_^

 

Danke euch!

Link zu diesem Kommentar
Auf anderen Seiten teilen

Kurz umrissen, das PlayerObject (und damit den Spieler) bewegt man wohl indem man ein NetworkTransform dem Player Prefab hinzufügt. Das NetworkTransform sorgt dann selbst für die notwendige Synchronisation (RPC Calls) der Rotation und der Bewegungen des Spielers (inklusive Interpolation) von Client zum Server (oder umgekehrt). Das PlayerObject wird dann durch den NetworkManager aus der ihm zugewiesenen Player Prefab erzeugt (Ein Client verbindet sich zum Server und ruft NetworkServer.AddPlayerForConnection auf).

Das ist alles Optional.

Man muss natürlich nicht ein NetworkTransform haben. Auch NetworkManager muss kein Player zugewiesen haben.

 

 

...nur wie kann ich jetzt darauf vom Client zugreifen um es zu steuern? Oder habe ich etwas total falsch verstanden?...

 

Also ich beschäftige mich auch wie du seit Wochen damit. Wenn man bisschen verstanden hat ist es nicht so schwer.

Wenn du ein Networkmanager benutzen tust: Das braucht bisschen Management. Wenn ein Spieler joint wird ja ein eine Funktion aufgerufen AddPlayerForConnection (falls man Networkmanager benutzt und nicht overrided).

Die Methodennamen erklären leider nicht immer was das genau macht.

Das ganze beginnt in dem Client sagt ClientScene.Ready(conn), ClientScene.AddPlayer(0). AddPlayer wie der Name NICHT erkennen lässt bedeutet das eigentlich nur "Spawne ihn".

Dadurch folgt ein Call auf dem Server OnServerAddPlayer(NetworkConnection conn, short playerControllerId). Die Funktion ist jetzt dafür gedacht, dass man nun auf allem Clients etwas spawnt.

Dabei ist wichtig nach Instantiante das hier zu tun: NetworkServer.AddPlayerForConnection(conn, playerGameObject, playerControllerId);

Das bedeutet nichts anderes als, dass das playerGameObject zu owner "conn" bzw. playerControllerID (Weiß nicht warum beides ist) gehört.

 

Danach kann man halt mit localplayer oder so abfragen, ob man es steuert.

Ich mache dafür gerne eine Controlling Variable, welches vom Client gesetzt wird (damit man später quasi die Kontrolle übergeben kann ohne großen Aufwand.)

Natürlich wird es überprüft, ob man steuern darf.

	if (isLocalPlayer || isSingleplayerControlling)
		Controlling = true;

Während ich am schreiben war hast du auch schon geschrieben.

 

Wenn du das mit Commands machen willst, dann musst du halt an dem Server spawn schicken(was du schon tust) und der Server muss mit ClientRPC dann zu Clients senden, dass sie auch Spawnen sollen.

Denn Commands geht nur an den Server und der Server kann nur mit ClientRPC an die Clients senden ( Sei denn du benutzt low level :D).

Das wäre fast wie das alte Verfahren mit RPC wo man bissel hin und her sendet.

Danach kannst du ja auch sowas wie Controlling variable machen.

 

Diesen Controlling variable habe ich gemacht, weil ich bei meinem Testprojekt Fahrzeuge hatte. Ich wollte gerne sowas wie bei GTA machen, dass man auch benutzen kann auch wenn man nicht der Owner ist. UNet hat zwar sein System dafür, aber ich habe es mir mal einfach gemacht ^^.

 

 

EDIT: Falls du willst, dass man per Knopfdruck spawnt (daher dein CMD), dann muss man einfach nur ClientScene.AddPlayer(0) bei Networkmanager(glaub ich)machen. Das hat ja singleton, wo du das dann callen kannst. Musst eventuell OnServerAddPlayer anpassen.

Link zu diesem Kommentar
Auf anderen Seiten teilen

Mazy hat recht. Der einfachste Weg ist es tatsächlich das SpielerObjekt im Networkmanager zu setzen.

Es ist zwar auch möglich anders zu spawnen, das macht allerdings alles viel komplizierter.

 

Übrigens geht "IsLocalPlayer" und die ganzen "Commands" auch nur auf eben diesem SpielerObjekt welches (automatisch) durch den Networkmanager instanziiert und im Netzwerk gespawnt wurde.

 

Das ist auch ein wichtiger Unterschied:

Instanziieren ist das was du aus dem Singleplayer kennst. Also das lokale erstellen eines GameObjekts.

"Spawning" im UNET Kontext ist hingegen die Anweisung des Servers an die Clients ein bestimmtes GameObjekt zu spawnen. Man übergibt der Spawn Methode also ein GameObjekt welches auf dem Server schon existiert und sorgt dafür, dass dieses auch auf den Clients erstellt wird.

 

Steht übrigens alles ausführlich im Networking Manual:

http://docs.unity3d.com/Manual/UNetConverting.html

Link zu diesem Kommentar
Auf anderen Seiten teilen

Mazy hat recht. Der einfachste Weg ist es tatsächlich das SpielerObjekt im Networkmanager zu setzen.

Es ist zwar auch möglich anders zu spawnen, das macht allerdings alles viel komplizierter.

Ich habe das eigentlich nicht gesagt. Zer0Cools Beschreibung passt da eher zu. Ich habe nur beschrieben, wie es abläuft.

Ich schreibe gerne meine eigene NetworkManager Script und ändere es ab. Natürlich abhängig davon, was für ein Spiel das sein wird. Beispiel in einem Spielgeschehen mit einsteigen wäre mir lieber mit nem Spawnbutton wie bei Battlefield.

 

 

EDIT: Aso jetzt merke ich gerade was du meinst. AddPlayerForConnection :D

Link zu diesem Kommentar
Auf anderen Seiten teilen

Vielen Dank für eure Hilfe!

 

Ich habe heute Nachmittag dieses öffentliche GitHub-Authoritative Server Projekt gefunden - da wurschtel ich mich gerade komplett durch, und mit zusammen mit euren Antworten ist schon einiges klarer geworden.

Ich meld mich dann wahrscheinlich bald wieder, wenn es wieder Probleme gibt :D.

 

 

Schönen Abend und nochmal vielen Dank!

Link zu diesem Kommentar
Auf anderen Seiten teilen

Archiviert

Dieses Thema ist jetzt archiviert und für weitere Antworten gesperrt.

×
×
  • Neu erstellen...