Logic Driver - Easily Design Gameplay Systems with State Machines

Hello!

[FONT=lucida sans unicode]Logic Driver is an editor which allows Finite State Machines to be created and debugged in Blueprints similar to Animation State Machines.

Marketplace

Version 2.0 is now available for UE 4.23+

Version 2.0 let’s you create your own node type either in blueprints or C++. Nodes can have any variable type exposed directly on them, each with their own BP graph. Variables can be drag and dropped onto nodes.

Additionally, powerful Text Graph Properties are available which allows variables and functions to be placed directly in the text. It is possible to create a functional dialogue system using Logic Driver, and the example project demonstrates one possible implementation.

Designing a new state machine.

Features:

  • New blueprint editor designed to simplify state machine creation.
  • Create your own node in blueprints or C++ and design your own editor system.
  • Expose variables directly on nodes, complete with drag & drop support.
  • Text parsing capabilities for easily injecting dynamic text into a node.
  • Hierarchical state machines are supported directly or by reference.
  • Use inheritance to extend base state machines and make calls to parent graphs.
  • Conditionally evaluate transitions or use execution nodes for event based triggers.
  • Auto-bind multicast delegates to transitions from a dropdown menu.
  • Manage as UObjects or ActorComponents for increased flexibility.
  • Supports run-time visual debugging with the blueprint editor to make testing easy.
  • Custom blueprint nodes are included such as “Has State Machine Reached End State”.
  • C++ source code included.

Hopefully this can help someone. If anyone has questions or feedback please let me know. Thanks!

Hello @Recursoft,

I’ve been eyeballing this package. Trying to ascertain the advantage of using it, over embedding such logic in Statemachines of the AnimBP/AnimGraph?

Well it’s not meant to replace Animation State Machines at all so please keep using those! Animation State Machines are designed to give you a final animation pose, not execute normal Blueprint logic. So if there’s a non-animation system you have that would benefit from a Finite State Machine, that’s where this would come in. Additionally this is designed to work anywhere, not only on a skeletal mesh.

For example, in a game I’m working on I use them for battle commands:

Hope that helps!

Hello @Recursoft,

Thank you for the detailed response. I’m considering Statemachines over Behavior Trees due to the implementation of BT Nodes as Actors. Organization can be a pain. I would have voted for them to use the same interface as the animgraph’s hierarchical statemachines. Prior to the release of your Code Plugin, my plan was to embed the logic into the AnimBP considering many of the actions are tied to Animation anyways. You have been very helpful.

[FONT=lucida sans unicode]After quite a bit of testing, the plugin has been updated with:

Run-time support for Android, iOS, HTML5, and MacOS.
Development support for MacOS.

You’re welcome and please let me know if you have any other questions.

I’ve been using Bruno’s FSM, can you tell me how yours differs to his? Having the proper graph for states would be beneficial and you only get that with some strange workarounds on his.

Your comment on MP page “Network Replicated: Yes, ActorComponents have full replication support.” leaves me with a question, can the states simply replicate from the server conditionally to either owning client and/or remote clients instead of them having to run the same logic? --As some of it stems from input.

Do you have functionality already existing with the concept of transition states that have durations? It would be nice if it supported it out of the box. For example, you tell it to equip an item, it goes to an “equipping” transition which takes x seconds, after which it goes to “equipped”. The states would then be “equipped”, “unequipped”, “on ground”, and the transitions would be “picking up”, “equipping”, “unequipping”.

To answer your first question I’ll go over limitations of Logic Driver: It’s designed so that you use graphs to create all state machines and compile them before hand which means run-time state creation isn’t really an option, and C++ support is limited to managing an instance since it’s using compiled Blueprints. Logic Driver doesn’t directly interface with Animation State Machines nor Behavior Trees. There are more options planned for the C++ side like binding delegates to states and transitions which would help with run-time creation. But overall the primary purpose of this plugin is to make designing and debugging state machines easier by using a custom Blueprint Editor designed for state machines.

Network replication works by syncing transitions. Say the server takes a transition, it will then notify clients to take the same transition. Transitions can be configured to which domain you want them to evaluate on: server, client, or both. Setting it to server means only the server will evaluate the transition and then update clients. Setting it to client means if the owning client triggers the transition, it will then notify the server which will update the appropriate proxies. State logic can also be configured the same way. So I believe the answer to your question is yes.

Transitions are always taken immediately, but there is a “Time in State” helper node to do what you want. I would design the equip system with the transitions also being states and have the equipping state take x seconds to complete. Having it as a state also makes it easier to define specific logic for equipping and a way to cancel it if desired.

Update 1.1

New Features:
Collapse Nodes to State Machines

  • Selected state nodes can be collapsed to a nested state machine while preserving transitions.

Comments

  • Can add comments to state machine graphs.

Bug Fixes:

  • Multiple instances of a state machine can be debugged properly now.
  • Fixed crash when a nested state machine was removed while opened in the editor.
  • Added work around for engine level crash when undoing the creation of a graph for the second time while the graph is open in the editor.

Update 1.2
Supports Unreal Engine 4.20 - 4.22

New Features:
Add Reference to State Machine

  • Other State Machine blueprints can now be directly referenced within a State Machine graph. This allows a single State Machine to be reused multiple times.
  • The context of the super State Machine will be passed into the reference automatically.
  • The reference will inherit the super State Machine’s replication settings.

Convert State Machine to Reference

  • Convert an existing State Machine in-place to a reference.
  • This will also look for any existing variables that are referenced and recreate them in the new blueprint. Any additional event graph logic or custom functions won’t be copied.

Bug Fixes

  • Blueprint Helper Nodes (Such as ‘Time in State’) can now be copied and pasted into supporting graphs.
  • Removed EditAnywhere from some properties which weren’t intended to be modified manually.

Hi! Thank you for this great plugin! I didn’t know I needed it until I saw it. It’s much easier to use than the other state machine plugins (as far as I can tell from the marketplace pages). It is worth the price.

Would it technically be possible to add an option for letting the state machine have it’s own tick rate?

Hey, I’m glad you like it!

Allowing an option to change the tick rate is a great idea. I’ve been wanting to revisit ticking anyway. I’ll see what I can do.

Update 1.3
S****upports Unreal Engine 4.20 - 4.22

New Features:
Change Tick Rate of State Machine

  • State Machines now support a variable delay in seconds between ticks.

Changes:

  • Added explicit Tick override option for ActorComponents.
  • Added/Removed some EditConditions around tick properties to better display when one option requires another.
  • Adding or changing a State Machine reference will default the path to the current Blueprint’s folder.
  • Initializing State Machines when using nested references improved.

Bug Fixes:

  • Duplicating a top level K2 State Machine node will correctly rename it when the name is already in use.

Hi, when you run the state machine as UObject instead of UActorComponent, how do you tick it? Timer perhaps?

The UActorComponent one still uses common tick right? Asking because I need to AddTickPrerequisitory() in some usecases.

State Machine UObject instances implement FTickableGameObject.
Actor components are wrappers around the UObject instances. The tick behavior is the same as if it were just the UObject itself.

Is it possible to use FTickFunction to tick both the UObject and UActorComponent? Having the TickPrerequisitory would help a great deal for things like timing combo state machine in fighting game.

I saw some posts about unsuccessfully adding FTickFunction to UObject though, so you don’t have to take this too far :slight_smile:

If you want precise control over the tick, you might want to consider managing it yourself. You could disable the tick of the State Machine, then from the tick function you want to use call the Update method of the State Machine actor component. The Update method takes a float DeltaSeconds param you can pass in, effectively allowing another method to tick the State Machine.

Do you think that would work for you? I’m sort of picturing it from overriding the actor tick. I haven’t used FTickFunction before.

Yeah I think that would work too. For now I only need the state machine to update after movement component.

HI will consoles be supported in the future?

The run-time component is designed to be platform independent but I don’t have console developer kits to test against.
I may try to see if it can build for consoles, but I won’t be able to officially support it.

Hi Recursoft, I think I have a problem with the State machine… I am using it for a project on the Oculus Quest (android SDK), and when I use the SM I get a critical error. This occurs some time after start- game/SM (independent if I do something in the level or not). The error occurs when the SM is filled of empty.

I use unreal 4.22.3

I hope you can help!

:
D/UE4 : Script Stack (0 frames):
D/UE4 :
D/UE4 : Assertion failed: !IsUnreachable() [File:D:\Build++UE4\Sync\Engine\Source\Runtime\CoreUObject\Private\UObject\ScriptCore.cpp] [Line: 1302]
D/UE4 : SM_NEW_C /Game/DugOutTVT/Maps/MotionController_MergedMap.MotionController_MergedMap:PersistentLevel.DugoutGameMode_C_0.SM_NEW_C_1 Function: ‘/Script/SMSystem.SMInstance:Tick’
D/UE4 : [2019.08.22-14.33.17:586][774]Assertion failed: !IsUnreachable() [File:D:\Build++UE4\Sync\Engine\Source\Runtime\CoreUObject\Private\UObject\ScriptCore.cpp] [Line: 1302]
D/UE4 : SM_NEW_C /Game/DugOutTVT/Maps/MotionController_MergedMap.MotionController_MergedMap:PersistentLevel.DugoutGameMode_C_0.SM_NEW_C_1 Function: ‘/Script/SMSystem.SMInstance:Tick’
D/UE4 : [2019.08.22-14.33.17:586][774]LogAndroid: Error: === Critical error: ===
D/UE4 : [2019.08.22-14.33.17:586][774]LogAndroid: Error:
D/UE4 : [2019.08.22-14.33.17:586][774]LogAndroid: Error: Assertion failed: !IsUnreachable() [File:D:\Build++UE4\Sync\Engine\Source\Runtime\CoreUObject\Private\UObject\ScriptCore.cpp] [Line: 1302]
D/UE4 : [2019.08.22-14.33.17:586][774]LogAndroid: Error: SM_NEW_C /Game/DugOutTVT/Maps/MotionController_MergedMap.MotionController_MergedMap:PersistentLevel.DugoutGameMode_C_0.SM_NEW_C_1 Function: ‘/Script/SMSystem.SMInstance:Tick’
D/UE4 : [2019.08.22-14.33.17:586][774]LogAndroid: Error: [Callstack] 0x00000000C589E2B4 (0x00000000039342B4) libUE4.so!FDebug::CheckVerifyFailedImpl(char const*, char const*, int, char16_t const*, …) ]
D/UE4 : [2019.08.22-14.33.17:586][774]LogAndroid: Error: [Callstack] 0x00000000C994FD64 (0x00000000079E5D64) libUE4.so!void FDebug::CheckVerifyFailed<char16_t [19], char16_t const*, char16_t const*>(char const*, char const*, int, char16_t const (&) [19], char16_t const*, char16_t const*) ]
D/UE4 : [2019.08.22-14.33.17:587][774]LogAndroid: Error: [Callstack] 0x00000000C994E1F4 (0x00000000079E41F4) libUE4.soUnknown ]
D/UE4 : [2019.08.22-14.33.17:587][774]LogAndroid: Error: [Callstack] 0x00000000C5D1AAAC (0x0000000003DB0AAC) libUE4.so!UObject::ProcessEvent(UFunction*, void*) ]
D/UE4 : [2019.08.22-14.33.17:587][774]LogAndroid: Error: [Callstack] 0x00000000C51048B8 (0x000000000319A8B8) libUE4.so!non-virtual thunk to USMInstance::Tick(float) ]
D/UE4 : [2019.08.22-14.33.17:587][774]LogAndroid: Error: [Callstack] 0x00000000C7CF2DF4 (0x0000000005D88DF4) libUE4.so!FTickableGameObject::TickObjects(UWorld*, int, bool, float) ]
D/UE4 : [2019.08.22-14.33.17:587][774]LogAndroid: Error: [Callstack] 0x00000000C7B63B70 (0x0000000005BF9B70) libUE4.so!UGameEngine::Tick(float, bool) ]
D/UE4 : [2019.08.22-14.33.17:587][774]LogAndroid: Error: [Callstack] 0x00000000C50CB6F0 (0x00000000031616F0) libUE4.so!FEngineLoop::Tick() ]
D/UE4 : [2019.08.22-14.33.17:587][774]LogAndroid: Error: [Callstack] 0x00000000C50C2B94 (0x0000000003158B94) libUE4.so!AndroidMain(android_app*) ]
D/UE4 : [2019.08.22-14.33.17:587][774]LogAndroid: Error: [Callstack] 0x00000000C50D1A54 (0x0000000003167A54) libUE4.so!android_main() ]
D/UE4 : [2019.08.22-14.33.17:587][774]LogAndroid: Error: [Callstack] 0x00000000C50F1384 (0x0000000003187384) libUE4.soUnknown ]
D/UE4 : [2019.08.22-14.33.17:587][774]LogAndroid: Error: [Callstack] 0x00000000E7A398D4 (0x00000000000478D4) libc.soUnknown ]
D/UE4 : [2019.08.22-14.33.17:587][774]LogAndroid: Error: [Callstack] 0x00000000E7A0BFE6 (0x0000000000019FE6) libc.soUnknown ]
D/UE4 : [2019.08.22-14.33.17:587][774]LogAndroid: Error:
D/UE4 : [2019.08.22-14.33.17:587][774]LogAndroid: Error:
D/UE4 : [2019.08.22-14.33.17:587][774]LogAndroid: Error:
D/UE4 : [2019.08.22-14.33.17:587][774]LogAndroid: Error:
D/UE4 : [2019.08.22-14.33.17:587][774]LogAndroid: FAndroidMisc::RequestExit(1)