SetActive(true)在协程内部不起作用

时间:2019-08-22 10:22:10

标签: unity3d coroutine

我正在使用协程来管理游戏中的通电冷却时间。当玩家与加电碰撞时,他们会获得效果,并且会开始冷却,因此他们在一定时间内无法再次使用它。

我正在使用协同程序来管理这些冷却时间-将gameObject设置为false,等待冷却时间,然后将gameObject设置为true。

我的代码:

IEnumerator RespawnTime ()
{
    gameObject.SetActive(false);
    Debug.Log("disabled");

    yield return new WaitForSeconds(3f);

    gameObject.SetActive(true);
    Debug.Log("enabled");
}

private void OnCollisionEnter2D (Collision2D collision)
{
    // Health stuff goes in here.
    Debug.Log("Health regen!");

    // Start cooldown
    StartCoroutine(RespawnTime());
}

但是,一旦禁用,gameObject就再也不会激活。我认为问题不在于产量,因为注释掉SetActive语句会导致两个调试消息都在正确的时间显示。

编辑:

对不起,我没有澄清。我知道协同程序不会在已禁用的GameObjects上运行。我制作了一个PowerUpManager脚本,但是没有用。代码:

PowerUp脚本中,在OnCollisionEnter2D方法中

StartCoroutines(PowerUpManager.RespawnTime(gameObject))

PowerUpManager脚本中

public static IEnumerator RespawnTime(GameObject powerUp)
{
    powerUp.SetActive(false);

    yield return new WaitForSeconds(3f);

    powerUp.SetActive(true);
}

3 个答案:

答案 0 :(得分:2)

打来电话的那一刻

gameObject.SetActive(false);

此对象不再收到Update消息,因此也不再执行Coroutine

  

MonoBehaviour被销毁时,或者附加了GameObject的协同作用也被禁用。


您第二次尝试不起作用的原因是:您仍在同一StartCoroutine上调用GameObject,因此PowerUpManager类的协程现在在您的计算机上执行 GameObject =>具有相同的效果。

如果您真的想使用PowerUpManager,则需要一个Singleton实例,并在该实例上调用StartCoroutine,例如

PowerUpManager中拥有

public static PowerUpManager Instance;

private void Awake()
{
    Instance = this;
}

然后您可以从脚本中调用

PowerUpManager.Instance.StartCoroutine(PowerUpManager.RespawnTime(gameObject));

在您不需要平滑移动等简单情况下,只需一个简单的延迟,我建议您根据需要使用Invoke。这还将在禁用或无效的GameObject上执行。

private void EnableAfterCooldown()
{
    gameObject.SetActive(true);
    Debug.Log("enabled");
}

private void OnCollisionEnter2D (Collision2D collision)
{
    // Health stuff goes in here.
    Debug.Log("Health regen!");

    gameObject.SetActive(false);
    Invoke("EnableAfterCooldown", 3f);
}

答案 1 :(得分:1)

如果停用游戏对象,所有对象的组件也会被禁用,因此协程将不再被调用。

您可以做的是,将协程冷却和检查碰撞的脚本分成2个单独的脚本。

我们叫Cooldown.csPowerup.cs。 然后,让它们相互交叉引用。 在powerup.cs中,您拥有

private void OnCollisionEnter2D (Collision2D collision)
{
    // Health stuff goes in here.
    Debug.Log("Health regen!");
    // Start cooldown
    Cooldown cd = gameObject.GetComponent<cooldown>();
    cd.CooldownCoroutine();
}

在Cooldown.cs中:

IEnumerator RespawnTime ()
{
     Powerup pu = gameObject.GetComponent<Powerup>()
     pu.SetActive(false);
     Debug.Log("disabled");
     yield return new WaitForSeconds(3f);
     pu.SetActive(true);
     Debug.Log("enabled");
}

public void CooldownCoroutine()
{
    // Health stuff goes in here.
    Debug.Log("Health regen!");
    // Start cooldown
    StartCoroutine(RespawnTime());
}

这样,您将不会禁用整个对象,而只会禁用检查冲突的脚本。

答案 2 :(得分:0)

协程不能在禁用的游戏对象上运行!

您应该在另一个游戏对象上运行它。