Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
74 changes: 73 additions & 1 deletion FSMUnityPrj/Assets/DFT_Games/GTFSM/Scripts/GTFSM.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: Apache-2.0
// Copyright (c) 2012-2026 Giuseppe Pino De Francesco (DFT Games Studios)
// Copyright (c) 2012-2026 Giuseppe Pino De Francesco (DFT Games Studios)
//
// Project: Generically Typed FSM for Unity
// File: GTFSM.cs
Expand Down Expand Up @@ -113,6 +113,37 @@ public TState RegisterState<TState>(TClient client)
return newState;
}

/// <summary>
/// Registers a new state for this client instance.
/// Creates a new state instance and initializes it.
/// If the state is already registered, returns the existing instance.
/// Use this overload if you want to provide a pre-configured state instance.
/// </summary>
/// <typeparam name="TState">The state type to register (must be a class with parameterless constructor)</typeparam>
/// <param name="client">The client instance that will use this state</param>
/// <param name ="newState">An instantiated state object to register</param>
/// <returns>The registered state instance</returns>
public TState RegisterState<TState>(TClient client, TState newState)
where TState : class, GTFSMState<TClient>, new()
{
Type stateType = newState.GetType();

// Return existing state if already registered (idempotent operation)
if (statesByType.TryGetValue(stateType, out var value))
return value as TState;

// Configure new state instance
newState.StateName = stateType.Name;

// Store in both dictionaries for flexible lookup
statesByType[stateType] = newState;
statesByName[newState.StateName] = newState;

// Initialize state with client reference (one-time setup)
newState.Init(client);
return newState;
}

/// <summary>
/// Retrieves a registered state for this client by its Type.
/// Returns null if the state is not registered.
Expand Down Expand Up @@ -254,6 +285,28 @@ public static TState RegisterState<TClient, TState>(TClient client)
return Me._RegisterState<TClient, TState>(client);
}

/// <summary>
/// Registers a state for a specific client instance.
/// Must be called before the state can be used.
/// Use this overload if you want to provide a pre-configured state instance (e.g., with parameters set).
///
/// Example: GTFSM.RegisterState(this, new PatrolState());
///
/// Note: Each client instance gets its own state instance,
/// so multiple enemies don't share the same PatrolState.
/// </summary>
/// <typeparam name="TClient">The client type</typeparam>
/// <typeparam name="TState">The state type to register (must have parameterless constructor)</typeparam>
/// <param name="client">The client instance</param>
/// <param name="state">Instantiated state</param>
/// <returns>The registered state instance</returns>
public static TState RegisterState<TClient, TState>(TClient client, TState state)
where TClient : class, IGTFSMClient<TClient>
where TState : class, GTFSMState<TClient>, new()
{
return Me._RegisterState(client, state);
}

/// <summary>
/// Sets the current state by Type, with validation.
///
Expand Down Expand Up @@ -525,6 +578,25 @@ private TState _RegisterState<TClient, TState>(TClient client)
return manager.RegisterState<TState>(client);
}

/// <summary>
/// Internal implementation of RegisterState.
/// Creates or retrieves the state manager and registers the state.
/// Use this overload if you want to provide a pre-configured state instance
/// </summary>
private TState _RegisterState<TClient, TState>(TClient client, TState state)
where TClient : class, IGTFSMClient<TClient>
where TState : class, GTFSMState<TClient>, new()
{
if (client == null)
{
Debug.LogError("[GTFSM] Cannot register state: client is null");
return default(TState);
}

InstanceStateManager<TClient> manager = GetOrCreateManager(client);
return manager.RegisterState(client, state);
}

/// <summary>
/// Internal implementation of SetState by Type.
/// Validates the state exists before attempting transition.
Expand Down