Noticias

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

Duda del rendimiento de switch

Iniciado por Biarox1166, Febrero 17, 2017, 01:46:27 AM

Tema anterior - Siguiente tema
Hola de nuevo, hago este post por una duda que me surgió al implementar dos switch´s en mi script. La duda es simple, si tengo varios switch´s en una script me pueden afectar el rendimiento?(Por si sirve de algo un switch lo tengo en una void que se llama pocas veces y la otra en la void Update dentro de un if). Gracias de antemano, saludos!!

HOla, afectar el rendimiento no creo, depende de que tengas en los switch(condicion y cuerpo), podrias subir el  codigo para verlo mejor.
 
 

Hola @Biarox1166
 
No, un switch no consume nada y no te afectara de ningun modo al rendimiento ... incluso consume menos que una serie de if anidados (que es a lo que se podria comparar, aunque el if tampoco te consume para que baje el rendimiento) teniendo dos ventajas muy importantes: la primera y mas evidente a simple vista es que el codigo queda mucho mas limpio y organizado, la segunda ventaja pero no por ello menos importante es que solo consultas el valor a comparar una sola vez en el momento de entrar en el switch.
 
En desventaja con una serie de if anidados es que con el uso de if puedes hacer las comparaciones de cada "caso" tan complejas como quieras, incluso comparar distintas variables en cada condicional ... mientras que con el switch en todos los casos comparas siempre la misma variable con valores distintos.
 
P.D. aunque el switch no afecte al rendimiento, lo que contenga dentro de cada caso evidentemente claro que puede afectar ...

Gracias @Arthure!!!!! era una duda que me tenía, pero no subo el código, principalmente porque pude simplificar el código, pero por lo menos ya lo puedo tener en cuenta. Y ya que estoy... alguno me puede ayudar con un problema que me sucede con la UI?
 
Verán, tengo mi barra de vida la cual es una image(no utilice slider por ningún motivo en especial), y con su variable fill amount logré hacerla bien el tema está en que ahora quiero que si mi personaje agarra un power up de vida, esta se incremente un poco más(digamos la máxima). Quice hacer esto de mil maneras, busque en la scripting reference y demás y no puedo modificar el "width" del Rect de la imagen. Les dejo el codigo por si les sirve:
 

public Image HealthBar;
public float Health;
public float CurrHealth;
// Use this for initialization
void Start () {
   
}

// Update is called once per frame
void Update () {
   CurrHealth = (Health/100);            //hago esto porque fillAmount pide valores de entre 0 y 1
   HealthBar.fillAmount = CurrHealth;
   if(Input.GetKeyDown(KeyCode.Q)){               //esto lu utilizo para probrar en ves del power up
      HealthBar.rectTransform.rect.width = 200f;      //el 200 es un numero al azar que puse ahora
   }
   if (Health <= ){
      Health = ;
   }
}

 
y el error que me da: (24,33): error CS1612: Cannot modify a value type return value of `UnityEngine.RectTransform.rect'. Consider storing the value in a temporary variable.
 
en lo que creí entender primero es que me pedía que el valor que pusiese(en este caso el 200) fuese una variable y no algo temporal.
 
Pero no funcionó, y despues pensé que quizas se refería a almacenar el width del rect en una variable y ahi modificarlo pero ya no se como hacer eso : p

Para agregar aca dejo un link para comparar en assembly un If-else y un switch en C.
 
http://www.eventhelix.com/RealtimeMantra/Basics/CToAssemblyTranslation3.htm#.WKbEGn_b0dU
 
Basicamente el if else hace una comparacion o lo que le pongas dentro, y luego un salto cada vez que pasas por uno. Un switch define el numero etiquetas (los "case"), hace la comparacion y a partir de alli hace 1 solo salto. Como los saltos siempre son cruciales conviene hacer switch donde puedas. Claro que en algunos casos no es posible, los case de los switch admiten un cierto valor, no podes decir por ejemplo esto es mayor a esto?
 
En definitiva no es razon para cuestionar el rendimiento de un juego, para nada.
 
 
 
Cita de: Biarox1166 date=1487307080Gracias @Arthure!!!!! era una duda que me tenía, pero no subo el código, principalmente porque pude simplificar el código, pero por lo menos ya lo puedo tener en cuenta. Y ya que estoy... alguno me puede ayudar con un problema que me sucede con la UI?
   
   
      Verán, tengo mi barra de vida la cual es una image(no utilice slider por ningún motivo en especial), y con su variable fill amount logré hacerla bien el tema está en que ahora quiero que si mi personaje agarra un power up de vida, esta se incremente un poco más(digamos la máxima). Quice hacer esto de mil maneras, busque en la scripting reference y demás y no puedo modificar el "width" del Rect de la imagen. Les dejo el codigo por si les sirve:
   
   

public Image HealthBar;
public float Health;
public float CurrHealth;
// Use this for initialization
void Start () {
   
}

// Update is called once per frame
void Update () {
   CurrHealth = (Health/100);            //hago esto porque fillAmount pide valores de entre 0 y 1
   HealthBar.fillAmount = CurrHealth;
   if(Input.GetKeyDown(KeyCode.Q)){               //esto lu utilizo para probrar en ves del power up
      HealthBar.rectTransform.rect.width = 200f;      //el 200 es un numero al azar que puse ahora
   }
   if (Health <= ){
      Health = ;
   }
}

   
      y el error que me da: (24,33): error CS1612: Cannot modify a value type return value of `UnityEngine.RectTransform.rect'. Consider storing the value in a temporary variable.
   
   
      en lo que creí entender primero es que me pedía que el valor que pusiese(en este caso el 200) fuese una variable y no algo temporal.
   
   
      Pero no funcionó, y despues pensé que quizas se refería a almacenar el width del rect en una variable y ahi modificarlo pero ya no se como hacer eso : p
   


Son los tipicos casos que debes usar el new, como cuando seteas un Vector3 y pones: new Vector3(x,y,z)
 
proba algo asi:
 

RectTransform rectT;
void Start()
{
rectT = GetComponent<RectTransform>();
}
 
rectT.sizeDelta = new Vector2( ancho , alto );
//si queres que sea el mismo alto --> gameObject.rectTransform.rect.height
     

 
Ojo que lo hice de ojo seguro hay errores, el size delta setea el size con respecto a los anchors, y los tenes todos juntos (por default estan en el centro creo) es lo mismo que modificar el size.
 
https://docs.unity3d.com/ScriptReference/RectTransform-sizeDelta.html
 
 

Ok ahora mismo lo voy a probar y gracias de nuevo por la info : )
Cita de: lightbug date=1487307220Son los tipicos casos que debes usar el new, como cuando seteas un Vector3 y pones: new Vector3(x,y,z)
   
   
      proba algo asi:
   
   

RectTransform rectT;
void Start()
{
rectT = GetComponent<RectTransform>();
}
 
rectT.sizeDelta = new Vector2( ancho , alto );
//si queres que sea el mismo alto --> gameObject.rectTransform.rect.height
     

   
       
   


Graciaaaaas!!!! me anda joya 


Cita de: lightbug date=1487307220Para agregar aca dejo un link para comparar en assembly un If-else y un switch en C.
   
   
      http://www.eventhelix.com/RealtimeMantra/Basics/CToAssemblyTranslation3.htm#.WKbEGn_b0dU
   
   
      Basicamente el if else hace una comparacion o lo que le pongas dentro, y luego un salto cada vez que pasas por uno. Un switch define el numero etiquetas (los "case"), hace la comparacion y a partir de alli hace 1 solo salto. Como los saltos siempre son cruciales conviene hacer switch donde puedas. Claro que en algunos casos no es posible, los case de los switch admiten un cierto valor, no podes decir por ejemplo esto es mayor a esto?
   
   
      En definitiva no es razon para cuestionar el rendimiento de un juego, para nada.
   
   
       
   
   
      Son los tipicos casos que debes usar el new, como cuando seteas un Vector3 y pones: new Vector3(x,y,z)
   
   
      proba algo asi:
   
   

RectTransform rectT;
void Start()
{
rectT = GetComponent<RectTransform>();
}
 
rectT.sizeDelta = new Vector2( ancho , alto );
//si queres que sea el mismo alto --> gameObject.rectTransform.rect.height
     

   
      Ojo que lo hice de ojo seguro hay errores, el size delta setea el size con respecto a los anchors, y los tenes todos juntos (por default estan en el centro creo) es lo mismo que modificar el size.
   
   
      https://docs.unity3d.com/ScriptReference/RectTransform-sizeDelta.html
   
   
       
   


Y gracias al enlace en asm que has enviado se puede ver como un switch (siendo puristas) es mejor que 'n' ifs ya que es independiente del número de casuísticas.
 
 

Cita de: iRobb date=1487357883Y gracias al enlace en asm que has enviado se puede ver como un switch (siendo puristas) es mejor que 'n' ifs ya que es independiente del número de casuísticas.
   
   
       
   


De nada! hace unos años tuve un curso de assembly en microcontroladores (Unos freescale viejos) y habia que minimizar la utilizacion memoria de para las instrucciones y los datos(si era posible). La clave era implementar esos tipos de bucles, sobre todo el switch cuando se podia, y la diferencia era grande para un dispositivo de estas caracteristicas. Claro que para un CPU moderno esto no afecta, pero no estaria mal tenerlo en cuenta

El GarbageCollector y otros se encargan de controlar el abuso de memoria de la mayoría de comandos, en C#. Yo no me preocuparía demasiado de eso, si es para plataforma PC....
 
Por otro lado, si lo que te apetece es buscar formas de optimizar toda vía más el código (EXTREME CODER!!! ), puedes probar a sustituir los IF y los SWITCH por diferentes lógicas que realicen la misma función de forma imperativa. Por ejemplo con "bitflag" o con "clamping" en los IF, etc...
 
Busca por Google algun libro bueno de optimización de código, algoritmos etc, que seguro que sale algo...
 
 
 
Buena suerte!

Cita de: pioj date=1487407799El GarbageCollector y otros se encargan de controlar el abuso de memoria de la mayoría de comandos, en C#.
   


Yo del Garbage Collector ni idea la verdad, pero no se encarga de manejar la memoria dinamica en la "heap"? como cuando creas una referencia y no la borras, cosas asi.
 
Podrias explicar un poco mas de esos bitflag y clamping? no los conocia

Febrero 18, 2017, 01:59:15 PM #11 Ultima modificación: Febrero 18, 2017, 02:04:30 PM por francoe1
Cita de: lightbug date=1487413158Yo del Garbage Collector ni idea la verdad, pero no se encarga de manejar la memoria dinamica en la "heap"? como cuando creas una referencia y no la borras, cosas asi.
   
   
      Podrias explicar un poco mas de esos bitflag y clamping? no los conocia
   


Es bueno entender cómo funciona GC para evitar pérdidas de rendimiento.
 
Desde mi punto de vista todos los que están aprendiendo no pueden empezar a optimizar codigo porque realmente no entienden cómo funcionan las cosas, y muchas veces se pueden confundir.
 
bitflag se llamaba antes a la utilización de una enumeración de tipo byte, es decir utilizaban enumeraciones con valores byte para una comparación mas rapida. 
 
En C++ lo he utilizado para algunos BackEnd.
 

enum bitflag (<< = 1)
{
valorA = 1,
valorB,
valorC
}

 
En C# jamás lo utilice, de esa manera, pero si utilizo muchísimo las enumeraciones y switch ya que hacen más legible el código (que relativamente es lo mismo).
 
C++ es muchisimo mejor para estas cosas, nos permite tener mas control sobre el uso de memoria, direcciones, etc.
 
 
 
Me gustaria tambien aportar unos tips para las comparaciones de múltiples tipos dentro de switch, las enumeraciones nos permiten trabajar con or.
 

private enum MiEnumeracion
{
Caso1 = 1,
Case2,
Case3,
TodosLosCasos = Caso1 |Caso2 | Caso3,
}

 
De esta manera podemos solventar muchas comparaciones.

Cita de: francoe1 date=1487422755Me gustaria tambien aportar unos tips para las comparaciones de múltiples tipos dentro de switch, las enumeraciones nos permiten trabajar con or.
   
   

private enum MiEnumeracion
{
Caso1 = 1,
Case2,
Case3,
TodosLosCasos = Caso1 |Caso2 | Caso3,
}

   
      De esta manera podemos solventar muchas comparaciones.
   


Los switch los uso todos con enums, son muy utiles. hacer la or es muy buena tambien.

Por lo general los que venimos de C, C++ estas cosas las tenemos muy asimiladas! 

Etiquetas: