Unity Destroying实例化克隆停止实例化

时间:2019-05-07 12:28:43

标签: c# unity3d instantiation

我有此代码,以实例化精灵

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事件,如果它与副本之一发生冲突,则应该销毁它。效果很好,问题是,如果我与最后生成的副本发生冲突,它将销毁它,然后副本停止生成

character.cs

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

2 个答案:

答案 0 :(得分:3)

不要在一堂课中混用不同的职责。

随着一类的增加,它使您的代码易于出错,并且越来越难以维护。您应该有一个生成苹果的生成器,以及一个带有对撞机的苹果预制件。两种不同的脚本。

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

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

由于生成器不会再生成其他生成器,因此我们将生成逻辑置于循环中。

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

概括。

现在,您的生成器执行唯一的功能-生成。它不再与苹果绑定,因此您可以与另一个生成器生成胡萝卜。逻辑保持不变。

Start中的魔术是什么?

您可以将Start用作协程。它与其他协程一样工作:一直运行到yield returnyield break或函数结束。后两个结束协程,否则等待,然后继续运行。最好使用Update中的标记来控制协程。

如果您需要每帧都运行的脚本,请使用Update

答案 1 :(得分:2)

首先,创建一个名为“ Applespawner”的新的空游戏对象。将Applespawner.cs放入其中。

更改此

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

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

您在isRunning中将Awake()设置为0,在Update函数中调用IEnumerator毫无意义。

您应将此行添加到Applespawner.cs public GameObject Apple = null;

并将Apple预制件附加到编辑器中Applespawner.cs的Apple插槽中。如果您不知道如何制作预制件,请用谷歌搜索。

我认为有两种最好的方法可以每隔X秒启动游戏对象。

  • 第一种方式

    public IEnumerator Wait()
    {
        while(true){
            yield return new Waitforseconds(X seconds);
            Instantiate an object.
        }
     }
    
  • 第二种方式

    float spawnRate = 1f;
    float nextTimeToSpawn = 0;
    
    private void Update()
    {
        if (Time.time >= nextTimeToSpawn){
    
            nextTimeToSpawn = Time.time + 1f / spawnRate;
            //Spawn something
        }    
    }
    

我个人更喜欢第二种方式。希望这会有所帮助。