Finding the distance between and object and multiple things.

Hey, I’m making a game in which you control citizens in a town. If you place a citizen next to a resource, I wan’t the citizen to harvest it, and the more citizens next to the resource, the faster it runs out. This is the code I have right now:

using UnityEngine;
using System.Collections;
using System.Collections.Generic;

public class resource : MonoBehaviour {

	public float MaterialOn;
	public Transform myTransform;
	public Selected select;
	public string materialType;
	public Transform[] Citizens; 
	public bool canHit;
	public float citizensOn;

	void Start () 
	{
		myTransform = transform;
	}
	

	void Update () 
	{
		StartCoroutine(Harvest());
		if (MaterialOn <= 0) 
		{
			Destroy (gameObject);
		}
	}

	IEnumerator Harvest()
	{
		foreach (Transform citizen in Citizens) {
			if (Vector3.Distance (citizen.position, myTransform.position) <= 5 && canHit == false) 
			{
				canHit = true;
				Debug.Log ("Harvesting");
				MaterialOn -= 1;
				yield return new WaitForSeconds (2);
				canHit = false;
			}
		}
	}
}

The problem I’m having is that no matter how many citizens I have next to the resource, it depletes at the same rate. Anyone know a solution??

The title you used and the problem you described are different, so I’ll assume your problem is the harvesting rate.

Your code has a few problems.

First, you start the Haverst coroutine on every frame, but the coroutine takes a few seconds to finish (2 seconds times the amount of citizens), so you’ll have A LOT of coroutines running at the same time. I’m not sure what you want to achieve, but starting a coroutine in the Update function without any condition is usually a bad idea. In your case the issues with this are hidden since your code depends on a boolean variable, so most of the started coroutines do nothing and finish. You can solve this storing the started coroutine in a variable and only starting it again if the variable isn’t null. At the end of the coroutine set the variable to null again so the Update restarts it.

Second, in your coroutine you remove 1 unit of material every 2 seconds because you’re waiting 2 seconds before checking for the next citizen. No matter how many citizens you have, the haverst rate will be the same. I guess what you want is to remove 1 per citizen in range, so I’d count them first, then substract the amount of citizens from the material. I think that the code you need is something like this:

 using UnityEngine;
 using System.Collections;
 using System.Collections.Generic;
 
 public class resource : MonoBehaviour {
 
     public float MaterialOn;
     public Transform myTransform;
     public Selected select;
     public string materialType;
     public Transform[] Citizens; 
     public bool canHit;
     public float citizensOn;     
     public Coroutine harvestRoutine;

     void Start () 
     {
         myTransform = transform;
     }

     void Update () 
     {
         if (harvestRoutine != null)
             harvestRoutine = StartCoroutine(Harvest());

         if (MaterialOn <= 0) 
         {
             Destroy (gameObject);
         }
     }
 
     IEnumerator Harvest()
     {
         int closestCitizensCount = 0;
         foreach (Transform citizen in Citizens) {
             if (Vector3.Distance (citizen.position, myTransform.position) <= 5) 
             {
                 closestCitizensCount++;
             }
         }

         MaterialOn -= closestCitizensCount ;
         yield return new WaitForSeconds (2);
         harvestRoutine = null;
     }
 }