Ich habe ein strategisches Multiplayer-Strategiespiel, das einen Game-Manager benötigt, der den aktuellen Spielstatus kontrolliert (wer an der Reihe ist usw.). Dieser Manager sollte für jeden Client gleich sein, sein Zustand sollte auf dem Server synchronisiert werden.
So mache ich das: Das Spiel-Manager-Objekt ist NetworkBehaviour und es hat NetworkIdentity, das keine lokale Player-Autorität oder Server-Autorität ist. Ich habe einen benutzerdefinierten NetworkManager erstellt, der den Game-Manager beim Client-Connect erzeugt und auch testet, ob es sich um einen Server handelt. Hier ist ein Code:
%Vor%Wenn ich es auf einem Server laufe, funktioniert es gut, es erstellt eine Instanz auf einem Client und synchronisiert Variablen von Server zu Client. Aber wenn ich versuche, Befehle vom Client auszuführen, ignoriert er sie und gibt folgende Warnung aus:
Versuch, Befehl für Objekt ohne Berechtigung zu senden. UnityEngine.Networking.NetworkBehaviour: SendCommandInternal (NetworkWriter, Int32, String)
Beachte, dass dieser Spiel-Manager vor jedem Spieler erstellt wird, da er für das Erstellen von Spielern verantwortlich sein muss. Was mache ich falsch?
Neben dem Code-Fragment die Warnung
Versuch, -Befehl für Objekt ohne Berechtigung zu senden.
Das bedeutet: Sie senden Befehl von einem Objekt, dessen Autorität Ihr (Spieler) nicht hat.
Was in Unity-Dokumenten heißt: Befehle werden von Spielerobjekten auf dem Client zu Spielerobjekten auf dem Server gesendet. Aus Sicherheitsgründen können Befehle nur von IHR Spielerobjekt gesendet werden, sodass Sie die Objekte anderer Spieler nicht steuern können.
ABER
Ab Unity Release 5.2 können Befehle von gesendet werden Nicht-Spieler-Objekte mit Client-Berechtigung. Diese Objekte müssen haben wurde mit NetworkServer.SpawnWithClientAuthority erzeugt oder haben Berechtigung mit NetworkIdentity.AssignClientAuthority festgelegt. Befehle von diesem Objekt gesendet werden auf der Serverinstanz des Objekts ausgeführt, nicht auf dem zugehörigen Player-Objekt für den Client ( mehr ).
Was ist die Lösung: Bevor Sie die Befehl (oder die Befehl -Funktion ausführen) senden, diesem Objekt die Berechtigung dieses Objekts zuweisen . So etwas Ähnliches
%Vor%" this " wird für Ihr Player-Objekt dargestellt. Nach dem Aufruf von Command können Sie die Berechtigung mithilfe dieses Code-Snippets entfernen.
%Vor%Auch hier wird " this " für Ihr Player-Objekt dargestellt.
Wichtiger Hinweis : Normalerweise ordne ich Autorität eines Objekts zu (wenn ich das verwenden möchte), indem ich OnTriggerEnter verwende und Autorität auf entferne > OnTriggerExit . Es hängt von einem bestimmten Szenario ab, bei welchem Ereignis eine Objektautorität erworben oder entfernt werden soll.
Sie können keinen Befehl ohne lokale Berechtigung senden.
%Vor%Aber welche Art von Daten senden Sie mit diesem Befehl? Im Allgemeinen und wie du gesagt hast:
"sein Zustand sollte auf dem Server synchronisiert werden"
Ihr habt also keinen Grund, ein Command
von eurem Player zu senden.
Befehle sollten für die Spielereingabe sein.
Diese Eingaben lösen Aktionen in Ihrem Spiel aus.
Ihr Manager wird Informationen von diesen Aktionen erhalten (Aktualisierung der Punkte, Ende des Spiels ...) und Daten senden und / oder Aktionen auf Clients auslösen, indem ClientRpc
Dies ist das Serverberechtigungsmodell. Wenn Sie ein lokales Objekt Befehle senden lassen, kann ein Hacker leicht kommen und zu Ihrem Manager sagen.
"Hey, ich bin dran. Hey, ich bin wieder dran. Hey, meine Punktzahl ist 9999999 und ich habe das Spiel in 1 Sekunde gewonnen.".
Tags und Links c# networking unity3d unity3d-unet