Viele Online-Spiele benötigen eine Art “Teams-System”, das die Clients in verschiedene Teams einteilen kann. Mit PUN 2 greifen Entwickler oftmals auf eigene Lösungen, was grundsätzlich auch nicht falsch ist, aber PUN 2 nimmt dir als Entwickler viel Arbeit ab. In PUN 2 ist nämlich ein solches System bereits integriert und sehr einfach zum Benutzen. Das ist der Teams Manager
, den ich heute vorstellen werde.
Ausser der
offiziellen API Referenz
zum Photon Teams Manager
existieren kaum Informationen über dieses äusserst hilfreiche System. Nachfolgend findest du eine aussführliche Erklärung über diese Funktion und eine Anleitung, wie man damit anfangs umzugehen hat.
Importieren des PUN 2 Assets
Die Reise beginnt ganz am Anfang beim Importieren des PUN 2 Assets. Dabei musst du darauf achten, dass du die nötigen Dateien importierst. Nebst all den anderen Dateien, die PUN 2 zwingend benötigt, gibt es auch einen Ordner namens “Utility Scripts”. Genau da findest du die benötigten Dateien für das Teams System. Es gibt natürlich auch andere “Utility Scripts”, die aber nicht zwingend nötig sind für den Zweck, den wir hier verfolgen, jedoch kann es nicht schaden, wenn man diese auch importiert, da man sie zu einem späteren Zeitpunkt eventuell brauchen könnte.
Diese Dateiens sind sehr wichtig, wenn man den Teams Manager verwenden möchte.
Einrichten des Teams Managers
Zuerst brauchst du einen Photon Teams Manager
in deiner Szene, welches ein C# Mono Behaviour Skript (eine Klasse, die von MonoBehaviour
erbt) ist. Du solltest diese Komponente an ein Objekt hängen, das konstant in der Szene ist und nicht instanziiert oder zerstört wird, sondern immer da, aktiv und von Anfang an in der Szene ist.
Dann kannst du Teams erstellen. Du kannst jedem Team, das du erstellst, einen Namen und einen Code geben. Der Code kann von 0 bis 255 gehen. Also kannst du theoretisch 256 Teams haben.
So sähe dein Photon Teams Manager mit 2 Teams (Rot und Blau) aus:
Das allererste, was du in deinem Code, in welchem du das System irgendwie benutzen möchtest, machen solltest, ist, den Photon.Pun.UtilityScripts
Namespace zu importieren. Da du höchstwahrscheinlich auch mit anderen PUN 2 Klassen und ihren Membern arbeiten wirst, empfiehlt es sich, auch den Photon.Pun
Namespace zu benutzen. Aus Erfahrung kann ich sagen, dass dies praktisch immer erforderlich ist, wenn du mit PUN 2 arbeitest.
Dann brauchst du eine Referenz zur PhotonTeamsManager
Komponente in der Szene. Wir werden ein “privates” (private
) Feld vom Typ PhotonTeamsManager
benutzen. Dazu verwenden wir noch das [SerializeField]
Attribut, um es im Inspector anzeigen zu lassen.
[SerializeField] private PhotonTeamsManager teamsManager;
Danach solltest du die Referenz per “Drag and Drop” in das Feld ziehen, das in der Zwischenzeit im Inspector erschienen ist.
Nun kannst du Spielern Teams zuweisen; sowohl dir selbst als auch anderen. So ist der Master Client beispielsweise dazu in der Lage, allen anderen Clients ein Team aufgrund von beliebigen Kriterien zuzuweisen.
Tipps und Tricks
Zuerst gibt es ein paar Dinge klarzustellen. Es gibt einige Klassen, denen du hier oft begegnen wirst.
Einerseits ist es die bereits erwähnte
PhotonTeamsManager
Klasse, die, wie es der Name schon sagt, als eine Art zentraler Manager für die Teams fungiert.Dann gibt es auch die
PhotonTeam
Klasse, die ein Team darstellt. Dabei enthält es Informationen, wie den Namen vom Team und den Code.Zuletzt ist hierbei auch die
Player
Klasse ein wichtiger Faktor. Dies ist eine Klasse, die im NamespacePhoton.Realtime
enthalten ist. Diese Klasse stellt einen Client/“Spieler” dar und ist nicht spezifisch für das Teams System geschaffen worden, sondern existiert auch ausserhalb davon, wie man es von dessen Namespace erraten kann.
Hinweis
Alle Methoden, die mit Try
beginnen, wie zum Beispiel TryGetTeamByName
oder TryGetTeamMembers
, tun genau das, was der Name auch verrät. Sie versuchen, etwas bestimmtes zu tun. Diese Methoden haben einen bool
Rückgabewert. Somit kann man diese Methoden in einer if-Abfrage benutzen und wenn diese false
zurückgibt, ist die Aktion gescheitert. Somit kann man den Code, der von einer erfolgreichen Aktion abhängt, innerhalb dieser if-Abfrage platzieren und nur ausführen, wenn die Methode erfolgreich ausgeführt wurde.
Damit entgeht man Fehlermeldungen und Sachen, die den reibungslosen Ablauf des Programmes behindern.
PhotonTeam Instanz
Du kannst jedes Team in einer PhotonTeam
Variable speichern, also jedes Team kann sozusagen durch eine PhotonTeam
Instanz ausgedrückt werden.
Informationen über das Team
Du kannst den Namen oder den Code von jedem Team mit Name
für den Namen und Code
für den Code erhalten. Also kannst du so den Code oder Namen einer PhotonTeam
Referenz bekommen.
Team eines Clients abfragen
player.GetPhotonTeam()
Du kannst das Team eines Spielers/Clients mit player.GetPhotonTeam()
abfragen, was eine PhotonTeam
Referenz zurückgeben wird. Jetzt kannst du zum Beispiel die Teams zweier Spieler/Clients vergleichen, den Code bekommen, irgendetwas anzeigen aufgrund des Teams oder sonst etwas. Das Team von sich selbst (dem lokalen Client), kannst du natürlich mit PhotonNetwork.LocalPlayer.GetPhotonTeam()
kriegen. Es ist nur wichtig, dass du eine Player
Referenz hast, von der du das Team abfragen kannst.
Team beitreten
player.JoinTeam(string teamName)
player.JoinTeam(byte teamCode)
player.JoinTeam(PhotonTeam team)
Du kannst jeden Spieler/Client einem Team zuordnen mit: player.JoinTeam()
, dabei übergibst du entweder den Namen des Teams (als string
), den Code als byte
oder das Team als PhotonTeam
Instanz als Parameter. Dabei muss player
, wie in diesem Beispiel benutzt, eine Referenz zu einer Player
(Photon.Realtime.Player
) Instanz sein.
Hierzu noch einige Beispiele, wie man dies in der Praxis benutzt.
PhotonNetwork.LocalPlayer.JoinTeam("Blue"); // Der EIGENE Client tritt dem Team "Blue" bei, falls dieses vorhanden ist
PhotonNetwork.LocalPlayer.JoinTeam(1); // Der EIGENE Client tritt dem Team mit dem Code 1 bei, falls vorhanden
Nun werde ich noch ein praxisnahes Beispiel aufführen, das bei einer Kollision mit einem Objekt, das den Tag “Player” trägt, den eigenen Client dem selben Team, dem der Spieler, mit dem man kollidiert ist, zugehört, beitreten lässt. In diesem Beispiel ist wichtig zu wissen, dass sowohl PhotonNetwork.LocalPlayer
als auch die nicht-statische Owner
Eigenschaft der PhotonView
Klasse eine Player
Referenz zurückgeben. Daher solltest du dich durch die langen Teile davor nicht verwirren lassen, denn dieses Vorgehen funktioniert mit jeder Player
Referenz genau gleich.
void OnCollisionEnter(Collision collision) // Wird beim Zusammenstoss mit einem anderen Collider aufgerufen (3D)
{
Transform otherObject = collision.transform; // Referenz zur `Transform` Komponente des Objektes, mit dem man zusammengestossen ist
if(otherObject.CompareTag("Player")) // Überprüfe, ob dieses Objekt den Tag "Player" besitzt
{
// Referenz zum Team des Clients (Zugriff auf Client durch Referenz zur `PhotonView` Komponente)
PhotonTeam team = otherObject.GetComponent<PhotonView>().Owner.GetPhotonTeam();
PhotonNetwork.LocalPlayer.JoinTeam(team); // Der EIGENE Client tritt dem Team des anderen Clients, mit dessen Objekt man zusammengestossen ist, bei
}
}
Die Anzahl Clients in einem Team
teamsManager.GetTeamMembersCount(string teamName)
teamsManager.GetTeamMembersCount(byte teamCode)
teamsManager.GetTeamMembersCount(PhotonTeam team)
Du kannst die Anzahl Clients in einem Team mit teamsManager.GetTeamMembersCount()
herausbekommen, wobei teamsManager
die Referenz zur PhotonTeamsManager
Komponente ist. Diese Methode erfordert wieder entweder einen string
für den Namen, einen nummerischen byte
Wert für den Code oder eine PhotonTeam
Referenz des Teams, dessen Anzahl Clients du erfahren möchtest, als Parameter.
Alle verfügbaren Teams
teamsManager.GetAvailableTeams()
Du kannst einen Array mit allen Teams mithilfe von teamsManager.GetAvailableTeams()
erhalten. Das ist dann ein PhotonTeam[]
(PhotonTeam
Array).
Team per Code erhalten
teamsManager.TryGetTeamByCode(byte teamCode, out PhotonTeam team)
Du kannst ein Team mit dem Code identifizieren. Dabei verwendet man die teamsManager.TryGetTeamByCode()
Methode, während sie einen byte
als ersten Parameter (für den Code, den du kennst) annimmt und eine PhotonTeam
out
-Referenz als zweiten Parameter. Denn was diese Methode buchstäblich macht, ist eine PhotonTeam
Referenz herauszugeben.
Zum Beispiel:
teamsManager.TryGetTeamByCode(1, out PhotonTeam team)
Nun kannst du diese neu erstellte lokale team
Variable verwenden.
Team per Name erhalten
teamsManager.TryGetTeamByName(string teamName, out PhotonTeam team)
Dasselbe mit dem Namen des Teams, nur mit teamsManager.TryGetTeamByName()
, während die Methode einen string
als ersten Parameter (für den Namen, den du kennst) annimmt und wieder eine PhotonTeam
out
-Referenz als zweiten Parameter. Denn was diese Methode buchstäblich macht, ist eine PhotonTeam
Referenz herauszugeben. Dieser Satz sollte dir schon bekannt vorkommen.
Zum Beispiel:
teamsManager.TryGetTeamByName("Blue", out PhotonTeam team)
Alle Spieler eines Teams
teamsManager.TryGetTeamMembers(string teamName, out Player[] players)
teamsManager.TryGetTeamMembers(byte teamCode, out Player[] players)
teamsManager.TryGetTeamMembers(PhotonTeam team, out Player[] players)
Man kann ebenfalls alle Spieler eines bestimmten Teams als Player[]
(Player
Array) erhalten. Dies ist mit der teamsManager.TryGetTeamMembers()
möglich. Diese nimmt als ersten Parameter entweder einen string
für den Namen, einen byte
für den Code oder eine PhotonTeam
Referenz an und der zweite Parameter ist wieder eine out
-Referenz, aber diesmal vom Typ Player[]
(Player
Array).
Beispiel:
teamsManager.TryGetTeamMembers(1, out Player[] players);
teamsManager.TryGetTeamMembers("Blue", out Player[] players);
teamsManager.TryGetTeamMembers(team, out Player[] players); // `team` ist hierbei eine `PhotonTeam` Instanz
Alle Mitspieler eines Spielers
teamsManager.TryGetTeamMatesOfPlayer(Player player, out Player[] teamMates)
Es gibt auch die Möglichkeit, alle Mitspieler eines Spielers/Clients zu erhalten, also alle Spieler, die neben diesem im selben Team sind. Dazu braucht man lediglich eine Player
Instanz, die man als ersten Parameter der teamsManager.TryGetTeamMatesOfPlayer()
Methode übergibt. Der zweite Parameter ist wieder eine out
-Referenz und erneut vom Typ Player[]
(Player
Array).
teamsManager.TryGetTeamMatesOfPlayer(player, out Player[] mates);
Wie du siehst, ist der Teams Manager von PUN 2 überhaupt nicht kompliziert zum Benutzen und zudem auch sehr hilfreich. Es erleichtert einem Entwickler eine ganze Menge Arbeit und unterstützt diesen bei einer oft verwendeten Funktion in Online-Spielen.