playMaker

Author Topic: EnableMultiFSM  (Read 3388 times)

ransomink

  • Playmaker Newbie
  • *
  • Posts: 44
EnableMultiFSM
« on: January 02, 2018, 05:26:24 AM »
Hello, over on the PlayMaker discord someone suggested a multi-enable fsm action so they don't have to place EnableFSM multiple times on a stateā€”I thought they meant for different game objects. Apparently, they wanted to enable multiple fsms on a single game object, so I combined the two ideas. This action will enable/disable multiple fsm components on an array of game objects.

Code: [Select]
// (c) Copyright Joshua Smith. Studio Flex, LLC 2015-2017. All rights reserved.

using UnityEngine;
using HutongGames.PlayMaker;
using Tooltip = HutongGames.PlayMaker.TooltipAttribute;

namespace StudioFlex.PlayMaker.Actions
{

    [ActionCategory(ActionCategory.StateMachine)]
    [Tooltip("Enable/Disable multiple FSM Components on GameObjects")]
    public class EnableMultiFSM : FsmStateAction
    {
        public class FSMController
        {
            public class FSM
            {
                [UIHint(UIHint.FsmName)]
                [Tooltip("Optional name of FSM on GameObject. Useful if you have more than one FSM on a GameObject.")]
                public FsmString fsmName;

                [Tooltip("Set to True to enable, False to disable.")]
                public FsmBool enable = true;

                [Tooltip("Reset the initial enabled state when exiting the state.")]
                public FsmBool resetOnExit = true;

                [Tooltip("The FSM component.")]
                private PlayMakerFSM component;

                /// <summary>
                /// The GameObject PlayMakerFSM component.
                /// </summary>
                public PlayMakerFSM Component
                {
                    get { return  component; }
                    set { component = value; }
                }
            }

            [RequiredField]
            [Tooltip("The GameObject that owns the FSM components.")]
            public FsmOwnerDefault gameObject;

            [RequiredField]
            [Title("PlayMaker Fsm")]
            [Tooltip("The FSM components to enable.")]
            public FSM[] fsms;
        }
       
        [Tooltip("An array of GameObjects controlling multiple PlayMaker FSMs.")]
        public FSMController[] fsmController;

        public override void Reset()
        {
            fsmController = new FSMController[ 1 ];
            fsmController[ 0 ].fsms = new FSMController.FSM[ 2 ];
        }

        public override void OnEnter()
    {
            DoMultiEnableFSM();

    Finish();
    }

        public override void OnExit()
        {
            foreach ( var controller in fsmController )
            {
                foreach ( var fsm in controller.fsms )
                {
                    if ( fsm.resetOnExit.Value )
                    {
                        fsm.Component.enabled = !fsm.enable.Value;
                    }
                }
            }
        }

        void DoMultiEnableFSM()
        {
            for ( int i = 0; i < fsmController.Length; i++ )
            {
                var go = fsmController[ i ].gameObject.OwnerOption == OwnerDefaultOption.UseOwner ? Owner : fsmController[ i ].gameObject.GameObject.Value;

                if ( go == null ) return;

                var fsms = fsmController[ i ].fsms;

                if ( fsms == null )
                {
                    LogError( "No Components assigned" );
                    return;
                }

                // find by FSM component name
                var fsmComponents = go.GetComponents<PlayMakerFSM>();

                for ( int j = 0; j < fsms.Length; j++ )
                {
                    var fsm = fsms[ j ];

                    if ( !string.IsNullOrEmpty( fsm.fsmName.Value ) )
                    {
                        foreach ( var component in fsmComponents )
                        {
                            if ( component.FsmName == fsm.fsmName.Value )
                            {
                                fsm.Component = component;
                                break;
                            }
                        }
                    }
                    else
                    {
                        // get first FSM component
                        fsm.Component = go.GetComponent<PlayMakerFSM>();
                    }

                    if ( fsm.Component == null )
                    {
                        LogError( "Missing Component" );
                        return;
                    }

                    fsm.Component.enabled = fsm.enable.Value;
                }
            }
        }
    }

}

Hope you like it...
« Last Edit: January 03, 2018, 05:08:55 AM by ransomink »

djaydino

  • Administrator
  • Hero Member
  • *****
  • Posts: 7614
    • jinxtergames
Re: EnableMultiFSM
« Reply #1 on: January 02, 2018, 09:46:50 AM »
Hi.
I have tested your action, but it seems that 'reset on exit' does not work.
and i am also getting a nullreference when selecting/adding the action

I also made an action a while ago but did not place it yet on the Ecosystem

I have uploaded it now and its called EnableMultipleFSM
you can just drop in fsm components and set 'reset' for all of them, not separately.

I do think your version could be useful in several cases, so if you can solve the issues i can place it also on the ecosystem :)

the top part should look something like this :
Code: [Select]
// (c) Copyright HutongGames, LLC 2010-2018. All rights reserved.
// author : ransomink
// Keywords: multi, multiple
/*--- __ECO__ __PLAYMAKER__ __ACTION__ ---*/

also namespace should be :

Code: [Select]
namespace HutongGames.PlayMaker.Actions
and then you wont need :
Code: [Select]
using Tooltip = HutongGames.PlayMaker.TooltipAttribute;

ransomink

  • Playmaker Newbie
  • *
  • Posts: 44
Re: EnableMultiFSM
« Reply #2 on: January 03, 2018, 05:08:00 AM »
I originally made the action for myself and the person who wanted it, that's why the namespace and tooltip were different. I didn't think to place it here or make it on the Ecosystem, that's cool. I can add all the changes you suggested and look at the reset on exit issue.

Here is an edited version. Let me know if this works fine...

Code: [Select]
// (c) Copyright HutongGames, LLC 2010-2018. All rights reserved.
// author : ransomink
// Keywords: fsm, enable, disable, multi, multiple
/*--- __ECO__ __PLAYMAKER__ __ACTION__ ---*/

using UnityEngine;

namespace HutongGames.PlayMaker.Actions
{

    [ActionCategory(ActionCategory.StateMachine)]
    [Tooltip("Enable/Disable multiple FSM Components on GameObjects")]
    public class EnableMultiFSM : FsmStateAction
    {
        public class FSMController
        {
            public class FSM
            {
                [UIHint(UIHint.FsmName)]
                [Tooltip("Optional name of FSM on GameObject. Useful if you have more than one FSM on a GameObject.")]
                public FsmString fsmName;

                [Tooltip("Set to True to enable, False to disable.")]
                public FsmBool enable = true;

                [Tooltip("Reset the initial enabled state when exiting the state.")]
                public FsmBool resetOnExit = true;

                [Tooltip("The FSM component.")]
                private PlayMakerFSM component;

                /// <summary>
                /// The GameObject PlayMakerFSM component.
                /// </summary>
                public PlayMakerFSM Component
                {
                    get { return  component; }
                    set { component = value; }
                }
            }

            [RequiredField]
            [Tooltip("The GameObject that owns the FSM components.")]
            public FsmOwnerDefault gameObject;

            [RequiredField]
            [Title("PlayMaker Fsm")]
            [Tooltip("The FSM components to enable.")]
            public FSM[] fsms;
        }
       
        [Tooltip("An array of GameObjects controlling multiple PlayMaker FSMs.")]
        public FSMController[] fsmController;

        public override void Reset()
        {
            fsmController = new FSMController[ 1 ];
        }

        public override void OnEnter()
    {
            DoMultiEnableFSM();

    Finish();
    }

        public override void OnExit()
        {
            foreach ( var controller in fsmController )
            {
                foreach ( var fsm in controller.fsms )
                {
                    if ( fsm.resetOnExit.Value )
                    {
                        fsm.Component.enabled = !fsm.enable.Value;
                    }
                }
            }
        }

        void DoMultiEnableFSM()
        {
            for ( int i = 0; i < fsmController.Length; i++ )
            {
                var go = fsmController[ i ].gameObject.OwnerOption == OwnerDefaultOption.UseOwner ? Owner : fsmController[ i ].gameObject.GameObject.Value;

                if ( go == null ) return;

                var fsms = fsmController[ i ].fsms;

                if ( fsms == null )
                {
                    LogError( "No Components assigned" );
                    return;
                }

                // find by FSM component name
                var fsmComponents = go.GetComponents<PlayMakerFSM>();

                for ( int j = 0; j < fsms.Length; j++ )
                {
                    var fsm = fsms[ j ];

                    if ( !string.IsNullOrEmpty( fsm.fsmName.Value ) )
                    {
                        foreach ( var component in fsmComponents )
                        {
                            if ( component.FsmName == fsm.fsmName.Value )
                            {
                                fsm.Component = component;
                                break;
                            }
                        }
                    }
                    else
                    {
                        // get first FSM component
                        fsm.Component = go.GetComponent<PlayMakerFSM>();
                    }

                    if ( fsm.Component == null )
                    {
                        LogError( "Missing Component" );
                        return;
                    }

                    fsm.Component.enabled = fsm.enable.Value;
                }
            }
        }
    }

}

djaydino

  • Administrator
  • Hero Member
  • *****
  • Posts: 7614
    • jinxtergames
Re: EnableMultiFSM
« Reply #3 on: January 03, 2018, 06:52:17 AM »
Hi.

It is working now and no errors, i also changed some of the naming to make it more clear.
I tried to use [ActionSection("Game Object")] to make it more clear but that seems not to work.
I also tried removing the Title on line 51 but then its more unclear. (elements for both objects and fsms then)
Ideally would be to show "FSMS (for fsm amount) and then FSM for the elements.

I will ask to jean if it is ok like this. Here is the code and also as package in the attachment.

Code: [Select]
// (c) Copyright HutongGames, LLC 2010-2018. All rights reserved.
// author : ransomink
// url : http://hutonggames.com/playmakerforum/index.php?topic=16390.0
// Keywords: fsm, enable, disable, multi, multiple
/*--- __ECO__ __PLAYMAKER__ __ACTION__ ---*/

using UnityEngine;

namespace HutongGames.PlayMaker.Actions
{

    [ActionCategory(ActionCategory.StateMachine)]
    [Tooltip("Enable/Disable multiple FSM Components on GameObjects")]
    [HelpUrl("http://hutonggames.com/playmakerforum/index.php?topic=16390.0")]
    public class EnableMultiFSM : FsmStateAction
    {
        public class FSMController
        {
            public class FSM
            {

                [UIHint(UIHint.FsmName)]
                [Tooltip("Optional name of FSM on GameObject. Useful if you have more than one FSM on a GameObject.")]
                public FsmString fsmName;

                [Tooltip("Set to True to enable, False to disable.")]
                public FsmBool enable = true;

                [Tooltip("Reset the initial enabled/disabled state when exiting the state.")]
                public FsmBool resetOnExit = true;

                [Tooltip("The FSM component.")]
                private PlayMakerFSM component;

                /// <summary>
                /// The GameObject PlayMakerFSM component.
                /// </summary>
                public PlayMakerFSM Component
                {
                    get { return component; }
                    set { component = value; }
                }
            }

            [RequiredField]
            [Tooltip("The GameObject that owns the FSM components.")]
            public FsmOwnerDefault gameObject;

            [RequiredField]
            [Tooltip("The FSM components to enable/disable.")]
            [Title("FSM")]
            public FSM[] fsms;
        }

        [Tooltip("An array of GameObjects controlling multiple PlayMaker FSMs.")]
        public FSMController[] fsmGameObjects;

        public override void Reset()
        {
            fsmGameObjects = new FSMController[1];
        }

        public override void OnEnter()
        {
            DoMultiEnableFSM();

            Finish();
        }

        public override void OnExit()
        {
            foreach (var controller in fsmGameObjects)
            {
                foreach (var fsm in controller.fsms)
                {
                    if (fsm.resetOnExit.Value)
                    {
                        fsm.Component.enabled = !fsm.enable.Value;
                    }
                }
            }
        }

        void DoMultiEnableFSM()
        {
            for (int i = 0; i < fsmGameObjects.Length; i++)
            {
                var go = fsmGameObjects[i].gameObject.OwnerOption == OwnerDefaultOption.UseOwner ? Owner : fsmGameObjects[i].gameObject.GameObject.Value;

                if (go == null) return;

                var fsms = fsmGameObjects[i].fsms;

                if (fsms == null)
                {
                    LogError("No Components assigned");
                    return;
                }

                // find by FSM component name
                var fsmComponents = go.GetComponents<PlayMakerFSM>();

                for (int j = 0; j < fsms.Length; j++)
                {
                    var fsm = fsms[j];

                    if (!string.IsNullOrEmpty(fsm.fsmName.Value))
                    {
                        foreach (var component in fsmComponents)
                        {
                            if (component.FsmName == fsm.fsmName.Value)
                            {
                                fsm.Component = component;
                                break;
                            }
                        }
                    }
                    else
                    {
                        // get first FSM component
                        fsm.Component = go.GetComponent<PlayMakerFSM>();
                    }

                    if (fsm.Component == null)
                    {
                        LogError("Missing Component");
                        return;
                    }

                    fsm.Component.enabled = fsm.enable.Value;
                }
            }
        }
    }

}

ransomink

  • Playmaker Newbie
  • *
  • Posts: 44
Re: EnableMultiFSM
« Reply #4 on: January 03, 2018, 10:27:16 AM »
That's what I tried to do for the naming of the array and each element. Unfortunately, it uses the title for both...

jeanfabre

  • Administrator
  • Hero Member
  • *****
  • Posts: 15500
  • Official Playmaker Support
Re: EnableMultiFSM
« Reply #5 on: February 01, 2018, 01:08:43 AM »
Hi,

 catching up.

 what is required from me here?

 Bye,

 Jean

ransomink

  • Playmaker Newbie
  • *
  • Posts: 44
Re: EnableMultiFSM
« Reply #6 on: February 03, 2018, 03:42:47 PM »
I tried placing a Title for the fsms variable named FSMS and wanted to name its elements as FSM but the elements display the same name as the Title for the array itself. If I remove the Title, the array is named as Element 0 by default and its elements as well, which isn't necessarily a problem but it'll be more readable with actual names instead...