En los juegos multijugador, los equipos de jugadores compiten o colaboran para lograr algún objetivo. El número de jugadores de cada equipo puede tener efectos radicales en la jugabilidad y muchos desarrolladores eligen proporciones concretas de jugadores para crear experiencias agradables.
El equilibrio de equipos divide a los jugadores en equipos siguiendo una proporción diseñada. La mayoría de los juegos multijugador equilibran los equipos de forma equitativa para que ninguno tenga ventaja. Algunos juegos crean intencionadamente escenarios desequilibrados, como enfrentar a cuatro jugadores contra un jugador superpoderoso. Independientemente de la configuración, el equilibrio de los equipos es fundamental para crear experiencias interesantes para varios equipos de jugadores.
Al completar esta guía, aprenderás a equilibrar dinámicamente los equipos de jugadores en tiempo de ejecución y siempre que se una un nuevo jugador a la partida. La secuencia de comandos completa se incluye al final de esta guía como referencia.
Funciones del lenguaje Verse utilizadas
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 está actualmente un jugador.
for: con la expresión for, puedes recorrer en iteración las matrices que utiliza el dispositivo.
if: la expresión if se utiliza para comprobar si los jugadores deben pasar 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 para controlar el flujo del programa.
API de Verse utilizadas
Suscribible: te suscribirás a
PlayerAddedEvent()para reequilibrar dinámicamente los equipos cuando un jugador se una a una partida en curso.Teams: la clase team añade, elimina y recupera jugadores de los equipos. En este tutorial utilizarás la clase `team` para manipular directamente a los jugadores y sus asignaciones de equipo.
Playspace: el espacio de juego realiza un seguimiento de los eventos subscribable relacionados con la entrada y salida de jugadores. También se encarga de recuperar listas de jugadores y equipos, y de encontrar el equipo de un jugador determinado. En este tutorial, te suscribirás a varios eventos del espacio de juego y recuperarás jugadores y equipos utilizando métodos del espacio de juego para poder manipularlos directamente.
Cómo configurar el nivel
Este ejemplo utiliza el siguiente dispositivo.
Cuatro dispositivos plataforma de aparición de jugador: este dispositivo establece dónde aparecerá el jugador al inicio de la partida.
Sigue estos pasos para configurar tu 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 Detalles .
En el panel Detalles, en Opciones de usuario:
Establece Equipo del jugador en Índice del equipo con un valor de 1.
Habilita Visible en partida.
Haz clic en la imagen para ampliarla.
Duplica la plataforma de aparición y colócala junto a la primera.
Duplica ambas plataformas de aparición y colócalas más 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 Detalles, en Opciones de usuario, cambia el valor de Índice del equipo a 2 para ambas.
En el esquematizador, selecciona el dispositivo Configuración de la isla para abrir su panel de detalles. En Opciones de usuario, reglas del juego:
Establece Equipos en Índice del equipo con un valor de 2. Este ejemplo utiliza dos equipos, pero puedes tener cualquier número.
Establece el tamaño del equipo en dinámico. Esto significa que tu código de Verse puede hacerse cargo del equilibrio del equipo.
Establece Unión en curso en Aparecer para que los nuevos jugadores puedan unirse al juego mientras se está ejecutando.
Haz clic en la imagen para ampliarla.
Crea un nuevo dispositivo de Verse llamado team_multiplayer_balancing utilizando el explorador de Verse y arrástralo hasta el nivel. (Si quieres más información sobre cómo crear un nuevo dispositivo en Verse, consulta Cómo crear tu propio dispositivo con Verse).
Tu nivel debería parecerse a esta configuración:
Cómo dividir los equipos por igual
Cómo equilibrar los equipos al inicio de la partida
Este paso muestra cómo dividir a los jugadores en equipos de forma equitativa al inicio de una partida y cuando un nuevo jugador se une a la partida.
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 la clase
team_multiplayer_balancing, añade una matriz de variablesteamllamadaTeamsque almacenará referencias a cada equipo en el que estén los jugadores.Verseteam_multiplayer_balance := class(creative_device): # Holds the teams found with GetTeams() var Teams : []team = array{}En la función
OnBegin(), actualiza la matrizTeamspara que coincida con los equipos configurados anteriormente en Ajustes de la isla. Llama a la funciónGetTeams()de la APIfort_team_collectionpara obtener todos los equipos del espacio de juego.VerseOnBegin<override>()<suspends>:void= Print("Verse Device Started!") set Teams = Self.GetPlayspace().GetTeamCollection().GetTeams()Encuentra a todos los jugadores del juego llamando a la función
GetPlayers()y guárdalos en una matriz de jugadores nombradaAllPlayers.VerseOnBegin<override>()<suspends>:void= Print("Verse Device Started!") set Teams = Self.GetPlayspace().GetTeamCollection().GetTeams() AllPlayers := GetPlayspace().GetPlayers()Recorre 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 más adecuado para ese jugador. En este caso, puedes utilizar el equipo al que se asigna automáticamente un jugador cuando comienza la partida utilizando
GetTeam[](ya 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 tipo agent, pero como jugador es una subclase de agent, puedes pasar un jugador sin casting de tipo.VerseAllPlayers := GetPlayspace().GetPlayers() for (TeamPlayer : AllPlayers, CurrentTeam := GetPlayspace().GetTeamCollection().GetTeam[TeamPlayer]): # Assign Players to a new team if teams are unbalancedComo `team` es una clase interna, no puede inicializarse y solo puede utilizarse como referencia a un objeto `team` existente.
Quieres asignar jugadores al equipo con menos jugadores hasta que todos los equipos estén equilibrados. Para ello, tienes que comprobar cada jugador y luego cada equipo mediante un bucle
for. Podrías utilizar 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 del equipo en su propio método. Configura el bucle for del jugador obteniendo una referencia a cada jugador y luego una referencia a cada equipo en el que esté en una constante nombradaCurrentTeam.Crea una nueva variable entera
TeamSizee inicialízala a0; luego establece que sea igual al tamaño del equipo en el que está actualmente este jugador. ComoGetAgents[]es una expresión falible, tienes que encerrar este conjunto en una sentencia 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
ToggleStasisForAllPlayers(). Devolverá un equipo opcional (?team) cuando se le paseTeamSizecomo argumento y se encargará de encontrar y devolver el equipo con el menor número de jugadores. Inicializa una nueva opción de equipo con el nombre establecido enSmallestTeamdentro deFindSmallestTeam(). Aquí utilizarás una opción porque un jugador puede estar ya en el equipo más pequeño cuando llames aFindSmallestTeam().Como tu opción
SmallestTeamtiene false como valor predeterminado, seguirá siendofalsesi no se encuentra ningún equipo más pequeño. SiFindSmallestTeam()devuelvefalse, sabrás definitivamente que el jugador ya estaba en el equipo más pequeño. También tienes que inicializar una variable intCurrentTeamSizecon el valor deTeamSize. Necesitas queCurrentTeamSizesea variable para poder actualizarlo al tamaño de cualquier otro equipo que encuentres con menos jugadores.VerseFindSmallestTeam(CurrentTeamSize : int) : ?team= var SmallestTeam : ?team = false var TeamSize : int = CurrentTeamSizeComo
TeamSizeregistra el tamaño deSmallestTeam, tienes que compararlo con el tamaño de cada equipo. Iterar a través de cada equipo y obtener su tamaño en un int localCandidateTeamSize. SiCandidateTeamSizees menor queTeamSize, estableceSmallestTeamen este equipo yTeamSizeen el tamaño de ese equipo.La condición
TeamSize > CandidateTeamSizees una condición de filtro porque se comprueba dentro del paréntesis del bucle for. Utilizar una condición de filtro garantiza que el código dentro de tu bucle se ejecute solo si la condición de filtro tiene éxito. Esto garantiza queSmallestTeamse establecerá en el equipo con menos jugadores si se encuentra alguno. Si no se encuentra ningún equipo con menos jugadores,SmallestTeamseguirá siendo false.Por último, devuelve
SmallestTeamuna vez comprobados 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 nombradaSmallestTeamdentro del buclefore inicialízala con el valor deFindSmallestTeam()cuando transfieraTeamSizecomo argumento.VerseSmallestTeam : ?team = FindSmallestTeam(TeamSize)A continuación, intenta acceder al valor de la variable opcional
SmallestTeam. Si el valor es false, el jugador ya estaba en el equipo más pequeño y no es necesario asignarlo. De lo contrario, deberás asignar al jugador a su nuevo equipo. Como muchos métodos no nos permiten pasar directamente una opción como argumento, tienes que extraer el valor a una variable localTeamToAssign. Puedes intentar asignar un jugador a este equipo utilizandoAddToTeam[jugador, equipo]. Ten en cuenta que esta asignación fallará si intentas asignar un jugador a un equipo en el que ya está. Sin embargo, esto no tendrá ningún efecto negativo, ya que el bucleforsolo iterará al siguiente jugador y dejará al primero en su equipo original.Verseif (TeamToAssign := SmallestTeam?, GetPlayspace().GetTeamCollection().AddToTeam[TeamPlayer, TeamToAssign]): Print("Attempting to assign player to a new team")
OnBegin()debe parecerse al bloque de código siguiente.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 un jugador que se incorpora a mitad de partida
Como también quieres poder equilibrar automáticamente los equipos de una partida en curso, tendrás que suscribirte al evento que se active cuando se una un nuevo jugador. Como no quieres repetir todo el código que acabas de escribir, puedes refactorizarlo en un método común.
Crea un método nombrado
BalanceTeams()y mueve todo el código de después de establecer la variableTeamsmedianteGetTeams(). Se llama en el métodoOnBegin()para que los equipos estén equilibrados cuando empiece el juego.BalanceTeams()debería parecerse a esto.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 nombrado
OnPlayerAdded()que contenga una llamada aBalanceTeams(). Aunque no utilizarás la variableplayer, la definición del método la requiere, ya que te suscribes aPlayerAddedEvent()mediante este método. Consulta la página Codificación de las interacciones de los dispositivos si quieres más información sobre los eventos subscribibles.VerseOnPlayerAdded(InPlayer : player) : void = Print("A new Player joined, assigning them to a team!") BalanceTeams()En
OnBegin(), suscríbete alPlayerAddedEvent()utilizandoOnPlayerAdded. Ahora, cuando un jugador se una 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 secuencias de comandos de Verse para compilar tu secuencia de comandos.
Haz clic en Abrir sesión en la barra de herramientas de UEFN para probar el nivel.
Cuando pruebes tu nivel, deberías ver el tamaño de cada equipo, así como los equipos más pequeños que encuentre la secuencia de comandos en el registro de salida. Los jugadores deben estar equilibrados entre los equipos y un nuevo jugador que se incorpore al juego debe mantener este equilibrio.
Secuencia de comandos completa
El código siguiente es la secuencia de comandos completa para un dispositivo que equilibra automáticamente 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, habrás aprendido a crear un dispositivo que equilibra automáticamente los equipos de jugadores utilizando Verse.
Con lo que has aprendido, intenta crear equipos intencionadamente desequilibrados para modos de juego asimétricos, como un jugador contra cuatro jugadores.