1

I want to make a script that loops through all game objects with the tag, Enemy I modified a code snippet from here, and ended up with 2 errors.


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

and

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

If anyone could tell me why this is happening or a solution to this I would be very grateful, thanks in advance! Here is my code:

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 Answers 3

4

FindGameObjectsWithTag as the name hints returns a GameObject[].

In order tog et the attached Rigidbody2D use GetComponent<Rigidbody2D>

It should be either GameObject[] or simply 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;
}

The second one was just a follow up error since you declared objects as a GameObject which indeed as the error says has no GetEnumerator implementation.


In general it is not the best thing to use FindObjectsWithTag repeatedly. I would rather use a pattern with a static list of all existing instances like

// Put this component on your enemy prefabs / objects
public class EnemyController : MonoBehaviour
{
    // every instance registers to and removes itself from here
    private static readonly HashSet<EnemyController> _instances = new HashSet<EnemyController>();
    
    // Readonly property, I would return a new HashSet so nobody on the outside can alter the content
    public static HashSet<EnemyController> Instances => new HashSet<EnemyController>(_instances);

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

and then use

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;
}
Sign up to request clarification or add additional context in comments.

Comments

1

Change GameObject type declaration to var

Or change it to GameObject[] since FindGameObjectsWithTag returns an array of GameObject

Also I wouldnt use FindGameObjectsWithTag its slow. More so in a update method

2 Comments

I changed GameObject to GameObject[] but I still can't figure out how to access the rigid body for that specific object.
You need to get it using GetComponent but it's slow too, create a domain specific type that holds enemy logic
1

First off, change GameObject to GameObject[] because FindGameObjectsWithTag returns a GameObject array. Be careful not to confuse it with FindGameObjectWithTag without the s which returns a single GameObject

Secondly, I think it would be best to have a separate Enemy script or something like that and assign them to each enemy rather than using FindGameObjectsWithTag which is very slow.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.