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
Krokodilo

C# - Retrasar ejecución de una linea de código

Recommended Posts

Hola buenas. Estoy aprendiendo a utilizar unity y programar en C#, por lo general toda duda que tengo la googleo y tarde o temprano encuentro una respuesta pero ahora se me complico jaja.

La escena es simplemente un personaje (controlado con el script "FirstPersonController" de los StandardAssests de Unity) y un par de arboles, lo que quiero es talar un árbol y tengo 3 scripts para eso.

 

Uno llamado "Golpe" que esta en el personaje

Simplemente tiene un if con una condición que al hacer click izquierdo reproduzca una animación y cambie la booleana "golpe" (que es public static) a true, utilice un contador para que solo pueda ejecutarse una vez cada cierto tiempo (velocidad de ataque).

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Golpe : MonoBehaviour {
    
    public static bool golpe;

    private float secondsCounter = 0;
    private float velAttack;

    private Animator animator;

    private void Awake()
    {
        animator = GetComponent<Animator>();
    }
    // Use this for initialization
    void Start () {
		
	}
	
	// Update is called once per frame
	void Update () {
        velAttack = Arma.velAttackPublic;
        secondsCounter += Time.deltaTime;

        if (Input.GetButton("Fire1") && secondsCounter >= velAttack)
        {
            secondsCounter = 0;
            animator.SetTrigger("Click Izq");
            golpe = true;

        }
        else
            {
                golpe = false;
                animator.ResetTrigger("Click Izq");
            }
        
    }
}

Otro llamado "Arma" que esta en el arma (el brazo derecho en este caso)

Si la booleana "golpe" del script "Golpe" es true, castea un rayo desde la camara hacia el frente con cierto rango, si el rayo colisiona con un objeto y este tiene el script "ControlDeVida" ejecuta el método "TakeDamage" del mismo

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Threading;

public class Arma : MonoBehaviour {
    
    public Camera cam;
    public float velAttack;
    public static float velAttackPublic;
    public int dañoBloque = 10;
    public float rango = 1;
    public static bool hitMe;

    // Use this for initialization
    void Start () {
		
	}
	
	// Update is called once per frame
	void Update () {
        velAttackPublic = velAttack;
        if (Golpe.golpe) Attack();
    }

    public void Attack()
    {
        RaycastHit hit;
        if (Physics.Raycast(cam.transform.position, cam.transform.forward, out hit, rango)) //Castea un rayo desde la camara hacia delante y comprueba si colisiono con algo
        {
            Debug.Log(gameObject.name + " to " + hit.transform.name); //Excribe por consola que "arma" colisiono con que objeto
            Thread.Sleep(500); //Intento fallido, congela todo el juego
            hit.transform.GetComponent<ControlDeVida>().TakeDamage(dañoBloque);// si el hit tiene el script "ControlDeVida" ejecuta el metodo "TakeDamage" de dicho script
        }
    }
}

Y por ultimo uno llamado "ControlDeVida" que esta en ambos arboles

Este controla la vida del objeto. 

utilizo el metodo "TakeDamage" para bajarle la vida y reproducir un sonido, si la vida es <= 0 se destruye.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ControlDeVida : MonoBehaviour {

    public int maxHealth;
    public int health;
    public AudioClip golpeSound;
    public AudioClip destroySound;

    AudioSource source;
    
    // Use this for initialization
    void Awake () {
        health = maxHealth;
        source = GetComponent<AudioSource>();
	}

    // Update is called once per frame
    void Update()
    {
        if (health <= 0)
        {
            source.PlayOneShot(destroySound);
            Destroy(gameObject);
        }
    }

     public void TakeDamage(int daño)
    {
        health -= daño;
        source.PlayOneShot(golpeSound);
    }
}

Tengo una animación para el golpe el cual es un puñetazo, el brazo (un simple cubo rectangular) se mueve hacia delante y regresa.

Ahora, en si funciona todo perfecto, pero mi problema es que entre el click y la ejecución de "TakeDamage" no hay ningún tiempo, osea apenas hacer click la vida del objeto baja. Quisiera hacer que esto tarde 0.2 segundos, que es lo que tarda la animación del golpe en llegar a cierto punto.

Para esto necesito que El llamado del método "TakeDamage" se retrase 0.2 segundos.

Buscando encontré "Thread.Sleep()" pero esto hace que se congele toda la escena.

Seguramente lo que estoy haciendo no sea lo mejor para lograr lo que quiero, pero es lo primero que se me ocurrió sabiendo tan poco de C# . Si quieren compartirme otra manera de hacerlo que les parezca mejor estaría genial. Desde ya muchas gracias n.n

 

 

 

Share this post


Link to post
Share on other sites

La manera más sencilla en Unity, es usar una corutina. También puedes tener una clase para manejar el tiempo, y pasar de corutinas, pero para ir aprendiendo te vendrá bien.

 

public IEnumerator TakeDamage(int danyo)
{
 	yield return new WaitForSeconds(0.2f);
  
  	health -= daño;
    source.PlayOneShot(golpeSound);
}

// Y para llamarla:

StartCoroutine(TakeDamage(cantidadDanyo));

 

Edited by OldGuy

Share this post


Link to post
Share on other sites

@OldGuy Muchísimas gracias, funciono perfectamente. Por ahora utilizare coroutines, pero ya voy a ir viendo como es eso de una clase que controle el tiempo, gracias.

Share this post


Link to post
Share on other sites

×
×
  • Create New...