Jump to content
UnitySpain

Aceptamos donaciones vía Paypal.

UnitySpain.com es un servicio gratuito, pero mantener la Comunidad conlleva una serie de gastos.

Fondo Anual Unityspain: Donados 15,00€ de 150,00€

  • Servidor: Dominio.com y Hosting Web
  • Mantenimiento de los Foros
  • Contenido y Servicios Extras
  • Mantenimiento para Redes Sociales
Sign in to follow this  
nomoregames

ANSWERED incremento con while

Recommended Posts

Hola a todos

:90_wave:

Estoy intentando,que cuando mantienes el botón derecho de el ratón  , mediante while, que una variable float, incremente de manera "pausada", pero no se por que no estoy consiguiendo absolutamente nada....

  while (ArrowAddForce != 30)
        {
            ArrowAddForce += 1;
            print(ArrowAddForce);
           // yield return new WaitForSeconds(0.4f); e probado con esto pero sigo sin conseguir nada
            
        }

estoy seguro de que tiene una respuesta muy sencilla, pero no llego a mas y es desesperante

 

Editado: en el código, donde pongo while(ArrowAddForce....) ponía originalmente  while(Input.GetMouseButtonDown(1)).


  

 

Share this post


Link to post
Share on other sites
Quote

Estás usando el Input.GetMouseButton( 1 ) no??

Sip

(joder me ha dado un huelco el corazón, siempre que apareces en alguno de mis posts me arreglas la vida)

Share this post


Link to post
Share on other sites
2 hours ago, nomoregames said:

Sip

(joder me ha dado un huelco el corazón, siempre que apareces en alguno de mis posts me arreglas la vida)

Jajaja, bueno me imagino que estás haciendo esto dentro de una corrutina. Quizás podrías subir el código entero así se ve mejor la cosa.

 

Share this post


Link to post
Share on other sites

Yo recomiendo usar tiempo siempre que puedas, en lugar de contadores arbitrarios que luego nunca nos acordamos de qué unidades contaban, y además nos arriesgamos a que funcionen diferente en diferentes ordenadores.

Yo en el Update() o FixedUpdate() simplemente usaría:

if (Input.GetMouseButton(1)) {
    buttonActionPressedTime = buttonActionPressedTime + Time.fixedDeltaTime;  // o deltaTime, pero esto yo lo pondría en FixedUpdate así que fixedDeltaTime
    this.UpdateBowTension();  // supongamos que este método existe por ahora
} else {
    pressedTime = 0.0f;
}

Y luego cuando necesites interpretar eso ya dividirás pressedTime por lo que toque, o le aplicas la función que quieras (lineal, cuadrática, una spline a tu gusto...). Igual necesitas caparla (clampearla) para que no crezca demasiado pero eso también puedes hacerlo al interpretarla, eso ya a tu gusto.

En otra parte (desde Update o FixedUpdate depende de lo que vayas a hacer), la usaría:

public void UpdateBowTension() {
    float bowTensionTime = 2.0f;  // esto bien podría ser una constante o ponerlo como parámetro de tu controller o tus globals
    float bowTension = Mathf.Clamp(buttonActionPressedTime / bowTensionTime, 0.0f, 1.0f);  // la tensión normalizada entre 0 y 1 (siempre mejor! :))

    // Y aquí lo usas para lo que quieras, por ejemplo actualizar la imagen o una barra, o si vas a disparar, usarlo como multiplicador de la fuerza.
}

De esta forma sabes exactamente que tu acción toma 2 segundos, y puedes cambiarlo fácilmente.

Es verdad que seguram1ente necesitarás un boolean para expresar también que estás de hecho disparando el arco, y lidiar con el sonido, y demás, pero espero que te inspire un poco lo de arriba.

Fíjate también que así es fácil cambiar la "respuesta" del arco, si quisieras. No te preocupes ahora pero estamos usando "buttonActionPressedTime / bowTensionTime" que es lineal, pero si quisieras que la tensión fuese acelerando podrías usar por ejemplo una cuadrática (elevando eso al cuadrado para que llegue antes al tope) o, tratándose de un arco, una función que decaiga como 1 - (x - 1)^2, aunque realmente no sé qué hace la gente.  También puedes crear una spline en el editor y llamo a su método para interpolar el tiempo, así tienes un control de las curvas, si necesitas algo tan fino.

Un saludo,

Edited by J Montes

Share this post


Link to post
Share on other sites
Quote

 Quizás podrías subir el código entero así se ve mejor la cosa.


    float ArrowAddForce;
    private void Update()
    {
    if (Input.GetMouseButtonDown(1))
        {
            StartCoroutine(tensiontime()); 
        }
    }

    IEnumerator tensiontime()
    {
        while (Input.GetMouseButtonDown(1))  
        {
            ArrowAddForce += 1;
            print(ArrowAddForce);
            yield return new WaitForSeconds(0.4f);


        }
    }

 

J Montes ...

es triste... pero es la unica parte que e logrado entender....

16 hours ago, J Montes said:

if (Input.GetMouseButton(1)) {     buttonActionPressedTime = buttonActionPressedTime + Time.fixedDeltaTime;

 

 

16 hours ago, J Montes said:

Y luego cuando necesites interpretar eso ya dividirás pressedTime por lo que toque, o le aplicas la función que quieras (lineal, cuadrática, una spline a tu gusto...).

con que lo tengo que dividir

 

16 hours ago, J Montes said:

// la tensión normalizada entre 0 y 1 (siempre mejor! :))

normalizar no era hacer que un numero fuera -1, 0 o 1, por que lo clampeas....

 

Como puedes ver, hablo desde una ignorancia... casi absoluta

Share this post


Link to post
Share on other sites

Para esta práctica necesitas 2 "eventos", MouseUp y MouseDown.

private void Update()
{
	if (Input.GetMouseButton(0)) // Si fuera DOWN se ejecutaria 1 vez. De esta menera detecta si el mouse esta siendo presionado.
	{
	}

	if (Input.GetMouseButtonUp(0))
	{
	}
}

Teniendo esto ahora necesitarás un factor, número del 0 al 1 que será utilizado para multiplicar el valor máximo que desees.
Para esto la forma más simple y de alguna manera "segura" es utilizando Time.deltaTime para incrementar una variable.

Dentro de el bloque IF del mouse "DOWN".

time_amount += Time.deltaTime;

Dentro de el bloque IF del mouse UP

OnFinishEvent(time_amount);
time_amount = 0;

La función OnFinishEvent es donde ejecutaras la mecanica necesario, multiplicando time_amount normalizado * el maximo valor permitido.

Edited by francoe1
Modifique un error lógico.

Share this post


Link to post
Share on other sites

No usarías corrutinas para esto, porque Unity está orientado a que este tipo de lógica no necesite corrutinas: en cada frame, tienes un evento Update() para ocuparte de la lógica que necesites ejecutar. 

Podríamos hacerlo en una corrutina, claro, pero sería más lioso que como te ha dicho @francoe1.

Una corrutina la usas cuando precisamente quieres ejecutar instrucciones a lo largo de varios frames. Por ejemplo, las uso mucho para demorar algo o secuenciar cosas (ejemplo: termina una partida, emito un sonido, paro reloj y controles, espero 2 segundos, y muestro un mensaje de Final. Para esperar esos dos segundos, podríamos usar una variable y en el Update comprobar si han pasado esos 2 segundos, pero sería engorroso hacer eso para cada secuencia, y rompe la linealidad del código. En ese caso, yo suelo hacer algo como:

void Update() {
  if (finished) {
    gameStopped = true;  // ejemplo: marcamos el juego como parado
    StartCoroutine(EndGameCoroutine);  // arrancamos nuestra secuencia de fin de juego
  }
}

private IEnumerator EndGameCoroutine(float waitTime) 
{
            endSound.Play();  // ejemplo: sonido de fin de juego
            timer.Stop();  // ejemplo: en este ejemplo, paro el reloj del juego ya mismo ya que ha acabado la partida
            yield return new WaitForSeconds(2.0f);  // esperamos un rato, me gusta que el jugador contemple su éxito o fracaso
            endGameBanner.SetActive(true);  // ejemplo: mostramos un mensaje de fin de partida
            yield return new WaitForSeconds(3.0f); // esperamos un rato, para que el jugador pueda ver el mensaje anterior
            restartRound();  // ejemplo: y reiniciamos
}

Ves que en este ejemplo sería engorroso tener condiciones el Update() para cada una de esas esperas de 2 segundos, en cambio con una corrutina se expresa de forma secuencial.

En todo momento, puede haber una o más corutinas ejecutándose. Éstas se ejecutan durante el Update(), de forma que puedes ir arrancándolas y se ejecutarán concurrentemente (en "paralelo") al resto de tus updates. Ojo a no dejar corrutinas perdidas. Fíjate también que en realidad las corutinas pendientes se ejecutan en realidad, en orden, al final del Update de la escena (no corren en hilos, sino que utilizan un modelo de programación asíncrona y de ahí que se llamen corrutinas). En resumen si lanzas una corutina en Update(), ésta se ejecutará al final del Update de ese frame para todos los objetos. Si una corrutina está esperando 2 segundos, se ejecutará la línea siguiente al final del Update cuando terminen esos 2 segundos.

La manera que tiene una corrutina de "parar y esperar a algún evento" es declarándose como IEnumerator y usando ese "yield return". Esto es una peculiaridad del lenguaje y no vamos a entrar en detalles por ahora.

Las corrutinas son útiles para muchas más cosas que temporizar algo. Por ejemplo, para díalogos de tipo "Aceptar / Cancelar". El código que espera la respuesta usa:

bool confirmed = yield return new ShowConfirmationDialog("Are you sure?");  // esta función no es estándar, es un ejemplo

Y se queda por tanto esperando a que el usuario responda a ese mensaje (es posible decirle a una corutina que "ya ha llegado su evento"). También se usan para peticiones de red o cargas de recursos (que se ejecutan por detrás, de forma asíncronas).

Mi consejo es que pienses por ahora en corrutinas para secuencias de acciones programadas. Por ejemplo, al soltar tu arco, podrías querer una corrutina para:

  1. Bloquear el movimiento del jugador
  2. Sonido de disparo
  3. Preparar la flecha y lanzarla
  4. (ESPERAR) al impacto de la flecha y/o timeout  <- este sería el motivo de usar una corrutina para esto
  5. comprobar el impacto (terreno válido, etc) y salir si es inválido
  6. sonido de "enganchar la flecha"
  7. crear el puente
  8. reestablecer el movimiento del jugador

Igualmente, podrías hacer esto usando varios scripts en la flecha. Usar una corrutina para este tipo de secuencias depende del contexto, y de tus preferencias y estilo personal. Pero de todas formas, esto sería una vez se decide soltar la flecha... en general para gestionar los controles yo te recomiendo que no pienses en corrutinas. Igual alguien tiene otra opinión, pero yo no veo su utilidad aquí, ya que el mecanismo de Update() está pensado exactamente para esa parte de la lógica -controles, movimientos de objetos, lógica que se ejecuta en cada frame...-).

 

En otro orden de cosas:

Normalizar no es hacer que algo valga "-1, 0, o 1". Normalizar significa "regularizar" algo y normalmente a lo que nos referimos depende del contexto.

Pero para empezar, es habitual referirse a valores entre  -1.0 y 1.0 (con todos los números reales intermedios). Quizá en algún contexto normalizar se refiera a "-1, 0 o 1" (valores enteros discretos) pero no en este caso. 

En otros casos nos referimos a valores positivos entre 0 y 1 , como en este caso, donde el tiempo de tensión puede ser "0" o "máximo" pero no puede ser negativo evidentemente. Si lo normalizamos, en general, la mayoría entendemos ponerlo entre 0 y 1 (es decir, dividir por el máximo).

En mi ejemplo, además lo clampeo porque si el usuario deja el ratón pulsado más tiempo entiendo que consideramos que está en el "máximo", por eso lo clampeo entre 0 y 1 (una vez dividido por el máximo: es decir, "normalizado").

Por supuesto, podrías clampear entre [0, maxTime] y luego dividir, o dividir primero y clampear entre [0, 1]... esto ya tienes que tener tú claro qué unidades y qué representa cada una de tus variables.

Y yo por eso sugiero contar tiempo, y hacer las cuentas al final: así tienes siempre el dato inequívoco (tiempo pulsado) y luego con un par de cuentas (como una división y un clamp) ya lo tienes entre 0 y 1 (disparar flojísimo - máxima tensión). Al estar normalizado, lo puedes usar para multiplicar por tu fuerza, para tu animación... entre 0 y 1. Por eso todo el mundo te aconseja que intentes trabajar así y no con valores absolutos, porque luego cualquier cambio te obligará a cambiar varias cosas. Pero... ¡todos metemos constantes en el código durante las pruebas!.

...en estadística, normalizar se refiere a normalizar los valores de una serie respecto a unos parámetros estadísticos. En álgebra lineal, normalizar un vector significa hacer que su magnitud sea 1 conservando su dirección (en Unity: Vector3.normalize() y muchas otras funciones), normalizar una matriz es hacer que la transformación que representa no escale el espacio, y etc etc...

 

Edited by J Montes

Share this post


Link to post
Share on other sites

Por lo que explicas, tenia una idea totalmente equivocado sobre las corrutinas ... como bes aun me queda mucho por aprender (aun tengo miedo a los while ), a partir de lo que me as contado intentare llegar a entenderlas completamente

 

Gracias a todos por la ayuda, y en especial a la explicación de J Montes :96_ok_hand:

Share this post


Link to post
Share on other sites
Sign in to follow this  

×
×
  • Create New...