Home > Back-end >  Having Troubles with Unity C# Time Delay / Coroutines
Having Troubles with Unity C# Time Delay / Coroutines

Time:02-05

I am trying to write a script for when you press a button to make it instantiate a card with a random rarity but I need to delete the cards after a small delay although I dont think the delay is working because the cards seemingly instantly dissapear

Code:

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

public class CardMasterScript : MonoBehaviour
{
    public GameObject[] CardArray = new GameObject[8];
    public float RollNumber;

    public void RollCard()
    {
        RollNumber = Random.Range(0.1f, 100);

        Debug.Log("Number Rolled: "   RollNumber);

        if(RollNumber <= 47.9)
        {
            var card = Instantiate(CardArray[0]);
            StartCoroutine(TimeDelay());
            Destroy(card);
        } else if(RollNumber > 47.9 && RollNumber <= 77.9)
        {
            var card = Instantiate(CardArray[1]);
            StartCoroutine(TimeDelay());
            Destroy(card);
        } else if( RollNumber > 77.9 && RollNumber <= 87.9)
        {
            var card = Instantiate(CardArray[2]);
            StartCoroutine(TimeDelay());
            Destroy(card);
        } else if(RollNumber > 87.9 && RollNumber <= 94.9)
        {
            var card = Instantiate(CardArray[3]);
            StartCoroutine(TimeDelay());
            Destroy(card);
        } else if(RollNumber > 94.9 && RollNumber <= 97.9)
        {
            var card = Instantiate(CardArray[4]);
            StartCoroutine(TimeDelay());
            Destroy(card);
        } else if(RollNumber > 97.9 && RollNumber <= 99.4)
        {
            var card = Instantiate(CardArray[5]);
            StartCoroutine(TimeDelay());
            Destroy(card);
        } else if(RollNumber > 99.4 && RollNumber <= 99.9)
        {
            var card = Instantiate(CardArray[6]);
            StartCoroutine(TimeDelay());
            Destroy(card);
        } else if (RollNumber > 99.9 && RollNumber <= 100)
        {
            var card = Instantiate(CardArray[7]);
            StartCoroutine(TimeDelay());
            Destroy(card);
        }
    }
    
    public IEnumerator TimeDelay()
    {
        yield return new WaitForSeconds(0.5f);
    }
}
  • please help me fix this issue if you know how and thank you in advance!

at first I thought it was a problem with the instantiating and that it just wasn't instantiating the cards at all but now I'm not quite sure what the problem is.

CodePudding user response:

you have to call the destroy after the waiting time like this

yield return new WaitForSeconds(0.5f);
Destroy(obj);

and other tip: Destroy method contains delay parameter

Destroy(obj,2.0f);

https://docs.unity3d.com/ScriptReference/Object.Destroy.html

CodePudding user response:

The destruction is occurring independent from the coroutine. When you start the coroutine, you are "splitting" the program into two branches. Currently your first branch just turns on an alarm clock for half a second and your other branch deletes your object.

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

public class CardMasterScript : MonoBehaviour
{
    public GameObject[] CardArray = new GameObject[8];
    public float RollNumber;

    public void RollCard()
    {
        RollNumber = Random.Range(0.1f, 100);

        Debug.Log("Number Rolled: "   RollNumber);

        if(RollNumber <= 47.9)
        {
            var card = Instantiate(CardArray[0]);
            StartCoroutine(TimeDelay());
        } else if(RollNumber > 47.9 && RollNumber <= 77.9)
        {
            var card = Instantiate(CardArray[1]);
            StartCoroutine(TimeDelay());
        } else if( RollNumber > 77.9 && RollNumber <= 87.9)
        {
            var card = Instantiate(CardArray[2]);
            StartCoroutine(TimeDelay());
        } else if(RollNumber > 87.9 && RollNumber <= 94.9)
        {
            var card = Instantiate(CardArray[3]);
            StartCoroutine(TimeDelay());
        } else if(RollNumber > 94.9 && RollNumber <= 97.9)
        {
            var card = Instantiate(CardArray[4]);
            StartCoroutine(TimeDelay());
        } else if(RollNumber > 97.9 && RollNumber <= 99.4)
        {
            var card = Instantiate(CardArray[5]);
            StartCoroutine(TimeDelay());
        } else if(RollNumber > 99.4 && RollNumber <= 99.9)
        {
            var card = Instantiate(CardArray[6]);
            StartCoroutine(TimeDelay());
        } else if (RollNumber > 99.9 && RollNumber <= 100)
        {
            var card = Instantiate(CardArray[7]);
            StartCoroutine(TimeDelay());
        }
    }
    
    public IEnumerator TimeDelay()
    {
        yield return new WaitForSeconds(0.5f);
        Destroy(card);
    }
}

In your case using a coroutine isn't actually necessery, since the Destroy method has a build in delay argument.

Streamlined your code could look like this:

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

public class CardMasterScript : MonoBehaviour
{
    public GameObject[] CardArray = new GameObject[8];
    public float RollNumber;

    public void RollCard()
    {
        RollNumber = Random.Range(0.1f, 100);

        Debug.Log("Number Rolled: "   RollNumber);

        if(RollNumber <= 47.9)
        {
            var card = Instantiate(CardArray[0]);
        } else if(RollNumber > 47.9 && RollNumber <= 77.9)
        {
            var card = Instantiate(CardArray[1]);
        } else if( RollNumber > 77.9 && RollNumber <= 87.9)
        {
            var card = Instantiate(CardArray[2]);
        } else if(RollNumber > 87.9 && RollNumber <= 94.9)
        {
            var card = Instantiate(CardArray[3]);
        } else if(RollNumber > 94.9 && RollNumber <= 97.9)
        {
            var card = Instantiate(CardArray[4]);
        } else if(RollNumber > 97.9 && RollNumber <= 99.4)
        {
            var card = Instantiate(CardArray[5]);
        } else if(RollNumber > 99.4 && RollNumber <= 99.9)
        {
            var card = Instantiate(CardArray[6]);
        } else
        {
            var card = Instantiate(CardArray[7]);
        }
        Destroy(card, 0.5f);
    }
}

CodePudding user response:

In Quick way, it is enough to enter the delay value in the second parameter of the Destroy method.

Destroy(card, .5f); // Delay Time

The second way is to write the functions themselves inside the Coroutine. Because the delay time is not executed outside the coroutine.

private IEnumerator DelayRun(GameObject gameObject)
{
    yield return new WaitForSeconds(.5f);
    
    Destroy(gameObject);
}

The third way is to specify the action with a delay time, which allows you to execute any command after a delay. Just make sure you use the System library.

using System;

...

void Start()
{
    StartCoroutine(DelayRun(.5f, () => Destroy(card)));
}

private IEnumerator DelayRun(float delay, Action action)
{
    yield return new WaitForSeconds(delay);
    
    action.Invoke();
}
  • Related