Hi!
I have been trying to make a script that finds all objects with a specific tag within a set distance, but i can’t find out how to remove a found object from an object list.
Here is my script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;
public class FindZombie : MonoBehaviour
{
public GameObject[] allObjectsWithTag;
private GameObject nearestObject;
public GameObject found;
private Rigidbody rb;
private NavMeshAgent nma;
// Start is called before the first frame update
void Start()
{
nma = GetComponent<NavMeshAgent>();
}
// Update is called once per frame
void Update()
{
allObjectsWithTag = GameObject.FindGameObjectsWithTag("Zombie");
rb = GetComponent<Rigidbody>();
nearestObject = allObjectsWithTag[0];
found = allObjectsWithTag[0];
float distanceToNearest = Vector3.Distance(rb.transform.position, nearestObject.transform.position);
for (int i = 0; i < allObjectsWithTag.Length; i++)
{
if (Vector3.Distance (gameObject.transform.position, allObjectsWithTag[i].transform.position) > 10 == false )
{
allObjectsWithTag.Remove(allObjectsWithTag[i]) // Here is the problem
}
}
for (int i = 0; i < allObjectsWithTag.Length; i++)
{
float distanceToCurrent = Vector3.Distance(rb.transform.position, allObjectsWithTag[i].transform.position);
if (distanceToCurrent < distanceToNearest)
{
nearestObject = allObjectsWithTag[i];
found = allObjectsWithTag[i];
distanceToNearest = distanceToCurrent;
}
}
if (found != null)
{
nma.SetDestination(found.transform.position);
}
}
}
Thank you for your time
A couple of items to consider. Trying to find all the Zombies in the Update loop is not a good idea. Something generated the Zombie I hope. Have that something keep track of all the Zombies and you don’t have to find the GameObjects repeatedly.
You should ideally place all this stuff into a class that manages the Zombies with properties and methods that do what you need without sprinkling it everywhere else. Tell the Zombies class to zombies.Kill(rb) passing along the RigidBody or something that identifies the position you want used (perhaps the Transform is more than enough).
And then have it iterate the array backwards. The array is getting smaller as you remove items.
The reason i put in update, is because the zombies can infect the humans, thus creating more zombies that need to be added to the list.
I’m very new to Unity, so I’m sure you also said a solution to this conundrum, but I have no idea what most of what you said means.
You are however, very welcome to try and explain in greater detail.
Studying concepts and twisting the solutions around in your head is a good way to learn. You placed “some code” in Update because you need it to run regularly. That’s why everyone places code in Update and why Unity added it to the process.
So the question you ask yourself is “what do I place in this Update method that will accomplish my goals without wasting cycles?”.
You locate all the Zombies over and over again. That is generally a waste of time or at a minimum a red flag indicating you should look for a more efficient way to handle it.
Something in your games makes these Zombies. So when you create a new one add it to a list of Zombies. If you destroy one remove it from the list of Zombies. You eliminate the need to look for Zombies in your Update method. As a side benefit if any other part of your game needed to know how many Zombies there were or their name or location you would have to first find all the zombies with the Zombie tag. You’d have the list already.
If the collection of Zombies is empty BTW you wouldn’t process the rest of your code.
Given you should have a class that represents Zombies, it would contain the list of Zombies. It could report how many zombies existed. It could (if handed a transform) figure out the distance to the nearest Zombie. Do you see the benefit yet? If you wanted to know the zombie closest to a player, closest to a door, closest to a the sign that says “beware of zombies” you would pass that object’s transform in and get the distance.
Look up “deleting elements from an array” in any C# (or any language) reference. You iterate the array in reverse (not 0 to length but rather length to 0) because you are affecting the array you are iterating. It is getting smaller. You don’t do that because it is known not to work.
I’ll suggest that you experiment a bit.
Thank you, i will look in to this 