首页 > 解决方案 > Unity Destroying Instantiated clone 停止实例化

问题描述

我有这段代码,用于实例化精灵

AppleSpawner.cs

public class appleSpawner : MonoBehaviour
{
  private int isRunning = 1;
  private readonly int[] positions = { -10, -5, 0, 5, 10 }; 
  public int NumberOfSeconds;
  System.Random rand = new System.Random();

  private void Update()
  {
      if (isRunning == 1) StartCoroutine(Wait());    
  }

  public IEnumerator Wait()
  {
      int randomX = rand.Next(5);
      isRunning = 0;
      yield return new WaitForSeconds(NumberOfSeconds);
      Instantiate(this, new Vector3(randomX, 5, 0), transform.rotation);

  }
}

这里出现了问题#1:这甚至是在实例化新副本之间等待 X 秒的最佳/最简单的方法吗?

我也有一个角色,有一个 oncollision 事件,如果它与其中一个副本发生冲突,它应该摧毁它。这很好用,问题是,如果我与最后生成的副本发生冲突,它会破坏它,然后副本停止生成。

字符.cs

private void OnCollisionEnter2D(Collision2D collision)
{
  if (collision.gameObject.tag == "apple")
    {
        Destroy(collision.gameObject);
        points++;
        text.text = "points: " + pont;
    }
}

标签: c#unity3dinstantiation

解决方案


不要在一个班级中混合不同的职责。

它使您的代码容易出错,并且随着一类变得越来越大,越来越难以维护。你应该有一个产卵器,它会产生苹果,还有一个带有碰撞器的苹果预制件。两种不同的脚本。

public class Spawner : MonoBehaviour {
    private static readonly int[] positions = { -10, -5, 0, 5, 10 }; 
    public int NumberOfSeconds;
    private System.Random rand = new System.Random();
    public GameObject Prefab;

    public IEnumerator Start() {
        while (true) {
            int randomX = positions[rand.Next(5)];
            Instantiate(Prefab, new Vector3(randomX, 5, 0), transform.rotation);
            yield return new WaitForSeconds(NumberOfSeconds);
        }
    }
}

在您的情况下,具有该组件的对象不应具有碰撞器或精灵,因此它们永远不会在与玩家碰撞时被破坏。生成的预制件是玩家收集或避免的常规苹果。

由于 spawner 不会产生另一个 spawner,我们将 spawn 逻辑放在一个循环中。

您可能想要数组中的随机位置而不是原始随机数,所以我修复了它。

概括。

现在你的产卵器做了唯一的功能——产卵。它不再绑定到苹果,所以你可以用另一个刷怪笼刷出胡萝卜。逻辑保持不变。

这是什么魔法Start

你可以做Start一个协程。它就像任何其他协程一样工作:运行直到yield returnyield break或函数结束。后两者结束协程,否则等待,然后继续运行。Update在控制协程时最好使用标志。

如果您需要一个应该运行每一帧的脚本,那么使用Update.


推荐阅读