Using Playmaker with Code: Quick Introduction

Summary

A quick bit of background so you can understand the level of this article.  I am a “hobbyist” Unity developer with a single simple Title in the App Store – http://www.nodisone.co.uk/ with Baby Toy Room.

I am investigating Playmaker as a means to improve my workflow after writing my first title fully in code (custom state machine code, custom touch handling etc) as a means to learn about Unity.  I am currently using Playmaker initially to add some levels to Baby Toy Room.

One of the first things that ran through my mind when looking at the wonderful Playmaker was –

How do I integrate this with my code so I can get the best of both worlds? the flexibility, fine control and familiarity of code use, but the GUI based Finite State Machine (FSM) maintenance, easy action library and potential ease of use of Playmaker?

After only using it a couple of weeks in my spare time, I will attempt some basic parts of this question.  I hope this may help other coders if they pick up (or intend to) Playmaker.

I will not attempt to discuss anything concerning performance of any examples given.

QUICK UPDATE FEB 28: Since writing this article, I have found out (but not yet used) about a built in Call Method Action which should allow multiple parameters AND a return parameter, please check this out after reading the below and I will update this at a later date.

Call a Script Method from a Playmaker Action (No Parameters)

Send Message Action

You use the Send Message Action to do this.  As you can see, you simply specify the Game Object where your Script resides along with a Method Name to call.

Capture

In my case this is my Main Camera GameObject calling FSM_ReadyToStart on my MonoBehaviour Script.

Note how you do not need to specify the exact script as per Unity3Ds SendMessage method, which this action uses under the hood –

“Calls the method named methodName on every MonoBehaviour in this game object.”

You can also call a script on the Owner GameObject (the one on which your FSM resides) and other option tweaks, see Docs for this.

Invoke Method Action

An alternative to SendMessage is the Invoke Method Action.  Just like the Unity Invoke Method it allows you to optionally set up a repeating method call.

Capture

Please note how you cannot pass any parameters using this Method.

As you can see, you specify the exact Behaviour and Method Name (these are also helpfully shown in the drop downs once the Game Object has been selected) to call and it also allows you to set up the Delay, Repeat option, Repeating Delay and whether to Cancel on Exit (stop the method being called once we have left the State this Action resides on).

Call Script Method from a Playmaker Action (with a Single Parameter)

You again use the Send Message Action to do this, but with the Parameter option set.

In order to provide this single parameter to your receiving Script you must first create a FSM Variable (OwnerGameObject in my case) and obviously set its value before your Send Message call.

You can see in this example of how I have passed the GameObject on which my FSM resides (the Owner) to my Script.

Tip: Passing the GameObject Owner of the FSM is a nice simple flexible pattern which then allows you in code to quickly interrogate that object for lots of further FSM information, such as multiple FSMs, States, Variables etc.
But, if you do not need to use the GameObject flexibly like this in your receiving script then performance could obviously be improved by only using the most basic data type you need to get the job done.

Capture

I have specified Require Receiver in both my examples so I ensure that this method must exist on my Camera GameObject.

Get Playmaker FSM from Owner GameObject (Code)

For reusable pieces of code such as this, it may be worthwhile creating an Extension Class.

If you know your GameObject only contains a “single” FSM then you can use this –

internal static class GameObjectExtension
{
    public static PlayMakerFSM GetPlayMakerFsm(this GameObject gameObject)
    {
        return gameObject.GetComponent<PlayMakerFSM>();
    }

If you know it has multiple FSMs attached (or are not sure), then you can use this –

    /// <summary>
    /// For use when you know your GameObject has multiple FSMs on it 
    /// </summary>
    /// <param name="gameObject">Gameobject which has named FSM Attached</param>
    /// <param name="fsmName">Name of FSM you would like to find</param>
    /// <returns>FSM Found or null if not Found</returns>
    public static PlayMakerFSM GetPlayMakerFsmByName(this GameObject gameObject, string fsmName)
    {
        PlayMakerFSM[] playMakerFsms = gameObject.GetComponents<PlayMakerFSM>();

        return playMakerFsms.FirstOrDefault(playMakerFsm => playMakerFsm.FsmName == fsmName);
    }

    ...

Send an Event to Playmaker FSM (Code)

Get hold of your PlayMakerFSM object as required, then simply call SendEvent(“[EVENT NAME]”)

    PlayMakerFSM playMakerFsm = Camera.main.gameObject.GetPlayMakerFsm();
    playMakerFsm.SendEvent("HitEvent");

Set Variable of Playmaker FSM (Code)

Get hold of your PlayMakerFSM object as required, then use –

FsmVariables.FindFsm[DATATYPE](“[VARIABLE_NAME”).Value = [NEW_VALUE];

FindFSM[DATATYPE] comes in various varieties (such FindFSMFloat, FindFSMInt, FindFSMGameObject) which match the variable data types available in Playmaker.

In this example, I have instantiated a new GameObject (created a new Tank) and intend to use both of its attached FSMs later in my code.

    GameObject spawnTankGameObject = (GameObject)Instantiate(TankGameObject, spawnPosition, Quaternion.identity);

    PlayMakerFSM playMakerFsm = spawnTankGameObject.GetPlayMakerFsmByName("AttackFSM");
    PlayMakerFSM playMakerFsmCore = spawnTankGameObject.GetPlayMakerFsmByName("CoreFSM");

    playMakerFsmCore.FsmVariables.FindFsmFloat("TimeToMoveFloat").Value = TimeToMove;

The above integration points, once known are easily understood and implemented, but things can get a little more complicated as we try to tie our code together with Playmaker using the further techniques below.

“Receive a Return Value” from a Script Method from a Playmaker Action

The “Public Property” Way

1) Use Send Message Action to call to MethodA on a given Script.

2) In MethodA set PropertyA (which is a Public Property on that Script) to the required Return Value.

3) Use the GetProperty Action to receive the Return Value stored in PropertyA and put it into FSMVariableA.

In this example,  we will store our single Return Value in TimeToMoveFloat (FSMVariableA) via exposing the TimeToMove (PropertyA) Public Property on my Main Camera TankCameraBehaviourScript.

Capture

As you can imagine, this is not the best use of encapsulation if you have to create / expose a public property JUST to return it from a function call, but is simple to understand and gets the job done.

The “Set FSM Variable” Way

1) Use Send Message / Invoke to call to MethodA on a given Script.

2)  In MethodA directly set FSMVariableA in code (as described previously in the article).

This involves less steps and messing about with Public Variables just to pass data back and forth.  Its still far from perfect, but it seems a bit cleaner.

“Custom Action” Ways

We will talk about Custom Actions in our next article as they now start to become compulsory for more advanced integration with Playmaker.  I will update this article with a link once it is completed.

Call Script Method from a Playmaker Action (with Multiple Parameters)

Because of the way SendMessage works in Unity, it does not provide a “out of the box” way of quickly passing multiple parameters to a SendMessage called function. So, as discussed in various Unity threads such as –

http://answers.unity3d.com/questions/451033/can-objectsendmessage-be-used-to-send-2-arguments.html
http://answers.unity3d.com/questions/23384/c-getting-a-return-from-sendmessage.html

The main way to achieve this is via a custom MessageArgs (whatever name you like) class which you simply create and instantiate with the required “parameters” and then send that as the single allowed SendMessage parameter.

This could be a specific “one per method call” as below, or a more generic one with use of lots of optionally set properties to cover most of your use cases.

For example, if you require an equivalent of a function call FunctionA(int a, Vector3 b, float c) your class could look like this –

public class MessageArgs {
    public int a { get; set; }
    public Vector3 b { get; set; }
    public float c { get; set; }
}

Interesting Note: You can also see in the above article how it mentions that you can use the by-reference nature of the MessageArgs class to pass a return value back in one of the class properties.
We will try to use this later in a Custom Action.

Yet, as you can see this does not translate easily to a Generic GUI based Action for use in Playmaker! and therefore one is not provided out of the box with Playmaker because of this.

Using a Custom Concrete Bridge Script

If you want to make a call with a given set of parameters then you could write a specific custom action accordingly.

An example bridge script project is provided in this thread by Jean Fabre – http://hutonggames.com/playmakerforum/index.php?topic=1437.0

Capture

Yet, as discussed in the thread this is hard-wired to call a specific script method per custom action so has no real flexibility.

Ask the Script to Look at Your Variables Instead

Also discussed in the thread, and a similar pattern to Returning a Value previously.  You can reverse the process of “passing multiple parameters” to instead “ask the function to query YOUR FSM variables or an equivalent Meta-FSM for its parameters“.

So you would use SendMessage (or even Invoke Method in this instance) to make your call, passing a reference (if needed) to allow you to acquire the required PlaymakerFSM variable(s) so you can then use them as parameters for your method work.

A More Flexible “Custom Action” Script

As mentioned previously, we will talk about Custom Actions in our next article, and see how we can flexibly solve this integration of multiple parameters and returning values from a Script Method with them.

Some Other Questions ?

  • What are the more complicated ways I can use Playmaker as a base for Finite State Machine code?
  • How can I use Event Data for our code integration?
  • What design patterns and coding / naming conventions are other coders users using to meld there code and Playmaker FSMs together for the best and most productive workflows?
  • How much “boiler-plate” code will I replace with Playmaker FSMs and actions?
  • How can I unit test my Playmaker FSMs …

I will try to answer some of these in my next posts on this subject.

Advertisements

7 thoughts on “Using Playmaker with Code: Quick Introduction

  1. Pingback: “Receive a Return Value” from a Script Method from a Playmaker Custom Action | matthewwaring

  2. I was searching info about multiple FSM on game objects and I stepped into your post.
    It’s funny, I’m using exactly the same solutions. 🙂
    I’m a programmer and I think that for complex logics, coding it’s much better than everything else, and that’s it!
    Good work!

    • Thanks Matteo, it certainly feels that way initially, I have not got far enough into solving more complex issues with Playmaker FSMs to decide fully, but I think even if you stick to a hybrid approach, there can be a nice balance achieved. I hope to revisit some of the questions at a later date and will post back 🙂 I did create the last level of Baby Toy Room entirely with Playmaker (and NO Code!) so am looking into it.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s