Playmaker Forum

PlayMaker News => General Discussion => Topic started by: rechronicle on July 12, 2020, 10:27:06 PM

Title: How to handle managers conversation?
Post by: rechronicle on July 12, 2020, 10:27:06 PM
I'm having trouble keeping the sanity intact when the project grows and so much reference from one side to another side. How to handle this? It usually causes no problem with a small project.

Title: Re: How to handle managers conversation?
Post by: jeanfabre on July 13, 2020, 03:19:52 AM

 yep, this is a very good question indeed and we are all facing this as we get more and more confortable making bigger project.

 My take( disclaimer: I am not a transhumanism fan by any means, but applied to technical engineering, this makes perfect sense...)

I think of my projects as a Human Body, made up of organs. Each of these organs must be replaceable and perceived as blackbox with a clear, unified interface. The lunge doesn't care about the internal working mechanism of the heart for example.

So each organs exposes an "Interface" for it to operate within the human body. The brain is the main Manager, the one that knows about everything that must happen for the body to function. The heart doesn't care about that, it's only purpose is to take care of the blood, its doesn't even care about that the blood usage.

 All the above is critical when you are going to design your project. It hasn't failed me for almost 10 years of thinking like that, since I read this book:

I strongly recommend you read this, it's old, but still very relevant with the right level of communication for us mere developers... :)

So, in playmaker, your interfaces will be composed of global events and Fsms that you expose on purpose. Let me explain:

 All global events are equaly accessible by any fsm, you MUST implement a convention, that you, as a developer, must respect to keep your project sane. Adopt a naming strategy that allow you to grow and add features to your project. I use for example global events with  "/" character to create menus within the dropdowns to avoid a long list of events. it helps structuring and categorize my global events.

try to be grammatically correct, an event can order something to be executed or listen to something being executed. It's very different and must be clearly differentiated.

something like:




I think it's self evident what an fsm should do with these events, right? just within the name itself, you have lots of meta information as to what this event is and how it should be used.

PAUSE MENU / MOUNT will be sent by gameplay logic, and will be listened to by fsms within the Pause Manager to display the UI elements of the pause menu.

PAUSE MENU / ON MOUNTED will be fired by the Pause manager and listened by any other fsm that needs to be aware of when the pause menu is mounted ( the game play manager to pause the physics computation, or the input manager to stop accepting user game play inputs, etc etc.)

We have covered Global events, you don't need much more than that for events. but that's not enough for proper integration as a whole, sometimes your organs/managers are monitoring data every frame, or during singular events, and they must access data somehow without any events triggered. So you must now create a convention for Fsm access between managers so that they can share data.

For example, you have ennemies prefabs, being instantiated on your levels, your player instance might want to interact with them ( two way interactions most likely), so your ennemy will have a convention that it must have an FSM called  "META DATA" at the root, and any other fsm that is not part of the ennemy instance will access this "META DATA" fsm using GetFsmXXX actions. This way, your player ( or bullet) can collide with anything in the world and simply access the meta data of that collided object, and if it exists it can then further access its data. you should of course use tags and layers to clearly identify the various objects in your level but for the sake of discussion to push this practice to its limit, let's assume no tags nor layers is used.

so ALL your instantiated objects ( ennemies, coins, loot, what ever the player can interact with) has a META DATA fsm, with a string or enum property called Type.

Type could be:

-- player
-- ennemy
-- coin
-- bonus/malus
-- healthpack
-- etc etc

it becomes clear that you can now safely interact with anything, query without any errors what is this thing and then further decide what to do with this thing depending on its type. let's say your player collided with a coin. you decide first who's responsible to acting upon that, let's say each coin is responsible for this and your player doesn't care about them.

your coin will collide with the player, it asks for the Meta Data Type property and if it finds it's a player, your send a global event "COIN / PICK UP" that will likely contains data like coin ID, now any manager can listen to that and act upon, check wether the game play allows for picking up, your coin can start animating the pick up effects and disappear and send "COIN / ON PICKED UP", more managers can listen to that: your purse manager can add money,  the level manager can flag this coin as picked so that next time it's not there, your player can also animate some effects.

then, you have a third connection between FSM, that needs to be done during initializon of your game or level. you want for example your brain manager to have access to your input manager at all time. for this you likely don't want to connect the two using the editor/inspector, because one or both could be instantiated at runtime and not known during editing.

 for this, I don't use global variables, but you could, this is a valid use of global variables, you could have a "Brain Manager" "Pause Menu Manager" and the pause menu when instantiated would set itself as the gameobject for this global variable  "Pause Menu Manager" and then other managers can simplky check if this this variable is not null and then further access its content ( "Meta Data" mainly or at least public fsm, designed to be accessed from other managers).

Does that make sense? with these technics, you should then end up with a clear strategy to handle the complexity of your project.

This is all good and well in an ideal world, but my experience is different... :) you always end up with exceptions, or weird features that is very difficult to design and operate within what I explained above ( for that matter on any solution you will adopt...), so it's very important to leave room for exceptions and handle them as cleanly as possible. I don't have any real world projects that doesn't features some hacks and exceptions to the rules... So be prepare for this, try to enforce the above with great care, making it clean, always name properly your fsm, etc etc, and then if you must break a rule/convention, make it VERY CLEAR, DOCUMENT IT.

The last thing to be very strong on and allocate enough time, is debugging strategy. I use a simple technic of an empty state with an active breakpoing on that I transition too when something odd happened within an fsm, so my logic flow will stop as soon as this state is active. It's critical for fast debugging of the source of the problem, which is half of the job done to then solve the problem itself. So all your logics should always be aware of potential issue and feature built in transition to this breakpoint state. this will be your life guard the day before you release when the unexpected happens to solve that problem fast and properly.

 I haven't touched on data handling, for this there are plenty of forum topics that will propose technics.

Let me know if you have questions :)



Title: Re: How to handle managers conversation?
Post by: rechronicle on July 15, 2020, 12:11:25 AM
Hello Jean, thank you for the detailed answer!

My challenge right now is to come up with a consistent name over time, I tend to keep changing how I name them. It turns out confusing in the end.

Is it good to differentiate between private/public variable and local/global events by their name? (ex: m_VariableName for private & variableName for public)
Really can't decide with this one, and this is a kind of vague context as everyone has their own way of writing.
Title: Re: How to handle managers conversation?
Post by: jeanfabre on July 15, 2020, 02:35:44 AM

 yes, it's a good idea to also have name convention and structure in the variable names.

 for example, when I work with Xml and DataMaker, I always have $VariableName so that I know this is the raw content of a node value.

Indeed, you must be strong with such convention, it will pay off only when your body of work will become overwhelming, you will open any project, any fsm of the last 5 or more years of your work and you will know exactly what's going on.

It takes discipline, not motivation: Be careful to properly identify this difference, when you are motivated by a new idea or a new project, only discipline will get you through until the completion of the project, when things will get not that fun to develop once you have the gameplay done or most of it... that's where we tend to let go of our convention and just rush to finish ( at least that's my problem due to my character traits, not everyone is like that of course).

Make a google document where you list all your convention, and read it from time to it.

 Also, as rigid as the above sounds, you must be prepare to evolve in your understanding of Unity, playmaker, and dev in general and so of course you are going to evolve and update your conventions, that's to be expected and should be the case. Being too rigid is also problematic sometimes. You will need to find a balance.