En los juegos multijugador, los equipos de jugadores compiten o colaboran para lograr algunos objetivos. El número de jugadores de cada equipo puede tener efectos importantes en el juego; muchos desarrolladores escogen determinadas proporciones de jugadores para crear experiencias memorables.
El equilibrio de equipos divide a los jugadores en equipos según una proporción diseñada. La mayoría de los juegos multijugador equilibra los equipos uniformemente para que ningún equipo tenga ventaja. Algunos juegos intencionalmente crean escenarios desequilibrados, como hacer competir a cuatro jugadores contra un jugador con demasiado poder. Independientemente de la configuración, el equilibrio de los equipos es crucial para crear experiencias interesantes para múltiples equipos de jugadores.
Al completar esta guía, aprenderás cómo equilibrar equipos de jugadores dinámicamente en el tiempo de ejecución y siempre que un nuevo jugador se una al juego. La secuencia de comandos completa se incluye al final de esta guía como referencia.
Funciones usadas del lenguaje Verse
array: este dispositivo utiliza matrices para almacenar una referencia a cada equipo.
option: este dispositivo utiliza opciones para determinar si hay un equipo con menos jugadores que el equipo en el que se encuentra actualmente un jugador.
for: con la expresión for, puedes iterar sobre las matrices que utiliza el dispositivo.
if: la expresión if se utiliza para comprobar si los jugadores deben moverse a un nuevo equipo en función del tamaño de los equipos.
failure: los contextos de fallo se utilizan para acceder a las matrices y controlar el flujo del programa.
API de Verse usadas
Suscribible: suscribirás
PlayerAddedEvent()para reequilibrar de forma dinámica a los equipos cuando un nuevo jugador se une a un juego en curso.Equipos: la clase de equipo añade, elimina y recupera jugadores de los equipos. En este tutorial, usarás la clase equipos para manipular directamente jugadores y sus asignaciones a equipos.
Espacio de juego: en el espacio de juego, se realiza un seguimiento de los eventos suscribibles relacionados con los jugadores que se unen al juego o lo abandonan. También controla la recuperación de listas de jugadores y equipos y la búsqueda de un equipo para un jugador determinado. En este tutorial, te suscribirás a múltiples eventos del espacio de juego y recuperarás jugadores y equipos mediante métodos del espacio de juego para poder manipularlos directamente.
Configuración del nivel
Este ejemplo usa el siguiente dispositivo.
4 x Dispositivo de plataforma de aparición de jugador: este dispositivo define dónde generar al jugador al comienzo del juego.
Realiza estos pasos para configurar el nivel:
Añade una plataforma de aparición de jugador al nivel.
Selecciona la plataforma de aparición en el esquematizador para abrir su panel de detalles .
En el panel de detalles, en Opciones de usuario:
Establece Equipo del jugador en Índice del equipo con un valor de 1
Habilita Visible en el juego
Haz clic en la imagen para ampliarla.
Duplica la plataforma de aparición y colócala junto a la primera plataforma de aparición.
Duplica ambas plataformas de aparición y colócalas lejos del primer grupo de plataformas de aparición. Aquí es donde aparecerán los jugadores del equipo 2.
Selecciona las plataformas de aparición duplicadas y, en el panel de detalles de Opciones de usuario, cambia el valor de Índice del equipo a 2 en ambas.
En el esquematizador, selecciona el dispositivo de configuración de la isla para abrir su panel de detalles. En Opciones de usuario - Reglas del juego:
Establece Equipos en Índice de equipo con un valor de 2. Este ejemplo usa dos equipos, pero puedes tener cualquier número de equipos.
Establece Tamaño del equipo en Dinámico. Esto significa que el código Verse puede hacerse cargo del equilibrio de equipos.
Establece Unión en curso en Generar para que los nuevos jugadores puedan unirse a la partida mientras se está ejecutando.
Haz clic en la imagen para ampliarla.
Crea un nuevo dispositivo de Verse denominado team_multiplayer_balancing con el explorador de Verse y arrastra el dispositivo al nivel. (Para aprender a crear un nuevo dispositivo en Verse, consulta Cómo crear tu propio dispositivo con Verse).
El nivel debería ser similar a esta configuración:
Cómo dividir de forma equitativa los equipos
Cómo equilibrar los equipos al inicio de la partida
Este paso muestra cómo dividir equitativamente los jugadores en equipos al comienzo del juego y cuando se unen nuevos jugadores.
Abre el explorador de Verse y haz doble clic en team_multiplayer_balancing.verse para abrir la secuencia de comandos en Visual Studio Code.
En la definición de clase
team_multiplayer_balancing, añade una matriz variable deequipodenominadaTeamsque almacenará las referencias para cada equipo en donde estén los jugadores.Verseteam_multiplayer_balance := class(creative_device): # Holds the teams found with GetTeams() var Teams : []team = array{}En la
funciónOnBegin(), actualiza la matrizTeamspara que coincida con los equipos definidos con anterioridad en Configuración de la isla. Llama a la funciónGetTeams()de la APIfort_team_collectionpara juntar a todos los equipos en el espacio de juego.VerseOnBegin<override>()<suspends>:void= Print("Verse Device Started!") set Teams = Self.GetPlayspace().GetTeamCollection().GetTeams()Llama a la función
GetPlayers()para encontrar todos los jugadores en el juego y guárdalos en una matriz de jugadores denominadaAllPlayers.VerseOnBegin<override>()<suspends>:void= Print("Verse Device Started!") set Teams = Self.GetPlayspace().GetTeamCollection().GetTeams() AllPlayers := GetPlayspace().GetPlayers()Itera a través de la lista de todos los jugadores y crea equipos con el mismo número de jugadores. Compararás el equipo en el que está actualmente un jugador con cualquier otro equipo y determinarás si es el que mejor se adapta a dicho jugador. En este caso, puedes usar el equipo al que se asigna de forma automática un jugador cuando comienza el juego mediante
GetTeam[](debido a que los jugadores deben estar en un equipo en los modos de juego con varios equipos). Ten en cuenta queGetTeam[]requiere un parámetro de agente de tipo, pero, debido a que un jugador es una subclase de agente, puedes pasar un jugador sin proyección de tipo.VerseAllPlayers := GetPlayspace().GetPlayers() for (TeamPlayer : AllPlayers, CurrentTeam := GetPlayspace().GetTeamCollection().GetTeam[TeamPlayer]): # Assign Players to a new team if teams are unbalancedComo equipo es una clase interna, no puede inicializarse y solo puede usarse como una referencia a un objeto de equipo existente.
Debes asignar jugadores al equipo con la menor cantidad de jugadores hasta que todos los equipos estén equilibrados. Para hacer esto, necesitas verificar a cada jugador y, luego, a cada equipo usando un
buclefor. Podrías usar dos bucles for, uno para iterar a través de los jugadores y otro para iterar a través de los equipos pero, en este ejemplo, extraerás el bucle for de equipos en su propio método. Obtén una referencia a cada jugador para configurar el bucle for de jugadores y, luego, haz referencia a cada equipo en el que están en una constante llamadaCurrentTeam.Crea una nueva variable entera
TeamSizee inicialízala en0; luego, establécela igual al tamaño del equipo en el que está actualmente este jugador. Debido a queGetAgents[]es una expresión falible, debes encerrar este conjunto en una declaración if.Versefor (TeamPlayer : AllPlayers, CurrentTeam := GetPlayspace().GetTeamCollection().GetTeam[TeamPlayer]): # Assign Players to a new team if teams are unbalanced var TeamSize : int = 0 if(set TeamSize = GetPlayspace().GetTeamCollection().GetAgents[CurrentTeam].Length): Print("Size of this player's starting team is {TeamSize}")Crea un método denominado
FindSmallestTeam(). Esto devolverá un equipo opcional (?team) cuando se pasaTeamSizecomo un argumento, y se encargará de encontrar y devolver el equipo con la menor cantidad de jugadores. Inicializa una nueva opción de equipo llamadaSmallestTeamdentro deFindSmallestTeam(). Aquí usarás una opción porque es posible que algún jugador ya esté en el equipo más pequeño cuando llames aFindSmallestTeam().Dado que el valor predeterminado de la opción
SmallestTeames falso, permaneceráfalsosi no se encuentra ningún equipo más pequeño. SiFindSmallestTeam()devuelvefalse, sabes definitivamente que el jugador dado ya estaba en el equipo más pequeño. También debes inicializar una variable intCurrentTeamSizeal valor deTeamSize. Necesitas queCurrentTeamSizesea una variable para poder actualizarla al tamaño de cualquier otro equipo que encuentres con menos jugadores.VerseFindSmallestTeam(CurrentTeamSize : int) : ?team= var SmallestTeam : ?team = false var TeamSize : int = CurrentTeamSizeDado que
TeamSizerealiza un seguimiento del tamaño deSmallestTeam, debes compararlo con el tamaño de cada equipo. Itera a través de cada equipo y obtén su tamaño en unCandidateTeamSizeint local. SiCandidateTeamSizees más pequeño queTeamSize, estableceSmallestTeamen este equipo yTeamSizeen el tamaño de dicho equipo.La condición
TeamSize > CandidateTeamSizees una condición de filtro porque se verifica dentro de los paréntesis del bucle for. Al usar una condición de filtro se garantiza que el código dentro del bucle se ejecute solo si la condición de filtro tiene éxito. Esto garantiza queSmallestTeamse establezca como el equipo con la menor cantidad de jugadores si se encuentra alguno. Si no se encuentra ningún equipo con menos jugadores,SmallestTeampermanecerá falso.Finalmente, devuelve
SmallestTeamuna vez que se hayan verificado todos los equipos.Versefor(Team : Teams, CandidateTeamSize := GetPlayspace().GetTeamCollection().GetAgents[Team].Length, TeamSize > CandidateTeamSize): set SmallestTeam = option{Team} set TeamSize = CandidateTeamSize Print("Found a team with less players: {CandidateTeamSize}") return SmallestTeamEn
OnBegin(), crea una nueva opción de equipo llamadaSmallestTeamdentro del buclefore inicialízala con el valor deFindSmallestTeam()cuando se paseTeamSizecomo un argumento.VerseSmallestTeam : ?team = FindSmallestTeam(TeamSize)A continuación, intenta acceder al valor en la variable opcional
SmallestTeam. Si el valor es false, el jugador ya estaba en el equipo más pequeño y no es necesaria ninguna asignación. De lo contrario, es deseable que asignes al jugador a su nuevo equipo. Debido a que muchos métodos no permiten pasar una opción como argumento directamente, debes extraer el valor a una variable localTeamToAssign. Puedes intentar asignar un jugador a este equipo conAddToTeam[player, team]. Ten presente que esta asignación fracasará si intentas asignar un jugador a un equipo en el que ya está. No obstante, esto no tendrá ningún efecto negativo, ya que el bucleforiterará al siguiente jugador y dejará al primero en el equipo original.Verseif (TeamToAssign := SmallestTeam?, GetPlayspace().GetTeamCollection().AddToTeam[TeamPlayer, TeamToAssign]): Print("Attempting to assign player to a new team")
OnBegin()debería verse como el siguiente bloque de código.VerseOnBegin<override>()<suspends> : void = Print("Verse Device Started!") set Teams = Self.GetPlayspace().GetTeamCollection().GetTeams() Print("Beginning to Assign Players") Playspace := GetPlayspace() AllPlayers := Playspace.GetPlayers() for (TeamPlayer : AllPlayers, CurrentTeam := Playspace.GetTeamCollection().GetTeam[TeamPlayer]): var TeamSize : int = 0 if(set TeamSize = Playspace.GetTeamCollection().GetAgents[CurrentTeam].Length): Print("Size of this player's starting team is {TeamSize}")
Cómo controlar a un jugador que se une a una partida en curso
Como también deseas poder equilibrar equipos en un juego en curso, deberás suscribir al evento que se activa cuando se une un nuevo jugador. Como no deseas repetir todo el código que acabas de escribir, puedes refactorizarlo en un método común.
Crea un método denominado
BalanceTeams()y mueve todo el código después de definir la variableTeamsconGetTeams(). Esto se llama en el métodoOnBegin()para que los equipos se equilibren cuando se inicia el juego.BalanceTeams()debería tener el siguiente aspecto.VerseBalanceTeams() : void = AllPlayers := GetPlayspace().GetPlayers() for (TeamPlayer : AllPlayers, CurrentTeam := GetPlayspace().GetTeamCollection().GetTeam[TeamPlayer]): var TeamSize : int = 0 if(set TeamSize = GetPlayspace().GetTeamCollection().GetAgents[CurrentTeam].Length): Print("Size of this player's starting team is {TeamSize}") SmallestTeam : ?team = FindSmallestTeam(TeamSize) if (TeamToAssign := SmallestTeam?, GetPlayspace().GetTeamCollection().AddToTeam[TeamPlayer, TeamToAssign]): Print("Attempting to assign player to a new team")Crea otro método denominado
OnPlayerAdded()que contenga una llamada aBalanceTeams(). A pesar de que no usarás la variableplayer, la definición del método la requiere, ya que suscribirás aPlayerAddedEvent()con este método. Consulta la página Codificación de interacciones entre dispositivos para obtener más detalles sobre los eventos suscribibles.VerseOnPlayerAdded(InPlayer : player) : void = Print("A new Player joined, assigning them to a team!") BalanceTeams()En
OnBegin(), suscríbete aPlayerAddedEvent()medianteOnPlayerAdded. Ahora, cuando un jugador se une al juego,OnPlayerAddedllamará aBalanceTeams()para equilibrar automáticamente los equipos.VerseOnBegin<override>()<suspends> : void = GetPlayspace().PlayerAddedEvent().Subscribe(OnPlayerAdded) Print("Beginning to balance teams") BalanceTeams()Guarda la secuencia de comandos en Visual Studio Code y haz clic en Compilar código de Verse para compilar tu secuencia de comandos.
Haz clic en Comenzar sesión en la barra de herramientas de UEFN para realizar una prueba de juego del nivel.
Cuando pruebes el nivel, deberías ver el tamaño de cada equipo además de los equipos más pequeños que encuentre la secuencia de comandos impreso en el registro de salida. Los jugadores deberían estar equilibrados uniformemente en todos los equipos y cualquier jugador que se una al juego debería conservar este equilibrio.
Secuencia de comandos completa
El siguiente código es la secuencia de comandos completa de un dispositivo que equilibra automáticamente los equipos de jugadores.
using { /UnrealEngine.com/Temporary/Diagnostics }
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
team_multiplayer_balance := class(creative_device):
# Holds the teams found with GetTeams()
var Teams : []team = array{}
OnBegin<override>()<suspends> : void =
Print("Verse Device Started!")
Por tu cuenta
Al completar esta guía, has aprendido cómo crear un dispositivo con Verse que equilibra automáticamente los equipos de jugadores.
Con lo que has aprendido, intenta crear intencionalmente equipos desequilibrados para modos de juego asimétricos, como un jugador contra cuatro jugadores.