- Home /
Dictionary suddenly loses its items
I have a dictionary containing several items, which are never removed through code. However, at random times, dictionary loses all its items.
I am very puzzled what could be causing this.
Edit: based on feedback from comments.
1) Action is not Monobehaviour. Does that make a difference?
2) When items are lost, all items are lost, i.e. dictionary is empty, but not null.
3) The issue occurs randomly, that is, not every game run, not at exact same time, not after a specific action.
4) Actions should not destroy themselves by their code. They are just classes that do math and move gameobjects.
5) Before the issue, actions perform as intended, i.e. are called by BehaviouSystem by key and do respective calculations and actions.
6) The NoneAction is just an inmplementation of the interface, with all functions being empty, that means logic should not be removing anything from the dictionary for sure.
Dictionary [ActionDictionary] is not referenced anywhere else, except for this class:
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public enum Action
{
Eat,
None,
}
public class BehaviourSystem : MonoBehaviour
{
private float reactionPeriod;
private float timeWithoutReaction;
private Action CurrentStrategy = Action.None;
private Dictionary<Action, IAction> ActionDictionary = new Dictionary<Action, IAction>();
void Awake()
{
InitStats();
InitActions();
}
#region Initialization
void InitStats()
{
reactionPeriod = 1.0F;
timeWithoutReaction = 0.0F;
}
void InitActions()
{
ActionDictionary.Add(Action.None, new NoneAction());
List<List<ObjectTag>> edibleTagCombinations = new List<List<ObjectTag>>()
{
new List<ObjectTag>(){ ObjectTag.Edible, ObjectTag.Small, ObjectTag.Plant }
};
ActionDictionary.Add(Action.Eat, new EatAction(gameObject.transform, edibleTagCombinations));
}
#endregion
void Update()
{
timeWithoutReaction += Time.deltaTime;
if(timeWithoutReaction > reactionPeriod)
{
timeWithoutReaction -= reactionPeriod;
CurrentStrategy = GetBestAction();
ActionDictionary[CurrentStrategy].MakeDecision();
}
}
private void FixedUpdate()
{
ActionDictionary[CurrentStrategy].PerformAction();
}
private Action GetBestAction()
{
Action bestAction = Action.None;
float bestActionScore = float.MinValue;
foreach (var potentialAction in ActionDictionary)
{
float actionScore = potentialAction.Value.GetActionPriorityScore();
if (actionScore > bestActionScore)
{
bestActionScore = actionScore;
bestAction = potentialAction.Key;
}
}
return bestAction;
}
}
This isn't relevant, but do be careful with creating an enum called Action
while still importing System
directly. System.Action
is a delegate type for methods without parameters or return values and your Action
enum type being declared in the global namespace might give you some weird behavior to anything using the System namespace's version of Action
as something like a coroutine callback, for example.
Right, the Action name collision would be my first concern. Though as long as it's defined in the global namespace it will always shadow the types defined in actual namespaces. The compiler will only complain if you have two types in equal priority namespaces since it can't tell which you want to use. Generally: global > otherNamespace.
However what confuses me a bit is that he said he has "several" items in the dictionary. However with that enum as key there can at max only be exactly 2 items: "None" or "Eat". Of course maybe he want's to add more in the future, however I don't really get the issues here. Which "item" is lost here? If there are only two in the dictionary and you loose one you would only have one left. Though the item "None" seems like a "null" / not used replacement. So effectively you only have one useable item at the moment. This question needs some serious clarifications on the actual issue.
The GetBestAction method iterates through all items (so the two items there are) and use the method GetActionPriorityScore from the interface IAction. We have no idea what value the "NoneAction" class and the "EatAction" class will return
I don't see anything obviously wrong with this code. Is the problem purely random? Or can you cause it to happen through a certain set of circumstances? i.e. Every time the Eat action is performed, the dictionary goes empty?
$$anonymous$$y first guess would be, that your Actions destroy themselves when they perform (i.e. remove themselves)? Does that make sense?
Answer by Arteminio777 · Dec 18, 2019 at 11:00 AM
After testing around, it appears that the dictionary becomes empty, if during runtime I make changes to any source file and save it.
Is this an expected behaviour?
EDIT: Comment confirms that it is indeed an issue, which can cause a dictionary to go empty.
Yes, this is expected. When you make any script changes, you should restart the run of the game, otherwise this, and other issues will occur. I changed my setting to automatically exit the run when a script change is detected, to stop this kind of confusion :)