Aprende a implementar un Singleton en tu videojuego para mantener un único “jefe” que coordine estados sin conflictos. Con una variable static y una inicialización en awake, podrás asegurar que solo exista una instancia de tu GameManager, accesible desde cualquier script mediante su shared instance.
¿Qué es un singleton y por qué evita conflictos?
Un Singleton garantiza que solo haya una instancia de una clase en todo el juego. Si tuvieras dos managers, uno podría decir “pausa” y otro “en partida”: conflicto asegurado. Con un único GameManager, todos los sistemas obedecen la misma autoridad.
Una sola instancia compartida por todo el juego.
Evita estados contradictorios: menú, pausa, in game.
Acceso global y simple a variables comunes.
¿Cómo se declara con static?
La clave es usar una variable static del mismo tipo del script. Así representas la instancia única y compartida.
publicstaticGameManager sharedInstance;
static: indica instancia única compartida.
sharedInstance: hace explícito que es la instancia compartida.
¿Qué ocurre al inicializar en awake?
El primer manager que “se despierte” en awake será el que gobierne. Si accidentalmente hay dos o más, solo el primero tomará el control.
voidAwake(){if(sharedInstance ==null){ sharedInstance =this;// yo soy la instancia compartida}}
Control seguro con if: evita reasignaciones.
El resto de copias quedan inactivas como managers.
¿Cómo se usa shared instance desde otros scripts?
Cualquier clase puede modificar el estado del juego accediendo a la sharedInstance del manager. Por ejemplo, desde un Player Controller, al detectar que el personaje toca el suelo en IsTouchingTheGround, actualizas el estado:
currentGameState público: accesible desde otros scripts sin problemas.
Comunicación directa y clara con el manager.
¿Cómo se prueba y qué casos prácticos cubre?
Puedes comprobar el cambio de estado al darle a play: por defecto estás en menú y, al tocar el suelo, pasas a ingame a través de la instancia compartida. Verás el cambio en pantalla y confirmarás que el Singleton funciona.
Flujo típico: menú → toca suelo → ingame.
Cambios orquestados por el GameManager único.
¿Qué beneficios aporta para comunicación entre clases?
Usar un Singleton permite notificar eventos importantes sin acoplar clases entre sí. El manager puede llevar el tracking de todo.
“He muerto”: el manager actualiza el estado y estadísticas.
“He tocado el suelo”: el manager avanza el juego.
“He ganado una moneda”: el manager suma y registra.
¿Cuándo usar singleton en player controller?
Si el juego es de un jugador, tiene sentido convertir el Player Controller en instancia compartida: una variable static y su asignación en awake.
Un solo jugador: un solo Player Controller compartido.
Misma lógica que en GameManager: static + awake + if.
¿Qué pasa si hay dos jugadores o más?
En un juego tipo “Mario y Luigi”, un Singleton para Player Controller no encaja: si mueves a Mario, podrías estar moviendo a Luigi también.
Dos jugadores: cada uno requiere su propia instancia.
Un singleton aquí puede mezclar controles y estados.
Reflexiona y elige diseño según número de jugadores.
¿Tú cómo lo implementarías en tu proyecto: Player Controller como singleton en single player y múltiple instancia en multijugador? Comparte tu razonamiento y resultados en los comentarios.
Ya que nuestro videojuego es de un solo jugador, ¿tiene sentido convertir el script PlayerController en Singleton?
Yo creo que si tiene sentido, es decir el programa podrá correr de igual manera. Pero sería impractico.
Si nuestro videojuego fuera multijugador, ¿tendría sentido convertir el script PlayerController en Singleton?
No tendria sentido, debido a que solo exisitiria una sola instancia de la clase y cada jugador necesitaria tener su propia instancia con sus propiedades unicas, como la respuesta a los diferentes inputs. Si se lo implementara, los players (1,2,...,n) tendrian exactamente el mismo comportamiento.
Eso es lo que entendí, por favor corrijanme si me equivoco.
Ya que nuestro videojuego es de un solo jugador, ¿tiene sentido convertir el script PlayerController en Singleton?
Yo diria que no ya que no habria otros scripts con los cuales chocar, de otra forma, no hya mas clases o metodos que interfieran
Si nuestro videojuego fuera multijugador, ¿tendría sentido convertir el script PlayerController en Singleton?
Ahi si, ya que el segudo jugador tiene sus propios controles y bien podria pausar su partida o bien saltar, por ejemplo en super contra son dos controles, el singleton es necesario para que cuando el jugador 1 salte, el jugador 2 se quede quieto
es lo que entiendo
Hola, creo que estas invirtiendo un poco el concepto del Singleton.
A mi parecer, que el juego de un solo jugador indica que nuestro Player puede ser un Singleton, ya que va a existir una sola instancia del mismo, y todos deberían acceder a esa única instancia.
El caso de un juego con varios Players, daría lugar a que no se implemente el Singleton, ya que pueden existir varias Instancias del Player y no queremos que sean la misma.
Saludos!
Si tiene sentido que nuestro player sea una instancia compartida o singleton además si existe un player2 que sea solo un acompañante y que haga los mismos movimientos que el player1 tiene sentido que sea un singleton. pero si el player2 realiza acciones independientes al player1 como apoyar disparando tomar ciertas acciones independientes, recoger por aparte monedas, medicina es necesario que exista un playerController aparte para el player2, no puede ser singleton.
<using System.Collections;using System.Collections.Generic;using UnityEngine;publicenumGameState{ menu, inGame, gameOver
}publicclassGameManager:MonoBehaviour{publicGameState currentGameState =GameState.menu;publicstaticGameManager sharedInstance;voidAwake(){if(sharedInstance ==null){ sharedInstance =this;}}// Use this for initializationvoidStart(){}// Update is called once per framevoidUpdate(){if(Input.GetKeyDown(KeyCode.S)){StartGame();}}publicvoidStartGame(){SetGameState(GameState.inGame);}publicvoidGameOver(){SetGameState(GameState.gameOver);}publicvoidBackToMenu(){SetGameState(GameState.menu);}privatevoidSetGameState(GameState newGameSate){if(newGameSate ==GameState.menu){//TODO: colocar la lógica del menú}elseif(newGameSate ==GameState.inGame){//TODO: hay que preparar la escena para jugar}elseif(newGameSate ==GameState.gameOver){//TODO: preparar el juego para el Game Over}this.currentGameState= newGameSate;}}>
Estoy en las mismas, si pudiste averiguar, me avisas
Me paso lo mismo, lo solucione haciendo un include en el archivo Assembly-CSharp.csproj que lo visualizo facilmente en el VS code:
Agregando la siguiente linea de codigo:
<Compile Include="Assets\Scripts\GameManager.cs" />
Abajo del PlayerController que si esta incluido por defecto:
Y ahi reconoce la clase sin problemas.
Creo que ese es el problema que tienen espero sirva si no lo solucionaron aun.
(Me quedo con la duda por ahora de porque exactamente pasa eso, si alguien tiene una explicacion seria util para futuros proyectos en C# y Unity. )
No entiendo por que dentro de una clase instanciamos un objeto de esa misma clase del tipo static...no seria mas sencillo y lógico declarar la propia clase como estática? Según yo tendría la misma utilidad.
Hola Diego, esa es la manera en la que funciona el patrón de diseño singleton que se utiliza para cuando queremos tener una única instancia de algo. Si bien pudieras hacerlo con una clase static sería mucho más tedioso para asegurarte de siempre estar trabajando con el mismo objeto sin conflicto de instrucciones
Te agradezco mucho por tu aporte massimokris :D
Cuando quiero probar lo del inGame y menu, mi personaje una vez que llega al suelo se congela en la animacion de salto. y en unity me sale este error: NullReferenceException: Object reference not set to an instance of an object
playerController.IsTouchingTheGround () (at Assets/Scripts/playerController.cs:45)
playerController.Update () (at Assets/Scripts/playerController.cs:26)
Ya lo resolví, me falta una mayúscula lpm. Horas de mi vida desperdiciadas.
No es tiempo perdido ... aprendiste !
Como el juego es de un solo player tiene sentido usar SINGLEton.
Si fuese para mas de uno, no, porque precisas una instancia del script para cada player, y con singleton no se podria instanciar, asi que no. Ademas mario y luigi, si cada uno crea una instancia del mismo script en una sola pc si habria conflicto al moverse, tendria que modificarse para que cada uno tenga una seleccion de teclas asignadas, si fuese un multiplayer online, ya cambia, cada player tiene su instancia del script y al tener una pc por player no hay conflicto ya que cada uno mueve un gameObject distinto. :)
Por cada terminal debe haber un jugador, pero si hay dos jugadores o más hay que ver la forma de separar cada grupo de inputs dentro de la misma terminal es decir usar Player un player controller por jugador, sin embargo cómo lo que más se usa hoy en día son los multiplayers online, si tiene sentido usar Singleton para el Player Controller
Hola, mi personaje se queda congelado en el salto y en Unity salta el siguiente error:
Este es el código que puse en el PlayerController el cual muestra que esta mal, pero no logro detectar ¿Cuál es el error?
Este es el código del GameManager
5:21 Hola buenas tardes me podrian explicar esa linea de codigo , no la entendi bienn jsjsjs, Muchas gracias
El current game state por defecto está en menú cuando le da al Play y toca el suelo cambia a in game eso pasa porque puede acceder a su instancia compartida y a partir de ahí a sus variables.
A pesar de que el game state está declarado en otro script diferente, al hacerlo publico y fuera de la clase se puede acceder a los estados del juego sin ningún problema para notificar al mánager.
lo que hace es asignar el valor "ingame" a la variable "currentGameState" dentro de la referencia estatica "sharedinstance" dentro de la clase "GameManager"
con el GameManager es que se puede conocer cuantas veces uno muere en un juego o cuantas monedas a agarrado el personaje y poder interactuar con esos datos en el menu como por ejemplo comprar cosas con las monedas recolectadas?
Tu decides donde lo quieres llevar, pero para tener un orden es mejor que lo lleve el GameManager
también se pueden usar los PlayerPrefs de UNITY o guardarlo en algún fichero como JSON.
y si tuviera singleton el player , como quedaria el codigo?
Yo creo que si el juego de un sólo jugador, tiene sentido utilizar Singleton pero para el PlayerController.
Si es multijugador no tiene sentido porque habrán varios GameControlles a los que el juego tiene que hacer referencia.
Creo que en un juego multiplayer si seria necesario el Singleton, e indicarle al juego cual es nuestro jugador y a cual debemos llamar los métodos como saltar o caminar, porque si no usaramos singleton, y hubiese mas de un Player, los 2 Players reaccionarian con el mismo Input
Yo digo que si es necesario el singleton en el PlayerController pues así nos aseguramos que solo exista un personaje y que se creen otros.
Si fuera multijugador no seria necesario pues aquí si podemos tener distintas instancias de la clase solo cambiáramos los controladores pero con el mismo script.
ya que nuestro juego es de un solo jugador ¿tiene sentido cambiar el script de playerController en sigleton?
yo diria que no, ya que solo usaremos a un jugador y este hara todas las acciones, no lo veo necesario.
ahora que pasa si ¿el juego es de multijugador?
depende mucho a que ira orientado, si tienes muchos personajes dinstintos con distintos stats, si, ya que unos deben moverse mas rapido y otros mas lento, dado que si damos singleton todos se moverian igual si es que hay un bug, osea debe tener un sigleton para cada unico personaje para que se mueva independiente, aunque puede variar en implementacion y tipo de juego. si es solo una skin no hace falta o recolor del mismo pj.
¿Que estoy haciendo mal?
Al iniciar el juego mi personaje hace la animacion de salto y despues muere y me aparece el siguiente error, PlayerController.IsTouchingTheGround () (at Assets/Scripts/PlayerController.cs:87).
El simple echo que muera es raro, fíjate en como estas haciendo la lógica del método start del PlayerControle.cs, y el árbol de todos los métodos donde controlas la variable State_Alive.
El error lo tienes en el GameManager, si te fijas en el if del awake, tienes un solo signo de = y deben ser dos:
if(sharedInstance ==null){ sharedInstance =this;}
Si le dejas solo uno, le estás asignando el valor null, por eso te tira error al momento de querer modificar un valor.
Sé que es de más de un año, pero ojalá si a alguien le pasó le ayude.
Hay algo muy interesante con el profesor que logra simplicar los conceptos dados, no tanto por las analogías sino por la forma en la que explica los conceptos, por ejemplo el patron de diseño singleton que se da en otros cursos aquí se retoma y logra disipar varias dudas.
Ya que nuestro videojuego es de un solo jugador, ¿tiene sentido convertir el script PlayerController en Singleton?
Si, siempre que solo se vaya a manejar una instancia del jugador.
Si nuestro videojuego fuera multijugador, ¿tendría sentido convertir el script PlayerController en Singleton?
Considerando el multijugador local: No. Para poder reutilizar el player controller para los otros jugadores, si no haría falta un PlayerController1 , 2 ,3 ,4....