Bug:
An ArgumentException occurs When BehaviorManager::EnableBehavior(Behavior) is called multiple times before the BehaviorTree has completed loading
Steps
1. From the inspector for a BehaviorTree component, ensure that 'AsynchronousLoad' is checked and 'Star When Enabled' is false.
2. From the Awake of a component that is attached to the same game object, call 'm_BehaviorTree .EnableBehavior( )' twice.
3. Press play
Observed
Note that the exception occurs because the behavior is added to the activeThreads list of the BehaviorManager twice because
Inside the EnableBehavior then following does not trigger an early exit if EnableBehavior is called multiple times as the behavior is not enabled until LoadBehaviorComplete is called.
.
A simple guard will fix the issue:
An ArgumentException occurs When BehaviorManager::EnableBehavior(Behavior) is called multiple times before the BehaviorTree has completed loading
ArgumentException: An item with the same key has already been added. Key: BT.AI.Default - Behavior
System.Collections.Generic.Dictionary`2[TKey,TValue].TryInsert (TKey key, TValue value, System.Collections.Generic.InsertionBehavior behavior) (at <f646c7a159d243a7909d5204af0f0c56>:0)
System.Collections.Generic.Dictionary`2[TKey,TValue].Add (TKey key, TValue value) (at <f646c7a159d243a7909d5204af0f0c56>:0)
BehaviorDesigner.Runtime.BehaviorManager.LoadBehaviorComplete (BehaviorDesigner.Runtime.Behavior behavior, BehaviorDesigner.Runtime.BehaviorManager+BehaviorTree behaviorTree) (at Assets/External/Behavior Designer/Runtime/BehaviorManager.cs:525)
BehaviorDesigner.Runtime.BehaviorManager+<CheckThreadLoaders>d__78.MoveNext () (at Assets/External/Behavior Designer/Runtime/BehaviorManager.cs:381)
UnityEngine.SetupCoroutine.InvokeMoveNext (System.Collections.IEnumerator enumerator, System.IntPtr returnValueAddress) (at /Users/bokken/build/output/unity/unity/Runtime/Export/Scripting/Coroutines.cs:17)
UnityEngine.GUIUtilityrocessEvent(Int32, IntPtr, Boolean&) (at /Users/bokken/build/output/unity/unity/Modules/IMGUI/GUIUtility.cs:190)
Steps
1. From the inspector for a BehaviorTree component, ensure that 'AsynchronousLoad' is checked and 'Star When Enabled' is false.
2. From the Awake of a component that is attached to the same game object, call 'm_BehaviorTree .EnableBehavior( )' twice.
3. Press play
Observed
Note that the exception occurs because the behavior is added to the activeThreads list of the BehaviorManager twice because
public class CreateBug : Monobehaviour
public BehaviorTree m_BehaviorTree;
void Awake(){
m_BehaviorTree = GetComponent<BehaviorTree>();
m_BehaviorTree .EnableBehavior( );
m_BehaviorTree .EnableBehavior( );
}
}
Inside the EnableBehavior then following does not trigger an early exit if EnableBehavior is called multiple times as the behavior is not enabled until LoadBehaviorComplete is called.
.
if (IsBehaviorEnabled(behavior)) {
return;
A simple guard will fix the issue:
Code:
[QUOTE]
from the BehaviorManager class:
public void EnableBehavior(Behavior behavior)
{
BehaviorTree behaviorTree;
//-- Added Start
if ( behavior.waitingForLoadThread )
{
return;
}
//-- Added End
if (IsBehaviorEnabled(behavior)) {. //this is not enough to ensure that EnableBehavior exits easy when aysncLoad is enabled
return;
}
...
...
...
if (behavior.AsynchronousLoad) {
...
....
....
//-- Added Start
behavior.waitingForLoadThread = true;
//-- Added End
activeThreads.Add(loader); //code will guard against behavior being added to activeThread multiple times
....
....
.....
} else {
behaviorTree = LoadBehavior(behavior, behavior.gameObject, behavior.gameObject.name, behavior.transform);
LoadBehaviorComplete(behavior, behaviorTree);
}
}
[/QUOTE]