TheSingularityWorkshop.FSM_API
1.0.0
See the version list below for details.
dotnet add package TheSingularityWorkshop.FSM_API --version 1.0.0
NuGet\Install-Package TheSingularityWorkshop.FSM_API -Version 1.0.0
<PackageReference Include="TheSingularityWorkshop.FSM_API" Version="1.0.0" />
<PackageVersion Include="TheSingularityWorkshop.FSM_API" Version="1.0.0" />
<PackageReference Include="TheSingularityWorkshop.FSM_API" />
paket add TheSingularityWorkshop.FSM_API --version 1.0.0
#r "nuget: TheSingularityWorkshop.FSM_API, 1.0.0"
#:package TheSingularityWorkshop.FSM_API@1.0.0
#addin nuget:?package=TheSingularityWorkshop.FSM_API&version=1.0.0
#tool nuget:?package=TheSingularityWorkshop.FSM_API&version=1.0.0
TheSingularityWorkshop.FSM.API
A highly intuitive and fluent API for defining and managing Finite State Machines (FSMs) in C#. Designed for clarity, robustness, and ease of use, this library empowers developers and even non-coders to create complex FSM logic with a clean, self-documenting syntax.
🌟 Features
- Fluent API: Define states, transitions, and FSM properties using a readable, method-chaining syntax.
- Intuitive State Definition: Easily scaffold
OnEnter,OnUpdate, andOnExitactions for each state. - Runtime Flexibility: Create, modify, and destroy FSM definitions at runtime.
- Live Instance Management: Robust handling for modifying FSM blueprints while instances are active, ensuring proper state lifecycle (
OnExit/OnEnter) calls during dynamic changes. - Processing Groups: Organize FSMs into custom update categories (
"Update","Physics","AI", etc.) for granular control over their execution. - Any-State Transitions: Define global transitions that can occur from any active state.
- Context-Driven Logic: All state actions and transition conditions operate on a user-defined
IStateContext, allowing seamless integration with your game entities or application data. - Automatic Instance Processing: FSM instances can be automatically updated based on their defined
ProcessRatewithin theirProcessingGroup.
📦 Installation
Install the NuGet package:
dotnet add package TheSingularityWorkshop.FSM.API
Or via NuGet Package Manager:
Install-Package TheSingularityWorkshop.FSM.API
🚀 Getting Started
1. Define Your State Context
Create a class that implements IStateContext. This object will hold the data specific to each FSM instance and will be passed to your state actions and transition conditions.
C#
public class PlayerContext : IStateContext
{
public string PlayerName { get; set; } = "Hero";
public bool IsMoving { get; set; } = false;
public bool HasJumped { get; set; } = false;
public string CurrentStateName { get; set; } = string.Empty; // Essential for FSM internal tracking
// Add any other properties relevant to your player's state (e.g., Health, Inventory, etc.)
}
2. Define Your FSM Blueprint
Use FSM_API.Create.CreateFiniteStateMachine to begin building your FSM.
C#
using TheSingularityWorkshop.FSM_API;
using System;
public static class GameFSMs
{
public static void DefinePlayerFSM()
{
FSM_API.Create.CreateFiniteStateMachine("PlayerFSM", processRate: 60, processingGroup: "GameLoop")
// Define the "Idle" state and its behaviors
.State("Idle",
onEnter: (ctx) => Console.WriteLine($"{((PlayerContext)ctx).PlayerName} is now Idle."),
onUpdate: (ctx) => {
// Logic to check for player input to move or jump
var playerCtx = (PlayerContext)ctx;
if (playerCtx.IsMoving) Console.WriteLine("Idle: Checking for movement...");
if (playerCtx.HasJumped) Console.WriteLine("Idle: Checking for jump...");
},
onExit: (ctx) => Console.WriteLine($"{((PlayerContext)ctx).PlayerName} stopped being Idle."))
// Define the "Moving" state
.State("Moving",
onEnter: (ctx) => Console.WriteLine($"{((PlayerContext)ctx).PlayerName} started Moving."),
onUpdate: (ctx) => {
// Handle continuous movement, check if player stops or jumps
var playerCtx = (PlayerContext)ctx;
Console.WriteLine($"{playerCtx.PlayerName} is still moving...");
},
onExit: (ctx) => Console.WriteLine($"{((PlayerContext)ctx).PlayerName} stopped Moving."))
// Define the "Jumping" state
.State("Jumping",
onEnter: (ctx) => Console.WriteLine($"{((PlayerContext)ctx).PlayerName} is Jumping!"),
onUpdate: (ctx) => {
// Apply jump physics, check for landing
var playerCtx = (PlayerContext)ctx;
Console.WriteLine($"{playerCtx.PlayerName} is in mid-air...");
// Example: Simulate landing after some time/logic
// if (some_landing_condition) playerCtx.HasJumped = false;
},
onExit: (ctx) => Console.WriteLine($"{((PlayerContext)ctx).PlayerName} landed."))
// Set the starting state for any new FSM instance based on this blueprint
.WithInitialState("Idle")
// Define transitions based on conditions evaluated against the PlayerContext
.Transition("Idle", "Moving", (ctx) => ((PlayerContext)ctx).IsMoving)
.Transition("Moving", "Idle", (ctx) => !((PlayerContext)ctx).IsMoving)
.Transition("Moving", "Jumping", (ctx) => ((PlayerContext)ctx).HasJumped)
.Transition("Idle", "Jumping", (ctx) => ((PlayerContext)ctx).HasJumped)
// An 'Any-State' transition: from *any* current state, transition to "Idle"
// if the player has jumped AND is no longer moving (e.g., they landed and stopped)
.Transition(FSM.AnyStateIdentifier, "Idle", (ctx) => ((PlayerContext)ctx).HasJumped && !((PlayerContext)ctx).IsMoving)
// Finalize the definition and register it with the FSM system
.BuildDefinition();
}
}
3. Create and Manage FSM Instances (Handles)
Once defined, you can create multiple instances of your FSM.
C#
public static class GameManager
{
private static FSMHandle playerOneHandle;
private static FSMHandle playerTwoHandle;
public static void Initialize()
{
GameFSMs.DefinePlayerFSM(); // Define the FSM blueprint once
// Create FSM instances for individual players
var playerOneContext = new PlayerContext { PlayerName = "PlayerOne" };
playerOneHandle = FSM_API.Instantiate.GetHandleForContext("PlayerFSM", "PlayerOneID", playerOneContext, "GameLoop");
var playerTwoContext = new PlayerContext { PlayerName = "PlayerTwo" };
playerTwoHandle = FSM_API.Instantiate.GetHandleForContext("PlayerFSM", "PlayerTwoID", playerTwoContext, "GameLoop");
Console.WriteLine($"PlayerOne is initially in state: {playerOneHandle.GetCurrentState()}");
Console.WriteLine($"PlayerTwo is initially in state: {playerTwoHandle.GetCurrentState()}");
}
public static void GameLoopUpdate()
{
// Advance all FSMs in the "GameLoop" processing group
FSM_API.Interaction.Update("GameLoop");
// Example: Simulate input changes for PlayerOne
if (DateTime.Now.Second % 5 == 0 && !((PlayerContext)playerOneHandle.Context).IsMoving)
{
((PlayerContext)playerOneHandle.Context).IsMoving = true;
Console.WriteLine("PlayerOne input: Start Moving!");
}
else if (DateTime.Now.Second % 5 != 0 && ((PlayerContext)playerOneHandle.Context).IsMoving)
{
((PlayerContext)playerOneHandle.Context).IsMoving = false;
Console.WriteLine("PlayerOne input: Stop Moving!");
}
if (DateTime.Now.Millisecond % 1000 < 50 && !((PlayerContext)playerOneHandle.Context).HasJumped) // Simulate quick jump
{
((PlayerContext)playerOneHandle.Context).HasJumped = true;
Console.WriteLine("PlayerOne input: Jump!");
}
else if (DateTime.Now.Millisecond % 1000 > 500 && ((PlayerContext)playerOneHandle.Context).HasJumped)
{
((PlayerContext)playerOneHandle.Context).HasJumped = false; // Simulate landing
}
Console.WriteLine($"PlayerOne's current state: {playerOneHandle.GetCurrentState()}");
Console.WriteLine($"PlayerTwo's current state: {playerTwoHandle.GetCurrentState()}");
Console.WriteLine("---");
}
}
4. Dynamic FSM Modification (Adding/Removing States)
The API supports changing FSM blueprints at runtime, even with active instances.
Adding a State
C#
// Example: Add a new "Death" state to PlayerFSM
FSM_API.Interaction.AddStateToFSM("PlayerFSM", "GameLoop",
"Death",
onEnter: (ctx) => Console.WriteLine($"{((PlayerContext)ctx).PlayerName} has died!"),
onUpdate: (ctx) => { /* Death animation, game over logic */ },
onExit: (ctx) => Console.WriteLine($"{((PlayerContext)ctx).PlayerName} is no longer dead (e.g., respawned)."));
// You would then add transitions to/from "Death" as needed
FSM_API.Interaction.ModifyFiniteStateMachine("PlayerFSM", "GameLoop")
.Transition(FSM.AnyStateIdentifier, "Death", (ctx) => /* some death condition for the player */ false) // Example condition
.BuildDefinition();
Removing a State
When removing a state that active instances might be in, they are automatically transitioned to a specified fallbackStateName (or the FSM's new initial state). OnExit is called for the removed state, and OnEnter for the fallback state.
C#
// Example: Remove the "Jumping" state. Any player currently "Jumping" will move to "Idle".
FSM_API.Interaction.RemoveStateFromFSM("PlayerFSM", "Jumping", "GameLoop", fallbackStateName: "Idle");
// If "Idle" was also being removed, and no other state would exist, you'd need to explicitly provide a valid fallback.
// FSM_API.Interaction.RemoveStateFromFSM("PlayerFSM", "Idle", "GameLoop", fallbackStateName: "SomeNewDefaultState");
📚 API Reference
FSM_API.Create.CreateFiniteStateMachine(string fsmName, int processRate, string processingGroup): Starts building a new FSM.
FSM_API.Interaction.ModifyFiniteStateMachine(string fsmName, string processingGroup): Gets a builder for an existing FSM.
FSM_API.Interaction.DestroyFiniteStateMachine(string fsmName, string processingGroup): Removes an FSM blueprint and all its handles.
FSM_API.Interaction.AddStateToFSM(string fsmName, string processingGroup, string stateName, Action<IStateContext> onEnter, Action<IStateContext> onUpdate, Action<IStateContext> onExit): Adds a new state to a live FSM definition.
FSM_API.Interaction.RemoveStateFromFSM(string fsmName, string stateName, string processingGroup, string fallbackStateName = null): Removes a state, gracefully transitioning live instances.
FSM_API.Instantiate.GetHandleForContext(string fsmName, string contextId, IStateContext context, string processingGroup): Creates or retrieves an FSMHandle for a given context.
FSM_API.Interaction.Update(string processingGroup): Advances all FSMs in a specific processing group.
IStateContext: Interface your context classes must implement, requiring string CurrentStateName { get; set; }.
🙏 Contributing
Contributions are welcome! Please feel free to open issues for bugs or feature requests, or submit pull requests.
📄 License
This project is licensed under the MIT License - see the License for details.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net8.0
- No dependencies.
NuGet packages (3)
Showing the top 3 NuGet packages that depend on TheSingularityWorkshop.FSM_API:
| Package | Downloads |
|---|---|
|
TheSingularityWorkshop.FSM_COS
Platform-neutral computation composition kernel for resolving, loading, arbitrating, and assembling MicroBundle-based computation. |
|
|
TheSingularityWorkshop.FSM_Bridge.Helix
A bridge layer to integrate the FSM_API with the Helix Toolkit for VR and 3D applications. |
|
|
TheSingularityWorkshop.Renderer
Observer-aware rendering foundations built around Event Horizons and computational detail. |
GitHub repositories
This package is not used by any popular GitHub repositories.