List problems

I’m having a problem with updating my list when an enemy dies. Unity gives me the error “Argument is out of range” when line 67 is called. ie, when i try to remove the enemy i just killed. Is this the proper way to do this?

some info: using a trigger to add to the list, and KillTargetInList is called when the enemy dies.

using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class Gouloriginal : MonoBehaviour {
	public Enemy2D enemy2D;
	public Transform target;
	public Transform player;
	public int moveSpeed;
	private Transform goul;
	public int idleDistance = 1;
	public int enemyMaxDistance = 20;
	public int enemyMinDistance = 2;
	//attack vars
	public float attackRange = 2;
	float attackRate = 1f;
	float coolDown = 1;
	public int goulDamage = 10;
	public List<Transform> myList;
	public bool enemyDied; 

	//12+ hours on this fucking script...
	void Awake(){
		goul = transform;
	}
	void Start () {
		myList = new List<Transform> ();
		GameObject po = GameObject.FindGameObjectWithTag("Player");
		player = po.transform;
	}
	void Update (){ 
		Vector3 theScale = transform.localScale;
		theScale.x *= -1;
		transform.localScale = theScale;
	}
	void FixedUpdate () {
		if( target != null  Vector3.Distance (goul.position, target.position) < attackRange){
			target = myList [0];
				if (Time.time >= coolDown){
					GoulAttack();
					coolDown = Time.time + attackRate;
				}
		}
		if (target == null || Vector3.Distance (goul.position, target.position) > enemyMaxDistance){
			if (Vector3.Distance (goul.position, player.position) > idleDistance) {
				if (player.position.x < goul.position.x) {
						goul.position -= goul.right * moveSpeed * Time.deltaTime; // player is left of goul, move left
				} else if (player.position.x > goul.position.x) {
						goul.position += goul.right * moveSpeed * Time.deltaTime; // player is right of goul, move right
					  }
				}
		}
		else if (target != null) {
			if (Vector3.Distance (player.position, target.position) < enemyMaxDistance  Vector3.Distance (goul.position, target.position) > enemyMinDistance) {
					if (target.position.x < goul.position.x) {
						goul.position -= goul.right * moveSpeed * Time.deltaTime; // target is left of goul, move left
					} else if (target.position.x > goul.position.x) {
						goul.position += goul.right * moveSpeed * Time.deltaTime; // target is right of goul, move right
					}
			}
		}
		Debug.DrawLine(player.position, goul.position, Color.yellow);
		if (target != null) {
						Debug.DrawLine (target.position, goul.position, Color.green);
		}
	}
	public void KillTargetInList(){
		myList.RemoveAt (0);
						Debug.Log ("enemy dead");
	}
	void OnTriggerEnter (Collider tripwire){
		if (tripwire.tag == "Enemy") {
			myList.Add (tripwire.transform);
			target = myList [0];
		}
	}
	private void GoulAttack(){
				//find target with tag
		if (target != null  target.gameObject.tag == "Enemy") {
								//send damage call to enemy script
								target.gameObject.SendMessage ("EnemyDamaged", goulDamage, SendMessageOptions.DontRequireReceiver);
		}
	}
}

You don’t seem to add anything to the List (myList)

line 72

best method to debug list is simply check the count

so line 67-68

if(myList.count > 0)
  mylist.RemoveAt(0);
else
 Debug.log("nothing in list");

however the problem with this approach is that it always remove the first item irregardless which is not a good idea unless it is ordered.

a proper method would be

if(myList.Contains(tripwire.transform))
   myList.remove(tripwire.transform);

just my 2cent

the debug.log works. so how do i remove something from a list that is destroyed?

Thats a very broad question and it depends on your approach, you can do it from the object(tripwire), the player’s controller or GameController.

a simple example, so from the tripwire object, assuming you are using trigger:
tripwire object itself

private GameController gameController;
void Start(){
    gameController = GameObject.FindGameObjectWithTag("GameController").GetComponent<GameController>();
}

void OnTriggerEnter (Collider other){
    if(other.transform.name == "Player"){ //assuming player object is called Player
        gameController.RemoveFromTripWireList(other.transform); //call the method from gameController
        Destroy(gameObject);
    }
}

in similar respect if the context is player’s object:
change

void OnTriggerEnter (Collider other){
    if(other.transform.name == "tripWire"){ //assuming tripwire object is called tripWire
        gameController.RemoveFromTripWireList(other.transform); //call the method from gameController
        Destroy(other.gameObject);
    }
}

from a GameController.cs you would simply have to call a public method to the gameController and pass the objects transform over.

using System.Collections.Generic;
private List<Transform> tripwire;

void CreateTripWireObject(){
    Transform curTripwire = Instantiate(....) as Transform;
    myList.Add(curTripwire); //Gamecontroller keep tracks of the tripwire
}

public void RemoveFromTripWireList(Transform tripwireTransform){
        if(myList.Contains(tripwireTransform){
            myList.remove(tripwireTransform);
        {
}

okay, i took your advice and made a game manager.

I’m going to post all the corresponding scripts so you can get the full picture.

player pushes the “F” key to spawn a goul.

how the goul spawns isn’t important.

Goul spawns:

using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class Gouloriginal : MonoBehaviour {
	public Enemy2D enemy2D;
	public EnemyManager enemyManager;
	public Transform target;
	public Transform player;
	public int moveSpeed;
	private Transform goul;
	public int idleDistance = 1;
	public int enemyMaxDistance = 20;
	public int enemyMinDistance = 2;
	//attack vars
	public float attackRange = 2;
	float attackRate = 1f;
	float coolDown = 1;
	public int goulDamage = 10;
	public bool enemyDied; 

	//12+ hours on this fucking script...
	void Awake(){
		goul = transform;
	}
	void Start () {
		GameObject po = GameObject.FindGameObjectWithTag("Player");
		player = po.transform;
	}
	void Update (){ 
		Vector3 theScale = transform.localScale;
		theScale.x *= -1;
		transform.localScale = theScale;
	}
	void FixedUpdate () {
		if( target != null  Vector3.Distance (goul.position, target.position) < attackRange){
			if (Time.time >= coolDown){
					GoulAttack();
					coolDown = Time.time + attackRate;
				}
		}
		if (target == null || Vector3.Distance (goul.position, target.position) > enemyMaxDistance){
			if (Vector3.Distance (goul.position, player.position) > idleDistance) {
				if (player.position.x < goul.position.x) {
						goul.position -= goul.right * moveSpeed * Time.deltaTime; // player is left of goul, move left
				} else if (player.position.x > goul.position.x) {
						goul.position += goul.right * moveSpeed * Time.deltaTime; // player is right of goul, move right
					  }
				}
		}
		else if (target != null) {
			if (Vector3.Distance (player.position, target.position) < enemyMaxDistance  Vector3.Distance (goul.position, target.position) > enemyMinDistance) {
					if (target.position.x < goul.position.x) {
						goul.position -= goul.right * moveSpeed * Time.deltaTime; // target is left of goul, move left
					} else if (target.position.x > goul.position.x) {
						goul.position += goul.right * moveSpeed * Time.deltaTime; // target is right of goul, move right
					}
			}
		}
		Debug.DrawLine(player.position, goul.position, Color.yellow);
		if (target != null) {
						Debug.DrawLine (target.position, goul.position, Color.green);
		}
	}
	public void KillTargetInList(){
		if (enemy2D.enemyDead == true) {
			Debug.Log (enemyManager.myList.Count);
			//myList.RemoveAt(0);
			//target = myList [1];
			target = null;


				}
		else
			Debug.Log("nothing in list");
	}

	private void GoulAttack(){
				//find target with tag
		if (target != null  target.gameObject.tag == "Enemy") {
								//send damage call to enemy script
								target.gameObject.SendMessage ("EnemyDamaged", goulDamage, SendMessageOptions.DontRequireReceiver);
		}
	}
}

when an enemy trips the trigger collider, player passes the transform to the enemy manager:

using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class PlayerPetTarget : MonoBehaviour {

	public Gouloriginal goul;
	public EnemyManager enemyManager;

	void OnTriggerEnter (Collider tripwire){
		if (tripwire.tag == "Enemy") {
			enemyManager.myList.Add (tripwire.transform);
			goul.target = enemyManager.myList [0];
			Debug.Log (enemyManager.myList.Count);
		}
	}
}
using UnityEngine;
using System.Collections;
using System.Collections.Generic;

public class EnemyManager : MonoBehaviour {

	public List<Transform> myList;

	// Use this for initialization
	void Start () {
		myList = new List<Transform> ();
	
	}
	
	// Update is called once per frame
	void Update () {
	
	}
}

BUT when the enemy enters the trigger i get a “Object reference not set to instance of an object” error.

I fixed it. lo and behold you have to initialize script references in the start or awake functions…
http://unitygems.com/script-interaction1/