Единство, уничтожающее созданный клон, перестает создавать экземпляры - PullRequest
2 голосов
/ 07 мая 2019

У меня есть этот код, чтобы создать спрайт

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

Ответы [ 2 ]

3 голосов
/ 07 мая 2019

Не смешивайте разные обязанности в одном классе.

Это делает ваш код подверженным ошибкам и становится все труднее поддерживать, так как этот класс становится больше. У вас должен быть спавнер, который порождает яблоки, и яблочный сборный с коллайдером. Два разных сценария.

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 return, yield break или до конца функции. Последние два заканчивают сопрограмму, иначе она ждет, а затем продолжает работать. Это лучше, чем флаги в Update управлении сопрограммами.

Если вам нужен скрипт, который должен запускать каждый кадр, тогда используйте Update.

2 голосов
/ 07 мая 2019

Во-первых, создайте новый пустой игровой объект под названием «Яблочник».Поместите в него файл Applespawner.cs.

Измените это

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

на

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

Вы установили isRunning в 0 в Awake(), не имеет смыславызовите IEnumerator в функции обновления.

Вы должны добавить эту строку в свой Applespawner.cs public GameObject Apple = null;

и присоединить ваш префаб Apple к слоту Apple Applespawner.cs в редакторе.Если вы не знаете, как приготовить сборный дом, отправьте его в Google.

Я думаю, что есть 2 лучших способа инициировать игровой объект каждые 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
        }    
    }
    

Лично я предпочитаю второй способ.Надеюсь, это поможет.

...