Playmaker Forum

PlayMaker Help & Tips => PlayMaker Help => Topic started by: Kein on July 06, 2017, 06:14:31 AM

Title: Printing all FSMvariables and their value of a specific GameObject runtime
Post by: Kein on July 06, 2017, 06:14:31 AM
So I'm iterating though GO and i want to get/print all FSM variables of a specific gameobject runtime, is it possible?
Title: Re: Printing all FSMvariables and their value of a specific GameObject runtime
Post by: djaydino on July 06, 2017, 08:21:16 AM
Hi,
You can use 'Get Fsm....' Actions to get the variables

Here is a video explaining Get Fsm Actions :

Title: Re: Printing all FSMvariables and their value of a specific GameObject runtime
Post by: Kein on July 06, 2017, 08:36:26 AM
Thanks but I mean through API during runtime, no Editor (obviously I could just check it there what is set to happen), just through default script attached to dummy object in the scene I want to get list of all variables on specific GO and iterate through each of it to retrieve value
Title: Re: Printing all FSMvariables and their value of a specific GameObject runtime
Post by: tcmeric on July 06, 2017, 09:21:57 AM
To clarify, you want to print all the variables of a FSM to a string or series of strings to display in the scene during run time?

If not a string, where do you want to save the values?
Title: Re: Printing all FSMvariables and their value of a specific GameObject runtime
Post by: Kein on July 06, 2017, 09:26:35 AM
To clarify, you want to print all the variables of a FSM to a string or series of strings to display in the scene during run time?

If not a string, where do you want to save the values?

Basically I'm doing this right now:

Code: [Select]
NamedVariable[] allNamedVariables = g3.GetComponent<PlayMakerFSM>().FsmVariables.GetAllNamedVariables();
for (int k = 0; k < allNamedVariables.Length; k++)
{
Debug.Log(allNamedVariables[k].ToString());
}

Ir returns me VALUES of some variables but not all of them, I need all children too.  Well, components, not children.

This does not return much useful info:

Code: [Select]
foreach (PlayMakerFSM c in GameObject.Find("myObjectMa,e").GetComponents<PlayMakerFSM>())
{
Debug.Log(string.Concat(new object[]
{
"name ",
c.name,
" type ",
c.GetType(),
" basetype ",
c.GetType().BaseType
}));
foreach (FieldInfo fi in c.GetType().GetFields())
{
object obj = c;
Debug.Log(string.Concat(new object[]
{
"fi name ",
fi.Name,
" val ",
fi.GetValue(obj)
}));
}
}
Title: Re: Printing all FSMvariables and their value of a specific GameObject runtime
Post by: djaydino on July 06, 2017, 10:58:27 AM
Hi,
Ah you want to get them in a script :)

I think you need to use GetComponents and place them (the multiple fsm components) in an array or list
then do the GetAllNamedVariables for each one in the array.

or get each fsm manually and set them in a variable using this :

Code: [Select]
public static PlayMakerFSM FindFsmOnGameObject(GameObject go, string fsmName)
I can't test right now, i will try tomorrow if this works (if not sorry for the wrong advice)
Title: Re: Printing all FSMvariables and their value of a specific GameObject runtime
Post by: Kein on July 06, 2017, 11:07:06 AM
Hey, no worries djaydino. I figured it out, just forgot to update post.

I have a different question, not necessarily PM related but in case someone is bored I'd appreciate a hint.

So, right now I iterate through all GameObjects in the scene to find objects that on specific layer. Then I again iterate through these narrowed objects to find the ones that have component "VeryImportantComponent" so I can get the value of "VeryImportantVar" from that component.

Is there an existing PM method that just gets me list of all gameObjects with specific named component?

And how do I even condition NamedVariable if I cant use normal operators like ==/!= ?
Title: Re: Printing all FSMvariables and their value of a specific GameObject runtime
Post by: djaydino on July 06, 2017, 09:49:28 PM
Hi,
is 'VeryImportantComponent' an fsm Component?

if so, after you got the GameObjects by layer, you can use :

Code: [Select]
PlayMakerFSM[] componentList = FoundGameobjectByLayer.GetComponentsInChildren<PlayMakerFSM>().ToArray();
then you need to iterate and use this :
Code: [Select]
var  currentFsm = componentList [i]
var fmsName = currentFsm
if (fsmName == "FSM")
     {
       //   get VeryImportantVar
     }

if it is not a fsm component change PlayMakerFSM to VeryImportantComponent.

I don't know if it is the best or fastest way, but this should work.
Title: Re: Printing all FSMvariables and their value of a specific GameObject runtime
Post by: Kein on July 07, 2017, 04:30:21 AM
Yeah, thanks.

Can I get list of Events for specific FMS?
Title: Re: Printing all FSMvariables and their value of a specific GameObject runtime
Post by: djaydino on July 07, 2017, 05:11:12 AM
Hi.
Yes you can :

Code: [Select]
FsmEvent[] myFsm = RegionFsm.FsmEvents.ToArray(); //for test
        for (int i = 0; i < fsmName.Length; i++)
        {
            var fsmEventName = myFsm [i].Name;
            Debug.Log(fsmEventName);
        }
Title: Re: Printing all FSMvariables and their value of a specific GameObject runtime
Post by: Kein on July 07, 2017, 03:00:01 PM
Thanks for all the tips. I'm currently using this method but it is quite slow. You do't have to answer this but if you have an idea off the top of your head how to do it faster I'd appreciate it:

Code: [Select]
GameObject[] array = UnityEngine.Object.FindObjectsOfType(typeof(GameObject)) as GameObject[];
for (int i = 0; i < array.Length; i++)
{
if (FSMUtility.LocateFSM(GameObject.Find(array[i].name), "VeryImportantFSM") != null)
{
this.fmsPool.Add(array[i].name.ToString());
}
}

Cheers!
Title: Re: Printing all FSMvariables and their value of a specific GameObject runtime
Post by: djaydino on July 08, 2017, 12:30:56 PM
Hi,
No problem :)

FindObjectsOfType is 'expensive'

Maybe you could get the fsms into an array within play maker?
and then get the array

Are these objects created @ runtime or preset?

If preset you can make an array and set the array type to 'Object' and Object Type to 'PlaymakerFSM' then you can drag the "VeryImportantFSM" into the array.

If from prefab or clone, then you can use the action i have added in the attachment. to get the fsm.
It will show the gameobject name it is in, but it has the correct fsm (if you use the correct name of course)

I have tested it a bit, but not much yet so it might not work perfectly, i will test some more later and add it to the Ecosystem (https://hutonggames.fogbugz.com/default.asp?W1181)

Title: Re: Printing all FSMvariables and their value of a specific GameObject runtime
Post by: Kein on July 08, 2017, 02:51:08 PM
Thanks this may come in handy.

Quote
Are these objects created @ runtime or preset?
As of right now all stuff is runtime
Title: Re: Printing all FSMvariables and their value of a specific GameObject runtime
Post by: Kein on July 27, 2017, 04:11:11 AM
So to make sure there is no way to directly fetch FSM without iterating? Even the built-in helper func does that?
Title: Re: Printing all FSMvariables and their value of a specific GameObject runtime
Post by: djaydino on July 27, 2017, 11:17:30 AM
Hi,
Have you tried my suggestions with the action i provided?
Title: Re: Printing all FSMvariables and their value of a specific GameObject runtime
Post by: Kein on July 27, 2017, 03:05:13 PM

then you need to iterate and use this :
Code: [Select]
var  currentFsm = componentList [i]
var fmsName = currentFsm
if (fsmName == "FSM")
     {
       //   get VeryImportantVar
     }

Yes, this is what you said^

Like, even if I know that MyObject has PlaymakerFSM component named "temp copmponent" attached I still have to iterate to get it. Here is example from your built-in util:

Code: [Select]
public static PlayMakerFSM LocateFSM(GameObject go, string fsmName)
{
if (go != null)
{
PlayMakerFSM[] components = go.GetComponents<PlayMakerFSM>();
if (components != null)
{
for (int i = 0; i < components.Length; i++)
{
if (components[i].FsmName == fsmName)
{
return components[i];
}
}
}
}
return null;
}


As I mentioned before I iterate through list of objects after scene loaded, I already sort them out by layer to narrow  results but even if I know that these specific gameObject will have specific FSM in 99% of cases I still need to iterate through all FSM-components and find the one matching by name instead of directly requesting it.
Title: Re: Printing all FSMvariables and their value of a specific GameObject runtime
Post by: djaydino on July 28, 2017, 01:11:11 AM
Hi,
I mean from this post :

Quote
Hi,
No problem :)

FindObjectsOfType is 'expensive'

Maybe you could get the fsms into an array within play maker?
and then get the array

Are these objects created @ runtime or preset?

If preset you can make an array and set the array type to 'Object' and Object Type to 'PlaymakerFSM' then you can drag the "VeryImportantFSM" into the array.

If from prefab or clone, then you can use the action i have added in the attachment. to get the fsm.
It will show the gameobject name it is in, but it has the correct fsm (if you use the correct name of course)

I have tested it a bit, but not much yet so it might not work perfectly, i will test some more later and add it to the Ecosystem

So you would only need to get that array, something like this :

Code: [Select]
PlayMakerFSM GameObjectFsm = GameObject.GetComponent<PlayMakerFSM>();
        int arrayLenght = GameObjectFsm .FsmVariables.GetFsmArray("arrayname").Length;
        for (int z = 0; z < arrayLenght; z++)
        {
            PlayMakerFSM  go = GameObjectFsm .FsmVariables.GetFsmArray("ArrayName").Get(z) as PlayMakerFSM;

          //  do your thing to the fsm
        }

it is best to place that array on a gameobject with a single fsm. but if not possible.

Then you can something like this to get to the array :
Code: [Select]
PlayMakerFSM[] playMakerFsms = gameObject.GetComponents<PlayMakerFSM>();
        for (int z = 0; z < playMakerFsms.Length; z++)
        {
            string currentFsmName = playMakerFsms[z].name;
            if (currentFsmName == "theNeededFsm")
            {
                PlayMakerFSM playMakerFsm = playMakerFsms[z];
            }
        }

or this way :
Code: [Select]
public static PlayMakerFSM GetPlayMakerFsmByName(this GameObject gameObject, string fsmName)
    {
        PlayMakerFSM[] playMakerFsms = gameObject.GetComponents<PlayMakerFSM>();

        return playMakerFsms.FirstOrDefault(playMakerFsm => playMakerFsm.FsmName == fsmName);
    }
I found this on this website (https://matthewwaring.wordpress.com/2014/01/14/using-playmaker-with-code-quick-introduction/)
Title: Re: Printing all FSMvariables and their value of a specific GameObject runtime
Post by: Kein on July 28, 2017, 06:05:27 AM
Thanks djaydino, but I should have specified - getting FSMs into array is no issue to me, the fact I need to iterate through them and thus affect performance is some way - is. I was hoping there was a direct way to get specific FSM knowing its name. Oh well, not a big deal.

I have another question

Hi.
Yes you can :

Code: [Select]
FsmEvent[] myFsm = RegionFsm.FsmEvents.ToArray(); //for test
        for (int i = 0; i < fsmName.Length; i++)
        {
            var fsmEventName = myFsm [i].Name;
            Debug.Log(fsmEventName);
        }

As I can see I'm getting list of all events? Is there a way to narrow per FSM component?
like
Code: [Select]
PlaymakerFSM tempFMS = FSMUtility.LocateFSM(gameObject, "fms_name");
FSMevent[] events = something.GetallEventOnFSM(tempFMS);
foreach [...]
etc
?
Title: Re: Printing all FSMvariables and their value of a specific GameObject runtime
Post by: djaydino on July 28, 2017, 07:05:17 AM
Hi.
Code: [Select]
FsmEvent[] events = something.FsmEvents.ToArray();
Btw you  can find some api references here (https://hutonggames.fogbugz.com/default.asp?W127) :)
Title: Re: Printing all FSMvariables and their value of a specific GameObject runtime
Post by: Kein on August 02, 2017, 11:06:02 AM
Is there a bug in .GetAllNamedVariables() extension method? It returns me ALL named variables on all FSMs of an object, even tho I specific specific FSM.
Title: Re: Printing all FSMvariables and their value of a specific GameObject runtime
Post by: Kein on August 15, 2017, 08:29:13 PM
Today I learned that when I iterate through NamedVar I need to do nullref check for EACH specific aspect of apparently...

Code: [Select]
NamedVariable[] allNamedVariables = curFSM.FsmVariables.GetAllNamedVariables();
if (allNamedVariables != null && allNamedVariables.Length != 0)
{
Debug.LogError("NameVars array aint null");
for (int v = 0; v < allNamedVariables.Length; v++)
{
if (allNamedVariables[v].Name != null && allNamedVariables[v] != null && allNamedVariables[v].VariableType != null)
{
Debug.LogError("Joke nullcheck passed lol");
VariableType variableType = allNamedVariables[v].VariableType;
File.AppendAllText(curFSM.FsmName + "_vars.txt", string.Concat(new object[]
{
"[name]: ",
allNamedVariables[v].Name,
" [value]: ",
allNamedVariables[v].ToString(),
" [type]: ",
allNamedVariables[v].VariableType.ToString(),
Environment.NewLine
}));
}
}
}