【问题标题】:Wait for coroutine to finish [duplicate]等待协程完成[重复]
【发布时间】:2017-12-17 23:08:40
【问题描述】:

我有协同程序,在N 秒后清除文本并将其恢复为原始形状。问题是协程在第一次返回后永远不会继续(wait for seconds)。

我在其他地方遇到了这个问题,并发现它正在发生,因为我在协程完成之前销毁了 Gameobject,所以我让它返回 bool 但现在我很困惑,不能在这里使用相同的技巧,因为我是通过脚本启动协程的未初始化。该脚本只有静态函数,我通过它启动协程。这是我的代码:

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);
    }
}

这是函数本身:

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;
}

我怎样才能使我的项目(OnMouseDown() 所在的位置)在协程完成之前不会破坏?

【问题讨论】:

    标签: c# unity3d unity5 coroutine


    【解决方案1】:

    如果你想等待协程完成......那么方法也必须是协程。

    您有 3 个选项,具体取决于您的具体情况:

    1. 将需要等待的代码移到现有协程方法中(最后一个当前yield.
      • 您也可以将委托传递给当前协程并将其用作回调,然后现有协程的每次使用都可以提供自己的回调委托。然后“等待完成”代码进入此委托。
    2. 把当前的非协程方法变成协程。
    3. 创建一个新的协程,将需要等待另一个协程的代码推入其中,包括对现有协程的调用,yield 在另一个协程上。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-11-01
      • 2012-04-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多