fix: universe entrance issues where entering behaviours adding more behaviours causing duplicate/missing calls
This commit is contained in:
@@ -11,14 +11,29 @@ public class UniverseEntranceManager : Internal.BehaviourIndependent
|
||||
private readonly ActiveBehaviourCollectorOrdered<int, IEnterUniverse> enterUniverses = new(GetPriority(), SortByAscendingPriority());
|
||||
private readonly ActiveBehaviourCollectorOrdered<int, IExitUniverse> exitUniverses = new(GetPriority(), SortByAscendingPriority());
|
||||
|
||||
private bool isInitialCollectionDone = false;
|
||||
private readonly FastListOrdered<int, IEnterUniverse> toCallEnterUniverses = new(GetPriority(), SortByAscendingPriority());
|
||||
|
||||
protected override void OnEnteredUniverse(IUniverse universe)
|
||||
{
|
||||
// FIXME: This causes an issue when the UniverseEntranceManager is already attached to a UniverseObject then registered into a Universe,
|
||||
// the enter/exit universe collectors call OnUniverseObjectRegistered internally on Assign, but since the Universe calls the OnUniverseObjectRegistered
|
||||
// event it tries to call OnUniverseObjectRegistered again on the same object, causing a duplicate entry error.
|
||||
Debug.Assert.AssertTrue(BehaviourController.Count == 1, $"{nameof(UniverseEntranceManager)} must be in it's own {nameof(IUniverseObject)} with no other {nameof(IBehaviour)}s attached at the moment. Failing to do so might cause instantiation or serialization issues.");
|
||||
enterUniverses.Assign(universe);
|
||||
exitUniverses.Assign(universe);
|
||||
|
||||
// FIXME: the isInitialCollectionDone is for the sole reason of some behaviours
|
||||
// adding more behaviours during entrance calls and the internal workings of
|
||||
// behaviour collector not being able to tell which behaviour was already called
|
||||
// (because it just runs a for loop with the behaviour count, and priority ordering doesn't help as well)
|
||||
// so it sometimes double processes or misses behaviours. A more elegant way of
|
||||
// handling this would be nice but for now it works good enough.
|
||||
//
|
||||
// SIDE NOTE: This same issue has the potential to occur on exitUniverses as well, but I've yet to run
|
||||
// into an instance of it actually happening so... I'm not gonna touch it until the edge case happens.
|
||||
isInitialCollectionDone = false;
|
||||
enterUniverses.Assign(universe);
|
||||
isInitialCollectionDone = true;
|
||||
|
||||
for (int i = toCallEnterUniverses.Count - 1; i >= 0; i--)
|
||||
toCallEnterUniverses[i].EnterUniverse(universe);
|
||||
toCallEnterUniverses.Clear();
|
||||
}
|
||||
|
||||
protected override void OnExitedUniverse(IUniverse universe)
|
||||
@@ -26,8 +41,17 @@ public class UniverseEntranceManager : Internal.BehaviourIndependent
|
||||
enterUniverses.Unassign();
|
||||
exitUniverses.Unassign();
|
||||
}
|
||||
|
||||
private void OnEnterUniverseCollected(IBehaviourCollector<IEnterUniverse> sender, IBehaviourCollector<IEnterUniverse>.BehaviourCollectedArguments args)
|
||||
=> args.BehaviourCollected.EnterUniverse(Universe);
|
||||
{
|
||||
if (!isInitialCollectionDone)
|
||||
{
|
||||
toCallEnterUniverses.Add(args.BehaviourCollected);
|
||||
return;
|
||||
}
|
||||
|
||||
args.BehaviourCollected.EnterUniverse(Universe);
|
||||
}
|
||||
|
||||
private void OnExitUniverseRemoved(IBehaviourCollector<IExitUniverse> sender, IBehaviourCollector<IExitUniverse>.BehaviourRemovedArguments args)
|
||||
=> args.BehaviourRemoved.ExitUniverse(Universe);
|
||||
|
||||
Reference in New Issue
Block a user