Removing units from Dictornary - missing reference exception

Hi guys,

I have two teams which are using a base entity script for all units. These entities are added to an entity/spawn manager which has a dictionary:

public Dictionary<Team, List> entitiesByTeam = new Dictionary<Team, List>();

The issue I am having is when the entity is destroyed upon death of the unit it will throw a missing reference exception error. Upon death of the unit I have the following code :

public virtual void Die()
    {
        Debug.Log(transform.name + "died.");
        entityManager.RemoveEntity(entity);
    }

To remove it from the dictionary and entity manager:

public void RemoveEntity(BaseEntity entity)
    {
        entitiesByTeam[entity.myTeam].Remove(entity);
        allEntities.Remove(entity);
        Destroy(entity.gameObject);
    }

Some more methods for reference:

public List<BaseEntity> GetEntitiesAgainst(Team enemyTeam)
    {
        switch (enemyTeam)
        {
            case Team.blueTeam:
                return entitiesByTeam[Team.redTeam];
            case Team.redTeam:
                return entitiesByTeam[Team.blueTeam];
            /*case neutral: // Setup neutral jungle units here
                break;*/
            default:
                return entitiesByTeam[Team.neutral];
        }

    }
protected void FindTarget()
    {
        var allEnemies = EntityManager.instance.GetEntitiesAgainst(myTeam); //One team is not finding the currentTarget from the other team. Need to fix.

        float minDistance = Mathf.Infinity;
        BaseEntity candidateTarget = null;
        foreach (BaseEntity e in allEnemies)
        {
                if (candidateTarget == null)
                {
                    candidateTarget = e;
                    //Debug.Log("Assigning any knight as closest.");
                }
                else
                {
                    if (Vector3.Distance(e.transform.position, currentPosition.position) <=minDistance)
                    {
                        //Debug.Log("Finding the closest enemy.");
                        minDistance = Vector3.Distance(e.transform.position, currentPosition.position);
                        candidateTarget = e;
                    }
                }
        }
        currentTarget = candidateTarget;
    }

Honestly thought this code was working. I have gone through and followed a youtube tutorial that seemed to have worked. Maybe I missed something. Please let me know if you can spot anything obvious.

Cheers,

Lettus

Copy/paste the exact error message. Does it have a file, line number, stack trace, anything like that? That might help in narrowing things down.

Are you sure you want to be using a List of units rather than a HashSet? If you don’t care what order the units are listed within the collection, and you aren’t intentionally putting a single unit into the list more than once, then a HashSet should meet your needs and would probably be more efficient. And it occurs to me that if you did somehow accidentally add a unit to your list more than once, then List.Remove would only remove the first one, and that could be a cause of the error you’re getting.

Ahh that makes sense. thanks so much. I don’t think the order is important.

MissingReferenceException: The object of type ‘BaseEntity’ has been destroyed but you are still trying to access it.
Your script should either check if it is null or you should not destroy the object.
BaseEntity.FindTarget () (at Assets/Scripts/BaseEntity.cs:152)
BaseEntity.Update () (at Assets/Scripts/BaseEntity.cs:84)
Basically it is referring to the lines of code that access the List GetEntitiesAgainst(Team enemyTeam) method.

I was using the dictionary to distinguish the different teams. Can I still do this with HashSet? Also I am instantiating the units containing a base entity script every 10 seconds.

Ok I found it. I had called the same methods (adding the new entity to the entitiesByTeam list) in the start method of the BaseEntity. So it was adding the same entity twice. Now to fixing more unusual bugs it seems.

Yes, just replace your Dictionary<Team, List> with a Dictionary<Team, HashSet>