Noticias

¡RECUERDA QUE SI ERES UN NUEVO USUARIO, DEBES PRESENTARTE PARA PODER PUBLICAR MENSAJES! | TENEMOS CANAL OFICIAL DE TELEGRAM: t.me/unity3dspain

Singleton

Iniciado por juanma_teso, Agosto 04, 2016, 01:54:00 AM

Tema anterior - Siguiente tema
Hola a todos! He estado bastante ausente en el foro debido a exámenes y vacaciones, todavía queda un mes largo de descanso por delante y qué mejor que picar un poco de código jajaja. Espero poder mostrar algo de lo que tengo entre manos muy pronto, de momento tengo una parte de la mecánica del juego hecha, se trata de un juego de carreras, supongo que cuando tenga modelos y escenarios definidos habrá algo que mostrar. Siempre me enrollo, la duda en sí es acerca del singleton, tengo varios gestores, en los que pido y doy variables, como no suelo acceder constantemente a ellos y en algunos casos persisten entre escenas me ha parecido buena idea hacer uso del singleton, el problema (o no) es que voy acumulando varios (5-6) y no sé si esto perjudique el rendimiento. Gracias!!

En teoría a menos que me lo justifiques, con uno debería ser suficiente.

Agosto 04, 2016, 04:37:06 PM #2 Ultima modificación: Agosto 17, 2016, 01:34:14 AM por pioj
Entonces por esa respuesta entiendo que sí afecta al rendimiento?
 
Son varios gestores que se encargan de diferentes cosas y están en diferentes partes (servidor/cliente) por ejemplo los gestores que tengo en el servidor sólo se instancian en éste, de momento tengo 2 y estaba a punto de hacer un tercero pero decidí preguntar.
 
Debería hacer referencia para sólo usarlo al principio de una escena (lobby)? Para aclarar dudas y si me aconsejáis mejor dejo exactamente lo que estoy haciendo:
 

  •    Un gestor que se encarga de escoger el prefab que va a usar el jugador (cliente, se instancia al iniciar el juego y nunca se destruye, contiene un array con los prefabs cargados de resources).


  •    Un gestor que se encarga de diferenciar las escenas (lobby/partida) la llamo al iniciar el cliente en el servidor (servidor, cambia en cada escena).


  •    Un gestor que controla cuándo los jugadores están listos y cambia a la partida cuando todos lo están (servidor, sólo en el lobby).


Entonces claro, el caso es que son varios objetos(jugadores) accediendo siempre al mismo objeto(gestor).
 
Debería cambiar y buscar y poner referencia a los diferentes gestores? Gracias de nuevo!

no afectan el rendimiento, si quieres dividir el programa en singletones es mas para facilitarte o complicarte, segun el caso

En qué casos me pueden complicar, voy a poner un ejemplo de cómo lo estoy haciendo ya que estas cosas se aprenden con experiencia y de eso algunos tenéis bastante jajaja
 

public class Gestor : MonoBehaviour {
public static Gestor singleton;
int variable;
void Awake () {
   singleton = this;
}
public static int PedirNumero () {
   return singleton.variable;
}
}
public class Jugador : NetworkBehaviour {
int numero;
void OnStartServer () {
   numero = Gestor.PedirNumero ();
}
}

 
Así es como estoy haciendo, me parece que queda limpio y si no afecta al rendimiento entonces perfecto. Aclaro que no es parte de mi código, pero esa es la estructura.

lo veo bien, es un codigo sencillo
 
pero se puede complicar si divides mucho las cosas y luego tienes que estar pidiendo un moton de cosas entre objetos... como ese PedirNumero tendrias que hacer un metodo/getter para cada "cosita"...
 
luego si resulta que necesitas mas de 1 instancia te toca refactorizar todo el codigo

Si tienes razón, pero ese era un ejemplo, cuando necesito pasar varias variables y más de una vez hago una referencia.
 
Más de una instancia del gestor, dices?

sí, de cualquier singleton... pues me preguntabas en q casos se puede complicar: imagina q hago un juego lleno de singletones, luego resulta q necesito hacerlo a pantalla dividida, entonces de pronto necesito 2 de cada gestor... ahi se rompe el patron y toca refactorizar el codigo, ya sea q cada singleton contenga datos para cada jugador o usar multiples instancias...

Básicamente atente a la definición de Singleton, si tienes una serie de datos y necesitas de un elemento gestor único que los mueva o trabaje con ellos, eso esta pidiendo a gritos un Singleton. Lo suyo es tener tantos Singletons como "tareas de gestión independientes" haya. Si tienes diferentes datos o tareas para un gestor global de sonido, persistencia de datos etc etc, lo lógico es crear Singletons con responsabilidades bien definidas, no un MACROSINGLETONDELCOPON con 100000 lineas de código ilegibles.


En definitiva, no hay una respuesta clara de cuantos Singletons esta bien o esta mal, ni pocos ni muchos, los justos y necesarios según tu diseño (suponiendo que es un buen diseño).


Saludos.

No estoy de acuerdo. Un singleton para todo el app. Esta clase es para mantener la coherencia entre scenes y su carga, pero no para almacenar tropocientos recursos como sonidos o imágenes que al final no serán necesarios todos ellos para esa scene. Y por eso ha de ser pequeña.
 
Debe mantener datos de sesión del player, referencias a otros datos como url's de servicios e INSTANCIAR lo que se necesite para esa scene, y no ir acumulando. Si gestiona las scenes, sabe lo que debe cargar y eliminar cada vez que hay un cambio de ellas.

Estas diferentes opiniones es justo lo que buscaba... :)
 
En mi caso no todos los singletones/gestores se mantienen durante las escenas, pero sí son únicos y gestionan diferentes datos (gestionan la UI, cuando los jugadores están listos...), el único singleton que se mantiene desde el incio y durante todas las escenas es el que maneja los prefabs (coches), los tiene en un array y le pasa la referencia del GameObject a cada cliente para que instancie el coche elegido. Los otros singletones los tengo porque me facilitan bastante no tener la referencia a objetos que no uso tantas veces durante la ejecución de las escenas. Pero no sé hasta qué punto sea más eficiente usar una función estática que usar una función a un objeto referenciado.

Creo que hay que distinguir entre el desarrollo de un app cuando es un solo desarrollador a cuando hay más. Yo siempre he desarrollado pensando que más desarrolladores accederán al código, como en el trabajo o como yo dentro de un tiempo que no me acuerde de casi nada. Tener muchas clases static y singleton no encapsula mucho el código y son como un montón de piezas de un puzzle para montar algo, que no tienen un orden aparente.
 
Es decir, puedo llamar a una función static para un play de un sonido sin tener que inicializar otra clase o llamar a otra función antes? Si la respuesta es no, como puedo saber a qué tengo que llamar antes. A qué función o a qué clase. Si la respuesta es si, entonces posiblemente tenga demasiado código repetido de inicialización en esa función.
 
En una estructura de clases que se instancian, hay una serie de pasos que se deben cumplir. Sea por el constructor o por el Start/Awake al inicializar o por tener que pasarle como parámetro otras clases, que entonces ya sé que me obliga a instanciarlas.
 
Y todo esto sin hablar del consumo de recursos, ya que una static es global y un singleton tendrá el DontDestroyOnLoad.

En realidad las clases no son estáticas, son clases normales pero sólo se instancian una vez y tienen una referencia de la misma clase estática para que sea usado por el objeto dentro de sus funciones estáticas. Todos los gestores son inicializados en el Awake() y no se usan hasta funciones llamadas posteriores, el tema de la organización creo que lo llevo bien, lo que quería llegar era al tema del rendimiento, no se si sea un error o algo así usar un singleton cuando se destruye al finalizar la escena, tampoco sé hasta qué punto gasto recursos por no poner unas cuantas referencias.

Mídelo con el profiler. Es muy potente y permite acotar áreas y agruparlas por un nombre definido para visualizarlas mejor.

Si lo he mirado, pero no noto diferencias ni bajadas de frames cuando se llaman las funciones. He visto algunos test que usan bucles para repetir mil veces un proceso usando dos variantes, puede que cuando termine haga la prueba y la postee aquí.

Etiquetas: