Wait for coroutine to finish [duplicate]

狂风中的少年 提交于 2021-02-02 09:58:15

问题


I have coroutine that after N seconds clear text and returns it to it's original shape. Problem is that coroutine never continues after first return (wait for seconds).

I had this problem somewhere else and figured it out that is happening because i destroy Gameobject before coroutine finish so i made it return bool but now i am confused and can not use same trick here since i am starting coroutine through script that is not initialized. That script only has static function through which i start coroutine. Here is my code:

void OnMouseDown()
{
    bool safeDestroy = false;

    IGatherable gather = CharacterCommands.character.GetComponent<IGatherable>();
    if(gather != null)
    {
        switch(itemID)
        {
        case 3:
            Drops[] d = ChestDrop.GetItemFromDropStash(drops, gather, this); //Here is function that is starting function with coroutine PROBLEM
            if(d.Length == 0)
            {
                safeDestroy = true;
            }
            else
            {
                drops = d;
            }
            break;
        default:
            if(ItemDatabase.GetItem(itemID).maxStackable < Inventory.GetCoins() + amount)
            {
                Parameters.centerText.text = "Not enough space in your bag!";
                safeDestroy = Parameters.clearText(Parameters.centerText, 3, this); //Coroutine i had same problem but done it this way.
            }
            else
            {
                gather.GatherItem(itemID, amount);
                safeDestroy = true;
            }
            break;
        }
    }
    if(safeDestroy)
    {
        Destroy(this.gameObject);
    }
}

And here is the function itself:

public static Drops[] GetItemFromDropStash(Drops[] drops, IGatherable gather, MonoBehaviour justToStartCoroutine)
{
    foreach(Drops drop in drops)
    {
        int r = UnityEngine.Random.Range(1, 101);
        if(r < drop.chance)
        {
            if(ItemDatabase.GetItem(drop.itemID).maxStackable > Inventory.GetItemFromInventoryById(drop.itemID).amount + drop.amount)
            {
                Inventory.AddItemToInventory(drop.itemID, drop.amount);
                Parameters.centerText.text = "+" + drop.amount + " " + ItemDatabase.GetItem(drop.itemID).itemName;
                switch(ItemDatabase.GetItem(drop.itemID).itemRarity)
                {
                case ItemRarity.common:
                    Parameters.centerText.color = Color.gray;
                    break;
                case ItemRarity.normal:
                    Parameters.centerText.color = new Color(80, 100, 255);
                    break;
                case ItemRarity.rare:
                    Parameters.centerText.color = new Color(255, 80, 80);
                    break;
                case ItemRarity.special:
                    Parameters.centerText.color = new Color(200, 0, 220);
                    break;
                case ItemRarity.legacy:
                    Parameters.centerText.color = new Color(199, 224, 0);
                    break;
                case ItemRarity.legendary:
                    Parameters.centerText.color = new Color(224, 169, 0);
                    break;

                }
                bool t = Parameters.clearText(Parameters.centerText, 3, justToStartCoroutine);

                int i = Array.IndexOf(drops, drop);
                List<Drops> tmp = new List<Drops>(drops);
                tmp.RemoveAt(i);
                drops = tmp.ToArray();
            }
            else if (Inventory.CheckForFreeSpaceInInventory() == true)
            {
                Inventory.AddItemToInventoryToNewSlot(drop.itemID, drop.amount);
                Parameters.centerText.text = "+" + drop.amount + " " + ItemDatabase.GetItem(drop.itemID).itemName;
                switch(ItemDatabase.GetItem(drop.itemID).itemRarity)
                {
                case ItemRarity.common:
                    Parameters.centerText.color = Color.gray;
                    break;
                case ItemRarity.normal:
                    Parameters.centerText.color = new Color(80, 100, 255);
                    break;
                case ItemRarity.rare:
                    Parameters.centerText.color = new Color(255, 80, 80);
                    break;
                case ItemRarity.special:
                    Parameters.centerText.color = new Color(200, 0, 220);
                    break;
                case ItemRarity.legacy:
                    Parameters.centerText.color = new Color(199, 224, 0);
                    break;
                case ItemRarity.legendary:
                    Parameters.centerText.color = new Color(224, 169, 0);
                    break;

                }
                bool t = Parameters.clearText(Parameters.centerText, 3, justToStartCoroutine);

                int i = Array.IndexOf(drops, drop);
                List<Drops> tmp = new List<Drops>(drops);
                tmp.RemoveAt(i);
                drops = tmp.ToArray();
            }
            else
            {
                Parameters.centerText.text = "Not enough space in inventory!";
                bool t = Parameters.clearText(Parameters.centerText, 3, justToStartCoroutine);
            }
        }
    }
    return drops;
}

How can i achieve so that my item (where OnMouseDown() is) doesn't destroy until coroutine is finished?


回答1:


If you want to wait for a coroutine to finish...then the method must also be a coroutine.

You have 3 options, depending on your specific scenario:

  1. Move the code that needs to wait into the existing coroutine method (after the last current yield.
    • You can also pass a delegate into the current coroutine and use it as a callback, then each use of the existing coroutine can supply its own callback delegate. The "wait for finish" code then goes inside this delegate.
  2. Turn the current not-coroutine method into a coroutine.
  3. Create a new coroutine, shove the code that needs to wait for the other coroutine into it, including the call to the existing coroutine, yield on that other coroutine.


来源:https://stackoverflow.com/questions/45076022/wait-for-coroutine-to-finish

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!