List/Array Not Updating

Hi guys,

I’ve been trying to hash together a script to find the nearest target objects with tag ‘Target’ in proximity to a player so I can use them to target the nearest target, next nearest target etc.

I attempted to do this by instantiated an array to hold all the targets in the level, then applying conditions to them and filling a List based on these conditions, which are then converted into an a different, local array.

However, despite the function being called from Update, the function only seems to run once-i.e. when the player moves out of range, the target_local array is not updated. I get the feeling this is because I’m not familiar with lists and therefore have used something wrongly.

Cheers,

Popup Pirate

// This is an excerpt from a camera script so other functions (i.e. Start()) are present that are not used in my current problem.

using UnityEngine;
using System.Collections;

public class Camera_Control : MonoBehaviour {
	public GameObject player;
	public float targeting_distance=500f;
	public GameObject[] targets;
	public GameObject[] targets_local;

	private System.Collections.Generic.List<GameObject> target_list = new System.Collections.Generic.List<GameObject>();


	void Start() {

	}


	void Update(){
		FindTargets ();

	}

	void LateUpdate() {


	}

	void FindTargets(){
		targets= GameObject.FindGameObjectsWithTag("Target");
		for (int i=0; i<targets.Length; i++){
			float distance=Vector3.Distance(player.transform.position, targets*.gameObject.transform.position);*

if (distance<targeting_distance && targets.gameObject.tag==“Target” && targets.gameObject.name!=player.gameObject.name&& target_list.Contains(targets*.gameObject)==false){
target_list.Add(targets.gameObject);
_ }_
if (distance>targeting_distance && targets.gameObject.name!=player.gameObject.name){
target_list.Remove(targets.gameObject);
_ }_
targets_local= target_list.ToArray();
_ }*_

* }*

You could use this thread:

m_targetList.Sort(delegate(GameObject c1, GameObject c2){
    return Vector3.Distance(this.transform.position, c1.transform.position).CompareTo
            ((Vector3.Distance(this.transform.position, c2.transform.position)));   
    });

this code above will order your list so the first one is the closest.

I would call the ordering at some frequency like every 0.5f second so that it does not affect too much. Even once per second would be enough.

Then when you iterate through the list to find the closest ones, you can stop the iteration as soon as one is too far since any other after will automatically be too far.

Now for the method:

GameObject [] FindTargets(){
   List<GameObject> list = new List<GameObject>();
   GameObject [] targets= GameObject.FindGameObjectsWithTag("Target");
    foreach(GameObject obj in targets){
        float distance=Vector3.Distance(player.transform.position, obj.transform.position);
        if (distance < targeting_distance && target_list.Contains(obj)==false){
            list.Add(obj);
        }     
    }
    return list.ToArray();
}

So now you do not need the List as global, you create a new list when needed and return it as array. So your Update becomes:

void Update()
{
    target_local = FindTargets();
}

It is not necessary to check again for tag since the objects in the collection are sure to be with it. If your player is not tag as target then no need to check for match. if so add this line at the beginning of the foreach loop:

if(obj == player)
{
    continue;
}

Using a new list remove the checking if the old one contains and the removal as well.

One thing I would recommend is that the target object should probably be added to a list when they are created so that you do not need to fetch them each time.

Here is the complete code that returns an array of the players nearest targets within a set targeting range, with target_local[0] being the closest gameobject within range and target[n] being the nth largest gameobject in range:

using UnityEngine;
using System.Collections;

public class Target_Control : MonoBehaviour {

	public float targeting_distance=50f;
	public bool targeting_on;
	public GameObject[] targets_local;
	
	private GameObject temp;
	private GameObject[] targets;


	void Start () {
	
	}
	
	// Update is called once per frame
	void Update () {

		targets_local = FindTargets ();
		Sort ();

	
	}


	GameObject [] FindTargets(){
		GameObject [] targets= GameObject.FindGameObjectsWithTag("Target");
		System.Collections.Generic.List<GameObject> target_list = new System.Collections.Generic.List<GameObject>();
		for(int i=0; i<targets.Length; i++){
			float distance=Vector3.Distance(transform.position, targets*.transform.position);*

_ if(targets*.gameObject.name==this.gameObject.name){_
_
continue;_
_
}_
if (distance <= targeting_distance && target_list.Contains(targets.gameObject)==false){
target_list.Add(targets.gameObject);
_ }_
if (distance > targeting_distance && target_list.Contains(targets.gameObject)==true){
target_list.Remove (targets.gameObject);
_ }
}*_

* return target_list.ToArray();
_ }*_

* void Sort(){*
* for (int i=0; i<targets_local.Length; i++) {
for (int j=0; j<targets_local.Length; j++) {
if(Vector3.Distance (transform.position, targets_local.transform.position)<Vector3.Distance (transform.position, targets_local[j].transform.position)){
temp=targets_local;
targets_local=targets_local[j];
targets_local[j]=temp;
_ }
}
}
}*_