web-dev-qa-db-fra.com

Unity3D. Essayer d'envoyer une commande pour un objet sans autorisation

J'ai un jeu de stratégie au tour par tour multijoueur qui a besoin d'un gestionnaire de jeu, contrôlant l'état actuel du jeu (qui est le tour, etc.). Ce gestionnaire doit être commun à chaque client, son état doit être synchronisé sur le serveur.

Voici comment je fais cela: l'objet gestionnaire de jeu est NetworkBehaviour et il a NetworkIdentity qui n'est ni l'autorité du joueur local ni l'autorité du serveur. J'ai créé un NetworkManager personnalisé et il génère le Game Manager lors de la connexion client, testant également s'il s'agit d'un serveur. Voici un code:

public override void OnClientConnect(NetworkConnection conn)
    {
        ClientScene.Ready(conn);
        if (NetworkServer.active)
        {
            var manager = Instantiate(MultiplayerManagerPrefab, Vector3.zero, Quaternion.identity) as GameObject;
            var tacticsManager = manager.GetComponent<MultiplayerManagerModel>();
            NetworkServer.RegisterHandler(MsgType.AddPlayer, tacticsManager.CreatePlayerOnServer);
            NetworkServer.Spawn(manager);
        }
        ClientScene.AddPlayer(0);
    }

Lorsque je l'exécute sur un serveur, cela fonctionne bien, il crée une instance sur un client et synchronise les variables du serveur au client. Mais lorsque j'essaie d'exécuter des commandes à partir du client, il les ignore, lançant cet avertissement:

Essayer d'envoyer une commande pour un objet sans autorisation. UnityEngine.Networking.NetworkBehaviour: SendCommandInternal (NetworkWriter, Int32, String)

Notez que ce Game Manager est généré avant tout joueur, car il doit être responsable de la génération des joueurs. Qu'est-ce que je fais mal?

11
PanCotzky

À côté de votre fragment de code, l'avertissement

Essayer d'envoyer commande pour un objet sans autorisation.

Signifie que: vous envoyez commande à partir d'un objet dont l'autorité , votre (joueur) n'en a pas.

Ce que les documents Unity indiquent: Commandes sont envoyés depuis les objets joueurs sur le client vers les objets joueurs sur le serveur. Pour des raisons de sécurité, Commandes ne peut être envoyé que par VOTRE objet joueur , vous ne pouvez donc pas contrôler les objets des autres joueurs.

[~ # ~] mais [~ # ~]

À partir de la version 5.2 de Unity , il est possible d'envoyer des commandes à partir d'objets non-joueurs qui ont l'autorité du client. Ces objets doivent avoir été générés avec NetworkServer.SpawnWithClientAuthority ou avoir des droits définis avec NetworkIdentity.AssignClientAuthority. Les commandes envoyées à partir de ces objets sont exécutées sur l'instance de serveur de l'objet, pas sur l'objet joueur associé pour le client ( plus ).

Alors quelle est la solution: Avant d'envoyer le Command (ou en exécutant commande fonction), Attribuez l'autorité de cet objet à votre lecteur . Quelque chose comme ça

assignAuthorityObj.GetComponent<NetworkIdentity>().AssignClientAuthority(this.GetComponent<NetworkIdentity>().connectionToClient);

" this " sera représenté à votre objet Player. Après avoir appelé Command, vous pouvez supprimer l'autorité en utilisant cet extrait de code.

 assignAuthorityObj.GetComponent<NetworkIdentity>().RemoveClientAuthority(this.GetComponent<NetworkIdentity>().connectionToClient);

Encore une fois, " this " sera représenté à votre objet Player.

Remarque importante: j'attribue généralement l'autorité d'un objet (si je veux l'utiliser) en utilisant OnTriggerEnter et supprimez l'autorité sur OnTriggerExit . Cela dépend du scénario spécifique à quel événement vous souhaitez acquérir ou supprimer une autorité d'objet.

12

Vous ne pouvez pas envoyer de commande sans autorité locale.

if (!isLocalPlayer) return;

Mais, quel type de données envoyez-vous avec cette commande? En général, et comme vous l'avez dit:

"son état doit être synchronisé sur le serveur"

Donc, à mon humble avis, vous n'avez aucune raison d'envoyer un Command à partir de votre lecteur. Les commandes doivent être destinées aux joueurs. Ces entrées déclencheront des actions dans votre jeu. Votre manager recevra les informations de ces actions (mise à jour du score, fin de partie ...) et enverra des données et/ou déclenchera des actions sur les clients, en utilisant ClientRpc

Il s'agit du modèle d'autorité de serveur. Si vous laissez un objet local envoyer des commandes, un pirate pourrait facilement entrer et dire à votre responsable

"Hé, c'est mon tour. Hé, c'est encore mon tour. Hé, mon score est de 9999999 et j'ai gagné le match en 1 seconde.".

5
FLX