I’d like to be able to toggle an OnIntersectionEnterTrigger
/OnIntersectionExitTrigger
action on or off based on game state, but I have a problem that toggling it off and back on again does not behave as expected if there is an active collision while toggling. I created the behavior below to manage the actions and toggle it via addBehavior
/removeBehavior
.
However, if I remove the behavior and unregister the actions while an intersection is active, that formerly active intersection remains in mesh._intersectionsInProgress
indefinitely. Later, when adding the behavior back in, I see the effect of that lingering behavior as follows:
Scenario: Player has returned to the same zone they were in when the action was unregistered
- Expected behavior: onIntersectionEnter is triggered
- Observed behavior: no action
Scenario: Player is not in a zone
- Expected behavior: no action
- Observed behavior: onIntersectionExit is triggered
Troubleshooting steps that I have tried:
- Disposing & recreating action manager when toggling
- Discarding & recreating
ExecuteCodeAction
s when toggling - Manually triggering the exit action with
ActionManager.processTrigger
While I’d expect the action to clean up its own state when being removed, I’d be happy to manually clear the intersections, but I cannot find any way to do that without modifying the private mesh._intersectionsInProgress
property directly.
import { Mesh, ActionManager, ExecuteCodeAction } from "@babylonjs/core";
export default class ActiveZoneBehavior {
/** ActiveZoneBehavior
* Triggers a callback when a target mesh enters or exits this mesh's AABB
* @param {Mesh} meshToWatch
* @param {Function} cbEnter - call when target mesh enters zone
* @param {Function} cbExit - call when target mesh exits zone
*/
constructor(meshToWatch, cbEnter, cbExit) {
this.name = "ActiveZoneBehavior";
this.meshToWatch = meshToWatch;
this.cbEnter = cbEnter;
this.cbExit = cbExit;
}
init() {
this.enterAction = new ExecuteCodeAction(
{
trigger: ActionManager.OnIntersectionEnterTrigger,
parameter: this.meshToWatch
},
this.cbEnter
);
this.exitAction = new ExecuteCodeAction(
{
trigger: ActionManager.OnIntersectionExitTrigger,
parameter: this.meshToWatch
},
this.cbExit
);
}
attach(mesh) {
if (!mesh.actionManager) {
mesh.actionManager = new ActionManager(mesh.getScene());
}
mesh.actionManager.registerAction(this.enterAction);
mesh.actionManager.registerAction(this.exitAction);
this.mesh = mesh;
}
detach() {
if (!this.mesh || !this.mesh.actionManager) {
return;
}
this.mesh.actionManager.unregisterAction(this.enterAction);
this.mesh.actionManager.unregisterAction(this.exitAction);
}
}