Freigeben über


Entitätsgruppen

PlayFab-Gildenlösung

Angenommen, Sie brauchen Gilden, Clans, Unternehmen, Unternehmen, Stämme - oder was auch immer Ihr Spiel nennt - PlayFab hat sie.

PlayFab erstellt Gilden mit dem neuen Entity Programming Model, genauer gesagt dem Entitätstyp von Gruppen. Entitätsgruppen sind ein umfassenderes Konzept als Gilden, aber im Grunde wurden Entitätsgruppen als Lösung für Gilden erstellt.

Entitätsgruppen

Entitätsgruppen sind das Grundkonzept, das von der Notwendigkeit von Clans/Gilden inspiriert wurde.

Im Kern sind Entitätsgruppen eine beliebige logische Gruppe von Entitäten, die jedem Zweck dienen können. Entitätsgruppen können gleichzeitig viele Zwecke in Ihrem Spiel erfüllen.

Beispiele

  • Clans/Gilden - Dies war der Ausgangspunkt und die Standard treibenden Notwendigkeit. Entitätsgruppen können verwendet werden, um eine Gruppe von Spielern zu beschreiben, die regelmäßig zusammen spielen, für jeden sozialen Klebstoff, der sie langfristig zusammenhält.

  • Parteien : Entitätsgruppen können für kurzfristige Gruppen verwendet werden, die erstellt werden, um einzelnen Spielern zu ermöglichen, ein unmittelbares Ziel zu erreichen, und anschließend leicht aufgelöst werden.

  • Chatkanäle : Kurz- oder langfristige Chatkanäle können als Entitätsgruppe definiert werden.

  • In-Game-Abonnement für Informationen - Haben Sie einen einzelnen instance legendären Gegenstand in Ihrem Spiel? Möchten Die Spieler ständig aktualisieren, was mit diesem Element geschieht? Erstellen Sie eine Entitätsgruppe, die sich auf dieses Element konzentriert, wobei alle Spielerentitäten, die an dem Element interessiert sind, als Mitglieder sind.

Kurz gesagt, Entitätsgruppen können eine beliebige Sammlung von Entitäten (NPC oder spielergesteuert, real oder abstrakt) sein, die einen persistenten Zustand benötigen, der an diese Gruppe gebunden ist.

Eine Freundesliste ist eine Gruppe. Ein privater Chat mit drei Personen ist eine Gruppe. Go nuts!

Notiz

Wir würden uns über eine Warnung in den Foren freuen, wenn Sie etwas versuchen, das wir möglicherweise nicht erwarten...

Da Entitätsgruppen auch Entitäten selbst sind, enthalten sie außerdem alle anfänglichen Features von Entitäten:

  • Objektdaten
  • Dateidaten
  • Profile

Sie sind in Zukunft für neue Entitätsfeatures berechtigt, wenn diese Features für Gruppen relevant sind.

Notiz

Gruppen haben einen Standardgrenzwert von 1.000 Mitgliedern pro Gruppe.

Verwenden von Entitätsgruppen

Heute können Entitätsgruppen Spieler und/oder Charaktere enthalten. Beim Erstellen einer Gruppe wird die erste Entität, die der Gruppe hinzugefügt wird, in einer Admin Rolle platziert (dieser Leitfaden bezieht sich der Einfachheit halber auf diese Entität als Besitzer). Der Besitzer ist dann in der Lage, neue Mitglieder einzuladen, neue Rollen mit einer Vielzahl von anpassbaren Berechtigungen zu erstellen, Mitgliedsrollen zu ändern, Mitglieder zu kicken usw.

Darüber hinaus funktionieren dieselben Entitätsfunktionen, die für Entitäten vorhanden sind, auch für Gruppen, sodass Sie JSON-Objekte und -Dateien direkt in der Gruppe speichern können, um beliebige spielspezifische Daten zu speichern.

Das unten bereitgestellte Codebeispiel sollte Ihnen einen Vorsprung bei der grundlegenden Interaktion mit Gilden bieten.

Es ermöglicht Ihnen, Gruppen zu erstellen, Mitglieder hinzuzufügen und zu entfernen und die Gruppe zu löschen. Es soll ein Ausgangspunkt sein und zeigt keine der Rollen oder Berechtigungen.

using PlayFab;
using PlayFab.GroupsModels;
using System;
using System.Collections.Generic;
using UnityEngine;

namespace TestGuildController
{
    /// <summary>
    /// Assumptions for this controller:
    /// + Entities can be in multiple groups
    ///   - This is game specific, many games would only allow 1 group, meaning you'd have to perform some additional checks to validate this.
    /// </summary>
    [Serializable]
    public class GuildTestController
    {
        // A local cache of some bits of PlayFab data
        // This cache pretty much only serves this example , and assumes that entities are uniquely identifiable by EntityId alone, which isn't technically true. Your data cache will have to be better.
        public readonly HashSet<KeyValuePair<string, string>> EntityGroupPairs = new HashSet<KeyValuePair<string, string>>();
        public readonly Dictionary<string, string> GroupNameById = new Dictionary<string, string>();

        public static EntityKey EntityKeyMaker(string entityId)
        {
            return new EntityKey { Id = entityId };
        }

        private void OnSharedError(PlayFab.PlayFabError error)
        {
            Debug.LogError(error.GenerateErrorReport());
        }

        public void ListGroups(EntityKey entityKey)
        {
            var request = new ListMembershipRequest { Entity = entityKey };
            PlayFabGroupsAPI.ListMembership(request, OnListGroups, OnSharedError);
        }
        private void OnListGroups(ListMembershipResponse response)
        {
            var prevRequest = (ListMembershipRequest)response.Request;
            foreach (var pair in response.Groups)
            {
                GroupNameById[pair.Group.Id] = pair.GroupName;
                EntityGroupPairs.Add(new KeyValuePair<string, string>(prevRequest.Entity.Id, pair.Group.Id));
            }
        }

        public void CreateGroup(string groupName, EntityKey entityKey)
        {
            // A player-controlled entity creates a new group
            var request = new CreateGroupRequest { GroupName = groupName, Entity = entityKey };
            PlayFabGroupsAPI.CreateGroup(request, OnCreateGroup, OnSharedError);
        }
        private void OnCreateGroup(CreateGroupResponse response)
        {
            Debug.Log("Group Created: " + response.GroupName + " - " + response.Group.Id);

            var prevRequest = (CreateGroupRequest)response.Request;
            EntityGroupPairs.Add(new KeyValuePair<string, string>(prevRequest.Entity.Id, response.Group.Id));
            GroupNameById[response.Group.Id] = response.GroupName;
        }
        public void DeleteGroup(string groupId)
        {
            // A title, or player-controlled entity with authority to do so, decides to destroy an existing group
            var request = new DeleteGroupRequest { Group = EntityKeyMaker(groupId) };
            PlayFabGroupsAPI.DeleteGroup(request, OnDeleteGroup, OnSharedError);
        }
        private void OnDeleteGroup(EmptyResponse response)
        {
            var prevRequest = (DeleteGroupRequest)response.Request;
            Debug.Log("Group Deleted: " + prevRequest.Group.Id);

            var temp = new HashSet<KeyValuePair<string, string>>();
            foreach (var each in EntityGroupPairs)
                if (each.Value != prevRequest.Group.Id)
                    temp.Add(each);
            EntityGroupPairs.IntersectWith(temp);
            GroupNameById.Remove(prevRequest.Group.Id);
        }

        public void InviteToGroup(string groupId, EntityKey entityKey)
        {
            // A player-controlled entity invites another player-controlled entity to an existing group
            var request = new InviteToGroupRequest { Group = EntityKeyMaker(groupId), Entity = entityKey };
            PlayFabGroupsAPI.InviteToGroup(request, OnInvite, OnSharedError);
        }
        public void OnInvite(InviteToGroupResponse response)
        {
            var prevRequest = (InviteToGroupRequest)response.Request;

            // Presumably, this would be part of a separate process where the recipient reviews and accepts the request
            var request = new AcceptGroupInvitationRequest { Group = EntityKeyMaker(prevRequest.Group.Id), Entity = prevRequest.Entity };
            PlayFabGroupsAPI.AcceptGroupInvitation(request, OnAcceptInvite, OnSharedError);
        }
        public void OnAcceptInvite(EmptyResponse response)
        {
            var prevRequest = (AcceptGroupInvitationRequest)response.Request;
            Debug.Log("Entity Added to Group: " + prevRequest.Entity.Id + " to " + prevRequest.Group.Id);
            EntityGroupPairs.Add(new KeyValuePair<string, string>(prevRequest.Entity.Id, prevRequest.Group.Id));
        }

        public void ApplyToGroup(string groupId, EntityKey entityKey)
        {
            // A player-controlled entity applies to join an existing group (of which they are not already a member)
            var request = new ApplyToGroupRequest { Group = EntityKeyMaker(groupId), Entity = entityKey };
            PlayFabGroupsAPI.ApplyToGroup(request, OnApply, OnSharedError);
        }
        public void OnApply(ApplyToGroupResponse response)
        {
            var prevRequest = (ApplyToGroupRequest)response.Request;

            // Presumably, this would be part of a separate process where the recipient reviews and accepts the request
            var request = new AcceptGroupApplicationRequest { Group = prevRequest.Group, Entity = prevRequest.Entity };
            PlayFabGroupsAPI.AcceptGroupApplication(request, OnAcceptApplication, OnSharedError);
        }
        public void OnAcceptApplication(EmptyResponse response)
        {
            var prevRequest = (AcceptGroupApplicationRequest)response.Request;
            Debug.Log("Entity Added to Group: " + prevRequest.Entity.Id + " to " + prevRequest.Group.Id);
        }
        public void KickMember(string groupId, EntityKey entityKey)
        {
            var request = new RemoveMembersRequest { Group = EntityKeyMaker(groupId), Members = new List<EntityKey> { entityKey } };
            PlayFabGroupsAPI.RemoveMembers(request, OnKickMembers, OnSharedError);
        }
        private void OnKickMembers(EmptyResponse response)
        {
            var prevRequest= (RemoveMembersRequest)response.Request;
            
            Debug.Log("Entity kicked from Group: " + prevRequest.Members[0].Id + " to " + prevRequest.Group.Id);
            EntityGroupPairs.Remove(new KeyValuePair<string, string>(prevRequest.Members[0].Id, prevRequest.Group.Id));
        }
    }
}

Dekonstruieren des Beispiels

Dieses Beispiel ist als Controller erstellt, der minimale Daten in einem lokalen Cache speichert (PlayFab ist die autoritative Datenebene) und eine Möglichkeit zum Ausführen von CRUD-Vorgängen für Gruppen bietet.

Sehen wir uns einige der Funktionen im bereitgestellten Beispiel an:

  • OnSharedError – Dies ist ein typisches Muster mit PlayFab-Beispielen. Die einfachste Möglichkeit, einen Fehler zu behandeln, besteht darin, ihn zu melden. Ihr Spielclient verfügt wahrscheinlich über eine viel komplexere Fehlerbehandlungslogik.

  • ListMembership – Ruft auf ListMembership , um alle Gruppen zu bestimmen, zu denen die angegebene Entität gehört. Die Spieler möchten wissen, welche Gruppen sie bereits beigetreten sind.

  • CreateGroup / DeleteGroup - Meist selbsterklärend. In diesem Beispiel wird das Aktualisieren des Infocaches der lokalen Gruppe veranschaulicht, wenn diese Aufrufe erfolgreich ausgeführt werden.

  • InviteToGroup / ApplyToGroup - Der Beitritt zu einer Gruppe ist ein zweistufiger Prozess und kann in beide Richtungen aktiviert werden:

    • Ein Spieler kann darum bitten, einer Gruppe beizutreten.
    • Eine Gruppe kann einen Spieler einladen.
  • AcceptGroupInvitation / AcceptGroupApplication – Der zweite Schritt des Joinprozesses. Die antwortende Entität nimmt die Einladung an und schließt den Prozess ab, den Spieler zu einem Teil der Gruppe zu machen.

  • RemoveMembers - Mitglieder, die dazu berechtigt sind (durch ihre Rollenberechtigungen definiert), können Mitglieder aus einer Gruppe kicken.

Server im Vergleich zu Client

Wie bei allen neuen Entitäts-API-Methoden gibt es keinen Unterschied zwischen der Server-API und der Client-API.

Die Aktion wird vom Aufrufer ausgeführt, je nachdem, wie der Prozess authentifiziert wurde. Ein Client wird als solcher identifiziert und ruft diese Methoden als Titelspielerentität auf, und seine Rollen und Berechtigungen innerhalb der Gruppe werden bei jedem Aufruf ausgewertet, um sicherzustellen, dass er über die Berechtigung zum Ausführen dieser Aktion verfügt.

Ein Server wird mit demselben developerSecretKeyauthentifiziert, wodurch dieser Prozess als Titelentität identifiziert wird. Ein Titel umgeht die Rollenüberprüfungen, und api-Aufrufe, die von einem Titel ausgeführt werden, schlagen nur fehl, wenn die Aktion nicht ausgeführt werden kann, in einem instance z. B. wenn eine Entität nicht entfernt werden kann, wenn sie kein Mitglied sind.