Уничтожить указанный c дочерний объект сборного объекта в c# / Unity - PullRequest
0 голосов
/ 26 мая 2020

Я много ищу, но не нашел ответа. Моя проблема: я создаю несколько Gameobject Prefab, каждый из которых состоит из двух дочерних объектов: препятствия и оценочной зоны. Я хочу уничтожить зону очков (только в этом конкретном экземпляре c), когда игрок касается препятствия. Итак, во время выполнения моя иерархия выглядит так:

  • -ObjectPrefab (clone)
  • --- Scorezone
  • --- Препятствие
  • - ObjectPrefab (Clone)
  • --- Scorezone
  • --- Препятствие
  • ...

Итак, мне нужно найти ОДИН дочерний игровой объект (не Преобразование), чтобы затем уничтожить его. Я пробовал несколько кодов, но ни один из них не работал. Вот код с тремя вариантами, которые я пробовал, но ни одна из них не сработала. всех созданных объектов.

Альтернатива 2:

Destroy(collision.gameObject.transform.parent.gameObject.FindWithTag("scorezone"));

Альтернатива 2 для меня будет звучать как logi c, но я получаю сообщение об ошибке «Преобразование не содержит определения для« FindWithTag » .

Альтернатива 3:

foreach (Transform child in collision.gameObject.transform)
  {
   if (child.tag == "scorezone")
      {
        Destroy(child.gameObject);
      }
  }

}

Альтернатива 3 не выдает ошибки, но на самом деле ничего не делает, когда игрок сталкивается с препятствием.

Я очень благодарен за некоторую помощь , заранее спасибо!

1 Ответ

0 голосов
/ 26 мая 2020

Сохраните ссылку!

Если это действительно «сборная», это означает, что вы используете ее как актив и инстанцируете ее во время выполнения, лучшим способом (в моих глазах и с точки зрения производительности) было бы использовать сериализованное поле:

// Put this component on your obstacle
public class ObjectController : MonoBehaviour
{
    // Drag the according object here via the Inspector in the prefab
    // => when the prefab is Instantiated this field is already referenced
    [SerializeField] private GameObject _scoreZone;

    // Read-only access to the reference
    public GameObject ScoreZone => _scoreZone;
}

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

, а затем

private void OnCollisionEnter2D(Collision2D collision) 
{
    // Rather use CompareTag which is slightly more efficient
    // and adds some security (== silently fails if typo, CompareTag throws an exception instead)
    if (collision.gameObject.CompareTag("obstacle")) 
    {  
        var controller = collision.gameObject.GetComponent<ObjectController>();
        if(controller) 
        { 
            Destroy(controller.ScoreZone); 
        }
    }
}

По индексу

В качестве альтернативы, но ошибка prone вы можете просто использовать index. Вы уже знаете, что есть только 2 дочерних элемента, первый из которых - Scorezone с индексом 0, поэтому вы также можете сделать

if (collision.gameObject.CompareTag("obstacle")) 
{  
    var scoreZone = collision.transform.parent.GetChild(0);
    Destroy(scoreZone); 
}

По имени

Используя имя, которое вы также можно использовать Find - я бы не рекомендовал это! Это подвержено ошибкам и медленно

if (collision.gameObject.CompareTag("obstacle")) 
{  
    var scoreZone = collision.transform.parent.Find("ScoreZone");
    Destroy(scoreZone); 
}
...