I recently switched out some arrays for Lists in most of my scripts as they are easier to use. The problem though is that brought out some new errors. They are :
- InvalidOperationException: Collection was modified; enumeration operation may not execute.
- ArgumentOutOfRangeException: Index was out of range. Must be non-negative and less than the size of the collection.
According to the errors, the problem is on line 96 of the Gorean Turret and line 37 of the POW_Camp. A couple other scrips also have that issue, but if I figure out what's wrong with these two I should be able to figure out how to fix the rest.
I searched up what to do about these errors and found a couple solutions. I changed the foreach loops to for (var i=0;) style loops. This was supposed to work, but unfortunately not.
My problem is how do I fix these errors. How do I need to change my scripts so there are no errors. As a side note, if you find something that can be shortened, please tell me. I have a feeling that the code is also longer than it needs to be.
Here is the POW_Camp Script :
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class POW_Camp : MonoBehaviour
{
public GameObject AmmunitionsDump;
public GameObject Explosion;
public GameObject Fences;
public List<GameObject> Prisoners;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
if (AmmunitionsDump.GetComponent<Health>().CurrentHealth<=0)
{
AmmunitionsDump.SetActive(false);
Explosion.SetActive(true);
}
//If the ammunitiondump is destroyed then destroy fences
if (AmmunitionsDump.activeSelf == false)
{
Destroy(Fences);
//Activate POWs
for (var i=0;i<Prisoners.Count; i++)
{
if (Prisoners[i] == null)
{
Prisoners.Remove(Prisoners[i]);
}
if (Prisoners[i] != null)
{
Prisoners[i].GetComponent<PlayerData>().Captured = false;
}
}
}
}
}
Here is the GoreanTurret Script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class GoreanTurret : MonoBehaviour
{
public GameObject Projectile;
public GameObject FiringPoint;
public GameObject GunTower;
public GameObject HealthBar;
public List<GameObject> TargetsWithinRange = new List<GameObject>();
public float FiringRange = 100;
public GameObject CurrentTarget;
public bool TargetLocked;
// Start is called before the first frame update
void Start()
{
InvokeRepeating("Shoot", 1, 0.5f);
HealthBar.GetComponent<Slider>().maxValue = gameObject.GetComponent<Health>().MaxHealth;
HealthBar.GetComponent<Slider>().value = gameObject.GetComponent<Health>().CurrentHealth;
}
// Update is called once per frame
void Update()
{
FindTargetsWithinRange(FiringRange, TargetsWithinRange);
TargetManager(TargetsWithinRange, FiringRange);
HealthBar.GetComponent<Slider>().value = gameObject.GetComponent<Health>().CurrentHealth;
//Look at Target if Target is Locked
if (TargetLocked)
{
GunTower.transform.LookAt(CurrentTarget.transform);
}
// If target is destroyed then set targetLocked to false and target to null;
if (CurrentTarget != null)
{
if (CurrentTarget.GetComponent<Health>().CurrentHealth <= 0)
{
TargetLocked = false;
CurrentTarget = null;
}
}
// If one of the targets in the target list is destroyed then remove that
foreach (GameObject possibleTarget in TargetsWithinRange)
{
if (possibleTarget == null || possibleTarget.GetComponent<Health>().CurrentHealth<=0 || possibleTarget.GetComponent<Health>()==null)
{
TargetsWithinRange.Remove(possibleTarget);
}
}
if (CurrentTarget == null)
{
TargetLocked = false;
CurrentTarget = null;
}
// If target is lost and there are still targets, then switch target
if (TargetLocked == false && (CurrentTarget == null || CurrentTarget.GetComponent<Health>().CurrentHealth<0) && TargetsWithinRange.Count>0)
{
if (TargetsWithinRange[0] != null)
{
CurrentTarget = TargetsWithinRange[0];
TargetLocked = true;
}
}
}
void FindTargetsWithinRange(float range, List<GameObject> TargetList)
{
Collider[] colliders = Physics.OverlapSphere(gameObject.transform.position, range);
foreach (Collider collider in colliders)
{
if (collider.gameObject.GetComponent<PlayerData>())
{
if (collider.gameObject.GetComponent<PlayerData>().Captured == false && TargetList.Contains(collider.gameObject) == false)
{
TargetList.Add(collider.gameObject);
}
}
}
}
void TargetManager(List<GameObject> TargetList, float MaxRange)
{
for (var i = 0; i < TargetList.Count; i++)
{
//If the Target is null or inactive then remove that target or if it has no health
if (TargetList[i] == null || TargetList[i].activeSelf == false || TargetList[i].GetComponent<Health>().CurrentHealth <= 0)
{
TargetList.Remove(TargetList[i]);
if (TargetList[i] == CurrentTarget)
{
TargetLocked = false;
}
}
//If the target is too far
if (Vector3.Distance(gameObject.transform.position, TargetList[i].transform.position) > MaxRange)
{
TargetList.Remove(TargetList[i]);
if (TargetList[i] == CurrentTarget)
{
CurrentTarget = null;
TargetLocked = false;
}
}
}
//If there is no target and the TargetLocked is false then Set a new target
if (CurrentTarget == null && TargetLocked == false && TargetList.Count > 0)
{
CurrentTarget = TargetList[0];
TargetLocked = true;
}
// If target is destroyed then set targetLocked to false and target to null;
if (CurrentTarget != null && CurrentTarget.activeSelf == true && CurrentTarget.GetComponent<Health>().CurrentHealth > 0)
{
if (CurrentTarget.GetComponent<Health>().CurrentHealth <= 0)
{
TargetLocked = false;
CurrentTarget = null;
}
}
}
public void Shoot()
{
if (TargetLocked == true)
{
Instantiate(Projectile, FiringPoint.transform.position, FiringPoint.transform.rotation);
}
}
}