[UNITY] El concepto del void Update()

marod

¡Hola a todos!

Últimamente estoy dudando de casi todo lo que programo en Unity a la hora de ver si es lo correcto en cuanto a programación, ya que estoy programando cositas pero al final no sabes si lo que haces, aunque funcione, lo estas haciendo bien.

Me llega el caso con el tema del Update, no me cabe en la cabeza el concepto de que a cada Frame se realice la acción que hay dentro del Update y que se repita una y otra y otra vez. Puede que sea una duda de programación muy simple, y creo que ya no la debería de tener.

Estoy programando un Game Manager para un prototipo de juego, en el que utilizo un Enum para definir los diferentes estados del juego, y tengo un Switch metido en el Update donde los casos son los del Enum.

La duda que tengo es el hecho de utilizar un switch en el Update y si esto es optimo y se hace así, pienso que a cada Frame se repite una y otra vez todo, aunque no me haga falta. Por ejemplo:

Tengo un canvas que cuando el estado es Game Over se activa y se muestra, pero claro, una vez activado y mostrado ya no me haría falta que entrara más en en ese switch, sin embargo sigue haciendo la linea de ShowMenu (GameOver, true), es decir que me sigue mostrando una y otra vez el menú a cada Frame hasta que algo cambie.

¿Qué me recomendáis que haga? ¿Me estoy volviendo paranóico? ¿Deberia quitar el Switch y el enum y utilizar lo mínimo el update?

void Update () {

	switch (gm) 
	{
	case GameState.Start:
		break;

	case GameState.inGame:
		
		if (Input.GetKeyDown (KeyCode.Escape) && !pause) 
		{
			pause = true;
			ShowMenu (Menu,true);
			Time.timeScale = 0;
		}
		else if(Input.GetKeyDown (KeyCode.Escape) && pause)
		{
			pause = false;
			ShowMenu(Menu,false);
			Time.timeScale = 1;
		}

		break;

	case GameState.GameOver:
		
		ShowMenu (GameOver, true);
		Time.timeScale = 0;

		break;
	}
		

}
Srednuht

#1 Lo que te he dicho por el grupo, tampoco te emparanoies.

En primer lugar, está claro que no es optimo sobrecargar el update de las funciones, pero psé, mucho tienes que hacer o cosas muy tronchas (generación de texturas muy grandes (o muchas) o mallas por ejemplo), para que tan solo un Update afecte a tu sistema.

Recuerda que el 'Profiler' es tu amigo. Primero que funcione bien, y luego que lo haga de la forma más optima posible. Si llegas a tener algun problema o si simplemente quieres mejorar el rendimiento de tu aplicación, con e profiler podrás detectar que tareas están sobrecargando el sistema y así podrás realizar las pertinentes tareas para optimizarlo todo bien.

1 respuesta
Cyph3r

Yo a modo de recomendación te diría que tengas un InputManager donde captures todos los eventos , keyDown , keyUp etc..

Y luego GameManager usa ese InputManager para gestionar las cosas.

Incluso para mí es mejor usar Eventos y GameManager está escuchando lo que necesita así tienes todo mas centralizado y evitas hacer check de keyDown en multiples sitios.

Por cierto tu código está bien para un Update todo lo que tienes ahí es nada. Con las cosas que tienes que vigilar son estructuras de datos , iterar , buscar elementos , etc.

1 1 respuesta
FernandoA

#1 Marod, te rayas demasiado la cabeza con estas cosas y no deberías. El código está bien y si te preocupa que se ejecute el método ShowMenu (); en cada iteracción mientras tengas pulsada la tecla puedes hacer algo tan simple como esto:

//En el método ShowMenu
this.menu = true;

//En el método para ocultar el menu
this.menu = false;

//En el switch
if (!this.menu && !this.pause && Input.GetKeyDown (KeyCode.Escape))

Tan simple como eso, así solo ejecutará el ShowMenu la primera vez (cuando no haya un menú mostrándose)

Por cierto, verás que he cambiado el orden de las condiciones en el if. Parece que muchos no lo saben pero ésto ayuda a mejorar el rendimiento del código. El operador && (al igual que el ||) sólo comprueba la primera condición que se le pasa, solo si se cumple comprueba la siguiente, pero si no ya la da como falsa directamente. Es lo que se llama short-circuiting y ahorra hacer comprobaciones innecesarias. Lo puedes ver aquí. Por eso mismo cambio el orden, en este caso comprobará primero si no tienes abierto un menú, si no es así (lo tienes ya abierto) ya no comprueba la tecla que tengas pulsada porque no importa ya que nunca ejecutará ese código con lo que solo hará una comprobación. Si el orden es al revés hará 2 comprobaciones en lugar de una, siendo la primera innecesaria al no cumplirse la segunda.

Vamos, personalmente te recomiendo que primero compruebes todas las condiciones que necesitas para saber donde se encuentra el jugador en ese punto concreto y que la última condición sea la tecla que está pulsando y no al revés.

1 respuesta
marod

Gracias a todos por las respuestas.

#2 Tiene razón, y me emparanoio facilmente por tener ansias de querer hacerlo todo bien, código limpio, legible y encima que funcione. Y muchas veces hago las cosas y aunque funcionen, siempre tengo la duda, de si será la mejor forma de hacerlo.

Es como comentaba por el grupo también, me siento como el mito de la caverna en cuanto a programación, hasta que no descubro una manera mejor, es posible que solo crea que vaya haber una forma de hacerlo, y por ende, esta forma puede estar mal.

#3 Me mirare el tema de Eventos en Unity porque no tengo ni zorra ni de como van ni de como utilizarlos.

#4 Si fuera por mi, metía booleans a todo, incluso hice por lo menos 2 ifs anidados en mi códico con 2 booleans para que una corrutina SOLAMENTE se realizar una vez dentro del Update, pero al final pienso, joder... tantos Booleans, esto es una chapuza o no debe de estar nada bien y volvemos a lo de... seguro que hay una forma mejor de hacerlo.

Lo de las condiciones no lo sabia para nada, así que me apunto ese consejo. Gracias

1 respuesta
Cyph3r

No uses eventos a nivel de Unity ya que a nivel de performance es muy lento.

Lo mejor es hacer una implementación de un Event Delegation . Por ejemplo : http://www.indiedb.com/games/coco-blast/tutorials/delegates-events-and-singletons-with-unity3d-c

Aunque hay mejores implementaciones o puedes hacer la tuya propia.

Yo por ejemplo en mi código en la mayoría de updates sólo tengo una linea o nada directamente. Yo uso una Maquina de estados y Coroutines para controlar todo.

FernandoA

#5 Ten en cuenta que los boolean son las variables que menos ocupan en memoria (solo un bite ya que solo se almacena o 0 o 1 binarios), así que usar muchos no es un problema, lo único en todo caso sería por la organización.

Y lo del orden no le des demasiada importancia, de hecho se nota que estaba ya medio dormido que lo puse al revés, sería más óptimo comprobar primero la pulsación del botón, pues será menos frecuente esa condición que las otras.

Básicamente, al realizar comprobaciones, el orden más óptimo sería:

  • Condición menos frecuente && condición más frecuente
  • Condición más frecuente || condición menos frecuente

El motivo es obvio, con el && solo si se da la condición menos frecuente de ambas realizamos las 2 comprobaciones, con el || al revés, solo se realizará la segunda comprobación si no se cumple la que es más frecuente que se de. De este modo se realizarán el menor numero de comprobaciones posibles.

En el caso de un switch se comprueban todos los cases uno tras otro hasta que encuentra el que coincida, por lo tanto, el orden ideal para realizar el menor número de comprobaciones posibles sería:

  • case muy frecuente
  • case poco frecuente
  • case raro
  • default

Así la mayor parte de las veces entrará en el primer case y solo pocas veces comprobará todos hasta llegar a los últimos. Lo mismo sería con ifs anidados. El default (al igual que el else) nunca debería ser la salida habitual si no la más extraña en darse, aunque muchas veces se utiliza al revés comprobando las excepciones y dejando como camino habitual el dafault/else (lo cual tampoco está mal).

De todos modos lo que se puede optimizar con ésto es escaso, salvo que tengas miles de casos en los que puede que se note algo. Hay muchas otras cosas que optimizar antes de tener que llegar a un extremo como éste, así que no le des ninguna importancia.

Usuarios habituales

  • FernandoA
  • Cyph3r
  • marod
  • Srednuht