Цикл по игровым объектам Unity - PullRequest
0 голосов
/ 18 июня 2020

Я пытаюсь создать игру, в которой пользователь управляет квадратом, а другие вражеские фигуры движутся к нему. Поэтому я подумал, что было бы неплохо пропустить l oop через все игровые объекты с тегом Enemy. Однако мне пришлось изменить фрагмент кода, который я нашел из здесь , но затем я получил 2 ошибки.


Cannot Implicitly convert 'Unity.GameObject[]' to 'Unity.GameObject'

и

Error   CS1579  foreach statement cannot operate on variables of type 'GameObject' because 'GameObject' does not contain a public instance definition for 'GetEnumerator'

Если бы кто-нибудь мог сказать мне, почему это происходит, или решение этой проблемы, я был бы очень благодарен, заранее спасибо! Вот мой код:

void FixedUpdate()

{
    GameObject objects = GameObject.FindGameObjectsWithTag("Enemy");
    var objectCount = objects.Length;
    foreach (var obj in objects)
    {
        // Move the players accordingly
        //var rb = 
        Vector2 direction = (player.position - transform.position).normalized;
        obj.rigidbody.velocity = direction * moveSpeed;

    }
}

Ответы [ 3 ]

1 голос
/ 18 июня 2020

Прежде всего, измените GameObject на GameObject[], потому что FindGameObjectsWithTag возвращает массив GameObject. Будьте осторожны, чтобы не путать его с FindGameObjectWithTag без s, который возвращает единственный GameObject

Во-вторых, я думаю, что было бы лучше иметь отдельный сценарий Enemy или что-то в этом роде и назначить их каждого врага вместо использования FindGameObjectsWithTag, что очень медленно.

1 голос
/ 18 июня 2020

FindGameObjectsWithTag в качестве подсказок по имени возвращает GameObject[].

Чтобы связать прикрепленный Rigidbody2D, используйте GetComponent<Rigidbody2D>

Это должно быть либо GameObject[], либо просто var

/*GameObject[]*/ var objects = GameObject.FindGameObjectsWithTag("Enemy");
var objectCount = objects.Length;
foreach (var obj in objects)
{
    // Move the players accordingly
    var rb = obj.GetComponent<Rigidbody2D>()
    Vector2 direction = (player.position - transform.position).normalized;
    rb.velocity = direction * moveSpeed;
}

Вторая была просто последующей ошибкой, поскольку вы объявили objects как GameObject, что действительно, как говорится в ошибке не имеет реализации GetEnumerator.


В общем, многократно использовать FindObjectsWithTag - не лучший вариант. Я бы предпочел использовать шаблон со списком static всех существующих экземпляров, например

// Put this component on your enemy prefabs / objects
public class EnemyController : MonoBehaviour
{
    // every instance registers to and removes itself from here
    public static HashSet<EnemyController> Instances = new HashSet<EnemyController>();

    // If possible already drag the Rigidbody into this slot via the Inspector!
    [SerializedField] private Rigidbody2D rb;

    // public read-only access
    public Rigidbody2D Rb => rb;

    private void Awake()
    {
        if(!rb) rb = GetComponent<Rigidbody2D>();
        Instances.Add(this);
    }


    private void OnDestroy()
    {
        Instances.Remove(this);
    }
}

, а затем использовать

var enemies = EnemyControler.Instances;
foreach (var enemy in enemies)
{
    // Move the players accordingly
    Vector2 direction = (player.position - transform.position).normalized;
    enemy.Rb.velocity = direction * moveSpeed;
}
1 голос
/ 18 июня 2020

Измените объявление типа GameObject на var

Или измените его на GameObject[], поскольку FindGameObjectsWithTag возвращает массив GameObject

Также я бы не использовал FindGameObjectsWithTag это медленно. Тем более в способе обновления

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...