playMaker

Author Topic: Global events are ignored if called inside OnExit()  (Read 1300 times)

PollitronicDev

  • Playmaker Newbie
  • *
  • Posts: 13
Global events are ignored if called inside OnExit()
« on: November 19, 2021, 06:19:21 PM »
    Hello fellow devs!

    As the title says - calling a global event via SendEvent() from an action's OnExit() function will cause the event to be ignored and the FSM will still transition to whatever state it was transitioning regardless of the event.

    To illustrate the issue, picture an FSM like this:

All states are empty except the one selected, and RESET_TEST, START_TEST and EVENT_SUCCESS events are global.

    The PM_TransitionTest action is like this:
Code: [Select]
namespace HutongGames.PlayMaker.Actions
{
    public class PM_TransitionTest : FsmStateAction
    {
        public override void OnExit()
        {
            PlayMakerFSM cFSM = Owner.gameObject.GetComponent<PlayMakerFSM>();
            cFSM.SendEvent( "EVENT_SUCCESS" );
        }
    }
}

    The logic of the test is:
- Send START_TEST (via Inspector) to start the test.
- After 1 second in Test_Wait, will try to transition to 'Test_Fail'.
- As part of the transition, the OnExit() in PM_TransitionTest will execute, which will send the 'EVENT_SUCCESS' in an attempt to change the transition to 'Test_Success'
- The SendEvent() is ignored and the FSM still transitions to 'Test_Fail'.

    This is quite unintuitive as one would expect the call to SendEvent() to be honored and have an effect.

    Can this be fixed, please?

    Thanks for your time!

PollitronicDev

  • Playmaker Newbie
  • *
  • Posts: 13
Re: Global events are ignored if called inside OnExit()
« Reply #1 on: November 30, 2021, 06:33:46 AM »
    Hello!

    Any news about this? Is this being worked on?

    Thanks!

djaydino

  • Administrator
  • Hero Member
  • *****
  • Posts: 7615
    • jinxtergames
Re: Global events are ignored if called inside OnExit()
« Reply #2 on: November 30, 2021, 09:27:44 AM »
Hi.
There should be no need to get the component, just use Fsm.event("eventName");

and add a :    public FsmEvent eventName;

djaydino

  • Administrator
  • Hero Member
  • *****
  • Posts: 7615
    • jinxtergames
Re: Global events are ignored if called inside OnExit()
« Reply #3 on: November 30, 2021, 09:38:01 AM »
Hi.
Have you tried placing the custom action above the event action?

Also im not sure what use case you would use this.
you can just make a custom action to send a succes or fail event after a certain time.

or use existing actions, for example adding a bool test to succeed and delayed send event (or a wait action) to fail.

PollitronicDev

  • Playmaker Newbie
  • *
  • Posts: 13
Re: Global events are ignored if called inside OnExit()
« Reply #4 on: December 03, 2021, 10:50:37 AM »
    Hello djaydino, thanks for answering!

    I did try to change the order of the actions, but unfortunately the result is the same.

    My use case would be something like:
    - I use an action to flag the object to have a certain property e.g. 'invulnerable') for the duration of the state. I set the flag in OnEnter(), and reset it in OnExit(). This is convenient because in case a global event happens I know the flag will always be first reset in OnExit().
    - The action's OnExit(), besides resetting the flag has also the potential to change the state globally via a global event (e.g. to a 'Dead' state). This can't be delayed, I need the transition to happen at this moment. But due to this bug, the global event will never have an effect.

    But independently of the use case, I think it's reasonable to expect SendEvent() to work in OnExit() the same as in any other function. At least in the documentation there is no mention that this should be avoided.

    Regards!

djaydino

  • Administrator
  • Hero Member
  • *****
  • Posts: 7615
    • jinxtergames
Re: Global events are ignored if called inside OnExit()
« Reply #5 on: December 03, 2021, 05:26:17 PM »
Hi.
You can set variables "on Exit"

possibly you can send a event to a different fsm using

public FsmEventTarget eventTarget;

and

Fsm.Event(eventTarget,sendEvent);


PollitronicDev

  • Playmaker Newbie
  • *
  • Posts: 13
Re: Global events are ignored if called inside OnExit()
« Reply #6 on: December 09, 2021, 12:59:15 PM »
Hi djaydino, thanks for your suggestion, unfortunately in my case the problem is quite widespread and I would very much prefer not to clutter all my objects with extra FSMs just to be able to send a message.

What I would really like is some official word from the team. This is the bug reporting forum, is this bug going to be fixed or not (I also sent this bug through the bug reporting form just in case)? I posted this almost 3 weeks ago and besides your kind words I got zero official feedback.

Thanks.

djaydino

  • Administrator
  • Hero Member
  • *****
  • Posts: 7615
    • jinxtergames
Re: Global events are ignored if called inside OnExit()
« Reply #7 on: December 09, 2021, 02:02:03 PM »
Hi.
I will ping Alex, but I don't think that its a bug.

From my end the logic looks correct as else 2 events will be send at the same time on the same fsm which will conflict.

For example :
if Send Event (state A) will send to state B then on exit will send event to state C.

actions that are within state B might or might not have triggered (depending of what action types)
as it would be immediately send to state C on exiting state A.

Alex Chouls

  • Administrator
  • Hero Member
  • *****
  • Posts: 3987
  • Official Playmaker Support
    • LinkedIn
Re: Global events are ignored if called inside OnExit()
« Reply #8 on: December 09, 2021, 06:52:46 PM »
This is an interesting problem. OnExit is called when transitioning to another state. The next state is already decided and the old state is given a chance to do some cleanup.

The new state also hasn't been entered yet, so the FSM is in kind of an intermediate state. It's not totally clear how to handle an event in that situation. I guess it might make sense to handle a global transition, since it would be clear how to resolve that event, but it feels a little "special case-y." It seems clearer to document that OnExit is called while transitioning states and new events are not handled while transitioning states.

But I'd like to better understand what you're trying to do, to see if there's another way to approach it, or add support for it. Could your actions do their work in Update instead?