playMaker

Author Topic: How to compose complex behavior and communicate between FSMs?  (Read 5196 times)

kocosephia

  • Playmaker Newbie
  • *
  • Posts: 7
How to compose complex behavior and communicate between FSMs?
« on: February 07, 2017, 12:02:38 PM »
Hello everyone!

We are using playmaker to try and build what essentially amounts to a level editor for a project we're working on. That is, we want to have simple behaviors encapsulated in actions like playmaker already does so well, but we also want to have larger, complex behaviors that are composed of actions encapsulated in some way as well. The idea is to be able to string together these complex behaviors to give ourselves even bigger building blocks than actions.

A couple examples of complex behaviors might be:

-Make this object drag-and-droppable and wait for it to be dragged to a target, firing onHover and onDrop events as necessary.

-Explode this game object by adding colliders, an explosive force, a selected particle effect, etc.

-Ask for keyboard input from the user by bringing up a UI and store that input in some specified variable.

Now, we're not sure exactly the best way to go about this but we had some ideas, and I'm curious to see what other playmaker users have done or what they would do. Some of our ideas are as follows:

1. We've thought about using templates to encapsulate complex behavior, in which case the current runFSM and Foreach actions feel a little limiting (specifically for running behavior on multiple targets simultaneously and providing input to the templates). But this might be the best solution if we were able to create custom actions to run FSM templates.

2. We've thought about just making large, complex actions, or maybe just scripting singleton objects that hold behavior that's simply manipulated by playmaker actions. This solution has the problem of bloating the code-base and being less flexible and reusable.

3. We've thought about just using FSMs prefabs that we instantiate which take input and provide output. This is like solution 1, but without the limitations of templates, losing some benefits of ease of use and creating a problem where multiple instantiations of gameobjects that hold FSMs are required for many objects running the same behavior (say 50 targets all exploding at once).

Anyway, all of our potential solutions seem to have a common problem that needs solving, namely: What is the best way to communicate between FSMs? The built in way seems to be to use event data and events for communication and data delivery,  but is this truly the best method of communication between FSMs? Does anyone have a project where they've done it better? The problems with event data for us is that
(1) it's not transparent to one FSM what data another FSM requires to be bundled with an event. We have an action we are working on that does some playmaker-style reflection to try and make that clearer, but it's messy right now. (2) Only one data-object of each FSM type can be sent at once. We build our own send event info action to overcome this limitation, but it's a little clunky, packaging a custom data object and sending it through the FSM Object event data slot.  (3) Bloating the global event namespace with a thousand different event names and requiring senders to have prior knowledge about what events another FSM responds to. We might be able to overcome this somewhere through a strong naming convention, but that's a little bit of a band-aid.

Sorry for the longish post, but here's my curiosity: Has anyone else wrestled with the kinds of problems that we currently are? (How to use actions to compose larger, most complex yet reusable behaviors, and creating robust inter-FSM communication.) And if so, what solutions did you end up coming up with? Or, is there some resource out there that has suggestions on this kind of thing?

Thanks a lot guys! And happy playmaking.
« Last Edit: February 07, 2017, 12:05:25 PM by kocosephia »

jeanfabre

  • Administrator
  • Hero Member
  • *****
  • Posts: 15500
  • Official Playmaker Support
Re: How to compose complex behavior and communicate between FSMs?
« Reply #1 on: February 08, 2017, 02:33:32 AM »
Hi,

 I would recommend using an MVC approach as much as possible, Model can be flexible, but View and Component can be enforced properly.

I tend to talk about "organs" for complex behaviors that needs to be reusable, much like a Human body would be your Application, organs would be your complex behaviors, and inside Organs you'd have smaller complex behaviors down to single Fsms.

 When you have that, you'll be able to create "Organs" that can communicate with defined interfaces and protocoles following simple conventions ( not configuration, as PlayMaker and Unity are so loose in a good way).

- No global variables should be used here.

- Each organ should have a MetaData fsm which holds the public Fsm variables accessible to other organs of your system, this fsm should always be named the same for ALL organs, like "MetaData" or something
- use Set/GetFSM to access this from within your organ and from outside and inside for all MetaData

- Create explicit global events per organ, "HEART/ START PUMPING" and "HEART / ON PUMPING STARTED". Check out how I use proper grammar to explain the context, if you do this, it will be easier to know what that event means ( is it an callback or an order basically).

- use nextFrameEvent wisely on critical operations to give time for an event ( and its associated data) to spread inside an Organ and Also for Unity to process things up, it's an important point for the sanity of your project.

- use the custom setEventProperty and getEventProperty for more powerful event data management ( it's on the ecosystem inside PlayMaker Utils, check your assets, you may have them already).


Yes events is the best way to communicate and if you are aware of the few pitfalls you'll be fine and actually be empowered with great flexibility. I for one find it very hard to come back to conventional scripting because of this.

now event data is tricky because limited, that's why I created a more flexible solution with SetEventProperty and GetEventProperty. Check out the code itself and you'll see that it's a static placeholder ( like PlayMaker does for it's built in eventData) so the BIG ISSUE with this is that you can eat up your data with concurrent events sent within the same stack, and so your fsm MUST process event data straight away upon reception of an event to avoid this.

Depending on the complexity of your project, you'll likely have several big assets frameworks from the Asset store that will nee to work together, I have extensive experience with thi and I recommand using proper dedicated custom actions to contorl them within PlayMaker and proper dedicated components for them frameworks to interface with PlayMaker. Check out the uGUi proxies or the ngui proxies or Photon proxies to check out various methods I have implemented for them. I also created a full set of convenient classes that have proper PropertyDrawers so that you can interface PlayMaker events and fsmVariable access within simple and concise scripts hidding away the complexity of interfacing with PlayMaker ( ugui proxies being the most advanced version of this).

You'll also quickly face some pretty tuff issues with managing data, for this, I found Xml to be the most powerful medium, but of course a database if cool too. However I created XmlMaker ( on the ecosystem) and it's fully functional with proper xpath queries and xml read/write full set of actions, this is something you should also investigate and master if your project will require custom data management.


Let me know if you have more questions. There is a lot to say about this for sure.

Bye,

 Jean


kocosephia

  • Playmaker Newbie
  • *
  • Posts: 7
Re: How to compose complex behavior and communicate between FSMs?
« Reply #2 on: February 08, 2017, 11:44:24 AM »
Hi Jean,

Your post was hugely helpful! Thank you! I'm going to mull over the information you've given me, but I'm sure I'll be back in the next couple days to ask more questions. I really appreciate it!

Just couple quick questions:

"use nextFrameEvent wisely on critical operations to give time for an event ( and its associated data) to spread inside an Organ and Also for Unity to process things up, it's an important point for the sanity of your project."

I'm taking this to mean that when sending data through an event it should look something like this:

1. Sender sets event data
2. Sender sends event to receiver
3. Receiver transitions to a new state via sent event
4. Receiver consumes the event data with GetEventData/Properties
5. Receiver uses a nextFrameEvent action to make sure that all received data has been properly processed before continuing and using the received data.

Is this right?

Second, I would love if there was an example resource or project I could look at, that in your opinion does things in a very good way. I love your analogy of organs for a body, do you have an example of an organ that you feel is set up "the right way" I could comb through?

Again, thanks so much! Playmaker is a great asset, for sure.

jeanfabre

  • Administrator
  • Hero Member
  • *****
  • Posts: 15500
  • Official Playmaker Support
Re: How to compose complex behavior and communicate between FSMs?
« Reply #3 on: February 09, 2017, 01:44:09 AM »
Hi,

nextframeEvent:

- it will depend on the chain on events happening around the initial Event, so if your organ is likely to generate more events as a result of this, likely yes you need to wait a frame and then fire your events. Typically, if your organ is complex and you send an event to the top of the hierarchy of that organ and the sendevent iwll propagate through children, then it's possible that you shoudl wait one frame befor e taking further action within that organ.

 mind you, this is very rare and in some precise cases, so don't do this until you find an issue really, that's how I go about it, do not over engineer for the sake of it. you should always strive for direct synchronous execution of routines and only implement a next frame event when you have fully understood why you need to do so for that particular case.

the example that is close to this it the uGui View Controller sample on the Ecosystem, it follows as closely as possible Apple xCode development MVC patterns and so you'll find a lot of similarities in the way I named events, how I send them and the protocoles conventions that the view and model have to agree upon for everything to work.

in that example, I separate the UI elements from the logic so I have dedicated empty GameObjects acting as my Controllers, Controllers can be aware of one another, talk to one another, they are the brain of a particular Organ if you will ( an organ could be made of many controllers of course, for sanity to avoid bloated fsms).

controllers are fully in charge of their views, the view is only doing the very minimal stuff given the Unity way of doing things, you can only go so far with this. The view can not communicate with anything else then its controller and what makes up its view ( could be UI, but it could anything really). The beauty of this is that know I can switch the view with another one that would loo completly different, but since it would follow the same convention, the controller and view would communicate the same way, unaware that user is experiencing a very different result.

 Bye,

 Jean

ps: more on best practice here:

http://hutonggames.com/playmakerforum/index.php?topic=429.msg1677#msg1677

wait one frame example:
http://hutonggames.com/playmakerforum/index.php?topic=13603.msg63288#msg63288