GS2-StateMachine SDK for Game Engine API Reference

Specifications of models and API references for GS2-StateMachine SDK for Game Engine

Model

EzStatus

State Machine Status

Represents a running instance of a state machine for a specific user. Tracks the current execution state including variables, call stack for sub-state machines, transition count, and random number state. The status transitions through Running, Wait, Pass (success), and Error states.

TypeConditionRequiredDefaultValue LimitsDescription
statusIdstring
*
~ 1024 charsStatus of State Machine GRN
* Set automatically by the server
namestring
UUID~ 36 charsStatus name
Maintains a unique name for each status of state machine.
The name is automatically generated in UUID (Universally Unique Identifier) format and used to identify each status of state machine.
enableSpeculativeExecutionString Enum
enum {
  “enable”,
  “disable”
}
“disable”Whether to enable speculative execution
When enabled, the state machine definition and random status are included in this Status entity. This allows clients to simulate transitions locally before server confirmation, reducing perceived latency.
DefinitionDescription
“enable”Enable
“disable”Disable
stateMachineDefinitionstring{enableSpeculativeExecution} == “enable”
*
~ 16777216 charsState machine definition
The GSL definition embedded in this status for speculative execution. Only present when enableSpeculativeExecution is enabled. Filtered out in normal API responses and only included when needed for client-side simulation.

* Applicable only if enableSpeculativeExecution is “enable”
randomStatusEzRandomStatus{enableSpeculativeExecution} == “enable”
*
Random status
The random number generation state for this execution instance. Used for speculative execution to ensure deterministic random behavior across client and server. Only present when enableSpeculativeExecution is enabled.

* Applicable only if enableSpeculativeExecution is “enable”
stacksList<EzStackEntry>[]0 ~ 1024 itemsStack
The call stack for sub-state machine invocations. When a state machine calls a sub-state machine, an entry is pushed with the caller’s state machine name and return task. When the sub-state machine completes, the entry is popped and execution resumes at the return task.
variablesList<EzVariable>[]0 ~ 1000 itemsState variables for each state machine
The current variable values for each state machine in the call hierarchy. Each entry holds the state machine name and a JSON-serialized value supporting int, float, string, bool, array, and map types. Variables persist across state transitions within the same execution instance.
statusString Enum
enum {
  “Running”,
  “Wait”,
  “Pass”,
  “Error”
}
“Running”Status
The current execution status of this state machine instance. “Running” means the machine is actively processing transitions. “Wait” means the machine is waiting for an external event (emit). “Pass” means it completed successfully. “Error” means it terminated with an error.
DefinitionDescription
“Running”Running
“Wait”Wait
“Pass”Pass
“Error”Error
lastErrorstring~ 1024 charsLast error
The error message from the most recent failure. Set when the status transitions to “Error”. Contains details about what caused the state machine to terminate abnormally.
transitionCountint00 ~ 2147483645Number of transitions
The total number of state transitions performed in this execution instance. Incremented on each transition. If this value exceeds 1000, the state machine is terminated with an error to prevent infinite loops.

EzStackEntry

Stack Entry

Represents a single entry in the sub-state machine call stack. When a state machine invokes a sub-state machine, the caller’s name and the return task are pushed onto the stack. When the sub-state machine completes, execution resumes at the return task of the popped entry.

TypeConditionRequiredDefaultValue LimitsDescription
stateMachineNamestring
~ 128 charsName of the state machine
The name of the calling state machine that pushed this stack entry. Used to identify which state machine’s context to restore when returning from a sub-state machine.
taskNamestring
~ 128 charsTask name
The name of the task (state) to return to when the sub-state machine completes. Execution resumes from this task in the calling state machine.

EzVariable

State variables per state machine

Holds the current variable state for a specific state machine within the call hierarchy. The value is a JSON-serialized representation supporting int, float, string, bool, array, and map data types.

TypeConditionRequiredDefaultValue LimitsDescription
stateMachineNamestring
~ 128 charsName of the state machine
The name of the state machine that owns these variables. In a nested call hierarchy, each state machine has its own independent variable scope identified by this name.
valuestring
~ 1048576 charsValue
The JSON-serialized variable values for this state machine. Supports int, float, string, bool, array, and map data types. Updated as the state machine processes transitions and actions.

EzChangeStateEvent

Change state event

Records a state transition that occurred within the state machine. Contains the destination task name, a hash for integrity verification, and the timestamp of the transition.

TypeConditionRequiredDefaultValue LimitsDescription
taskNamestring
~ 128 charsTask name
The name of the destination task (state) that the state machine transitioned to.
hashstring
~ 64 charsHash
A hash value for verifying the integrity of the state transition. Used to validate that the transition was performed correctly and the state is consistent.
timestamplong
Timestamp

EzEmitEvent

Send a message event

Represents a message emitted by the state machine to trigger external actions. The event name identifies the type of action, and parameters provide the action-specific data.

TypeConditionRequiredDefaultValue LimitsDescription
eventstring
~ 128 charsEvent name
The name identifying the type of emitted event. Used to determine which external action to invoke, such as granting rewards or consuming resources.
parametersstring
~ 1024 charsParameters
The parameters passed with the emitted event. Contains action-specific data in a serialized format that is used to configure the external action triggered by this event.
timestamplong
Timestamp

EzEvent

Event

Represents an event that occurred during state machine execution. Can be either a state change event (recording a state transition) or an emit event (sending a message to trigger external actions).

TypeConditionRequiredDefaultValue LimitsDescription
eventTypeString Enum
enum {
  “change_state”,
  “emit”
}
Event type
The type of event. “change_state” records a state transition within the state machine. “emit” represents a message sent to trigger external actions such as granting rewards or consuming resources.
DefinitionDescription
“change_state”Change state
“emit”Send a message
changeStateEventEzChangeStateEvent{eventType} == “change_state”
✓*
Change state
* Required if eventType is “change_state”
emitEventEzEmitEvent{eventType} == “emit”
✓*
Send a message
* Required if eventType is “emit”

EzRandomStatus

Random number status

Manages the random number generation state for a state machine execution instance. Contains a seed value and per-category usage tracking. Used for speculative execution to ensure deterministic random behavior across client and server.

TypeConditionRequiredDefaultValue LimitsDescription
seedlong
0 ~ 4294967294Random seed
The seed value for deterministic random number generation within the state machine execution.
usedList<EzRandomUsed>0 ~ 1000 itemsList of used random number
Tracks random numbers consumed per category. Each category represents a distinct purpose for random number usage, allowing independent tracking to maintain consistency across speculative re-executions.

EzRandomUsed

Used random number

Tracks the number of random values consumed for a specific category within a state machine execution. Each category allows independent random number tracking for different purposes.

TypeConditionRequiredDefaultValue LimitsDescription
categorylong
0 ~ 4294967294Category
A numeric identifier for the random number usage category. Each category tracks random consumption independently, allowing the state machine to use separate random sequences for different purposes.
usedlong
0 ~ 4294967294Used count
The number of random values that have been consumed in this category. Incremented each time a random number is drawn from this category’s sequence.

EzVerifyActionResult

Verify Action execution result

TypeConditionRequiredDefaultValue LimitsDescription
actionString Enum
enum {
"Gs2Dictionary:VerifyEntryByUserId",
"Gs2Distributor:IfExpressionByUserId",
"Gs2Distributor:AndExpressionByUserId",
"Gs2Distributor:OrExpressionByUserId",
"Gs2Enchant:VerifyRarityParameterStatusByUserId",
"Gs2Experience:VerifyRankByUserId",
"Gs2Experience:VerifyRankCapByUserId",
"Gs2Grade:VerifyGradeByUserId",
"Gs2Grade:VerifyGradeUpMaterialByUserId",
"Gs2Guild:VerifyCurrentMaximumMemberCountByGuildName",
"Gs2Guild:VerifyIncludeMemberByUserId",
"Gs2Inventory:VerifyInventoryCurrentMaxCapacityByUserId",
"Gs2Inventory:VerifyItemSetByUserId",
"Gs2Inventory:VerifyReferenceOfByUserId",
"Gs2Inventory:VerifySimpleItemByUserId",
"Gs2Inventory:VerifyBigItemByUserId",
"Gs2Limit:VerifyCounterByUserId",
"Gs2Matchmaking:VerifyIncludeParticipantByUserId",
"Gs2Mission:VerifyCompleteByUserId",
"Gs2Mission:VerifyCounterValueByUserId",
"Gs2Ranking2:VerifyGlobalRankingScoreByUserId",
"Gs2Ranking2:VerifyClusterRankingScoreByUserId",
"Gs2Ranking2:VerifySubscribeRankingScoreByUserId",
"Gs2Schedule:VerifyTriggerByUserId",
"Gs2Schedule:VerifyEventByUserId",
"Gs2SerialKey:VerifyCodeByUserId",
"Gs2Stamina:VerifyStaminaValueByUserId",
"Gs2Stamina:VerifyStaminaMaxValueByUserId",
"Gs2Stamina:VerifyStaminaRecoverIntervalMinutesByUserId",
"Gs2Stamina:VerifyStaminaRecoverValueByUserId",
"Gs2Stamina:VerifyStaminaOverflowValueByUserId",
}
Type of action to be executed in the Verify Action
verifyRequeststring
~ 524288 charsJSON string of the request used when executing the action
statusCodeint0 ~ 999Status code
verifyResultstring~ 1048576 charsResult payload

EzConsumeActionResult

Consume Action execution result

TypeConditionRequiredDefaultValue LimitsDescription
actionString Enum
enum {
"Gs2AdReward:ConsumePointByUserId",
"Gs2Dictionary:DeleteEntriesByUserId",
"Gs2Enhance:DeleteProgressByUserId",
"Gs2Exchange:DeleteAwaitByUserId",
"Gs2Experience:SubExperienceByUserId",
"Gs2Experience:SubRankCapByUserId",
"Gs2Formation:SubMoldCapacityByUserId",
"Gs2Grade:SubGradeByUserId",
"Gs2Guild:DecreaseMaximumCurrentMaximumMemberCountByGuildName",
"Gs2Idle:DecreaseMaximumIdleMinutesByUserId",
"Gs2Inbox:OpenMessageByUserId",
"Gs2Inbox:DeleteMessageByUserId",
"Gs2Inventory:ConsumeItemSetByUserId",
"Gs2Inventory:ConsumeSimpleItemsByUserId",
"Gs2Inventory:ConsumeBigItemByUserId",
"Gs2JobQueue:DeleteJobByUserId",
"Gs2Limit:CountUpByUserId",
"Gs2LoginReward:MarkReceivedByUserId",
"Gs2Mission:ReceiveByUserId",
"Gs2Mission:BatchReceiveByUserId",
"Gs2Mission:DecreaseCounterByUserId",
"Gs2Mission:ResetCounterByUserId",
"Gs2Money:WithdrawByUserId",
"Gs2Money:RecordReceipt",
"Gs2Money2:WithdrawByUserId",
"Gs2Money2:VerifyReceiptByUserId",
"Gs2Quest:DeleteProgressByUserId",
"Gs2Ranking2:CreateGlobalRankingReceivedRewardByUserId",
"Gs2Ranking2:CreateClusterRankingReceivedRewardByUserId",
"Gs2Schedule:DeleteTriggerByUserId",
"Gs2SerialKey:UseByUserId",
"Gs2Showcase:IncrementPurchaseCountByUserId",
"Gs2SkillTree:MarkRestrainByUserId",
"Gs2Stamina:DecreaseMaxValueByUserId",
"Gs2Stamina:ConsumeStaminaByUserId",
}
Type of action to be executed in the Consume Action
consumeRequeststring
~ 524288 charsJSON string of the request used when executing the action
statusCodeint0 ~ 999Status code
consumeResultstring~ 1048576 charsResult payload

EzAcquireActionResult

Acquire Action execution result

TypeConditionRequiredDefaultValue LimitsDescription
actionString Enum
enum {
"Gs2AdReward:AcquirePointByUserId",
"Gs2Dictionary:AddEntriesByUserId",
"Gs2Enchant:ReDrawBalanceParameterStatusByUserId",
"Gs2Enchant:SetBalanceParameterStatusByUserId",
"Gs2Enchant:ReDrawRarityParameterStatusByUserId",
"Gs2Enchant:AddRarityParameterStatusByUserId",
"Gs2Enchant:SetRarityParameterStatusByUserId",
"Gs2Enhance:DirectEnhanceByUserId",
"Gs2Enhance:UnleashByUserId",
"Gs2Enhance:CreateProgressByUserId",
"Gs2Exchange:ExchangeByUserId",
"Gs2Exchange:IncrementalExchangeByUserId",
"Gs2Exchange:CreateAwaitByUserId",
"Gs2Exchange:AcquireForceByUserId",
"Gs2Exchange:SkipByUserId",
"Gs2Experience:AddExperienceByUserId",
"Gs2Experience:SetExperienceByUserId",
"Gs2Experience:AddRankCapByUserId",
"Gs2Experience:SetRankCapByUserId",
"Gs2Experience:MultiplyAcquireActionsByUserId",
"Gs2Formation:AddMoldCapacityByUserId",
"Gs2Formation:SetMoldCapacityByUserId",
"Gs2Formation:AcquireActionsToFormProperties",
"Gs2Formation:SetFormByUserId",
"Gs2Formation:AcquireActionsToPropertyFormProperties",
"Gs2Friend:UpdateProfileByUserId",
"Gs2Grade:AddGradeByUserId",
"Gs2Grade:ApplyRankCapByUserId",
"Gs2Grade:MultiplyAcquireActionsByUserId",
"Gs2Guild:IncreaseMaximumCurrentMaximumMemberCountByGuildName",
"Gs2Guild:SetMaximumCurrentMaximumMemberCountByGuildName",
"Gs2Idle:IncreaseMaximumIdleMinutesByUserId",
"Gs2Idle:SetMaximumIdleMinutesByUserId",
"Gs2Idle:ReceiveByUserId",
"Gs2Inbox:SendMessageByUserId",
"Gs2Inventory:AddCapacityByUserId",
"Gs2Inventory:SetCapacityByUserId",
"Gs2Inventory:AcquireItemSetByUserId",
"Gs2Inventory:AcquireItemSetWithGradeByUserId",
"Gs2Inventory:AddReferenceOfByUserId",
"Gs2Inventory:DeleteReferenceOfByUserId",
"Gs2Inventory:AcquireSimpleItemsByUserId",
"Gs2Inventory:SetSimpleItemsByUserId",
"Gs2Inventory:AcquireBigItemByUserId",
"Gs2Inventory:SetBigItemByUserId",
"Gs2JobQueue:PushByUserId",
"Gs2Limit:CountDownByUserId",
"Gs2Limit:DeleteCounterByUserId",
"Gs2LoginReward:DeleteReceiveStatusByUserId",
"Gs2LoginReward:UnmarkReceivedByUserId",
"Gs2Lottery:DrawByUserId",
"Gs2Lottery:ResetBoxByUserId",
"Gs2Mission:RevertReceiveByUserId",
"Gs2Mission:IncreaseCounterByUserId",
"Gs2Mission:SetCounterByUserId",
"Gs2Money:DepositByUserId",
"Gs2Money:RevertRecordReceipt",
"Gs2Money2:DepositByUserId",
"Gs2Quest:CreateProgressByUserId",
"Gs2Schedule:TriggerByUserId",
"Gs2Schedule:ExtendTriggerByUserId",
"Gs2Script:InvokeScript",
"Gs2SerialKey:RevertUseByUserId",
"Gs2SerialKey:IssueOnce",
"Gs2Showcase:DecrementPurchaseCountByUserId",
"Gs2Showcase:ForceReDrawByUserId",
"Gs2SkillTree:MarkReleaseByUserId",
"Gs2Stamina:RecoverStaminaByUserId",
"Gs2Stamina:RaiseMaxValueByUserId",
"Gs2Stamina:SetMaxValueByUserId",
"Gs2Stamina:SetRecoverIntervalByUserId",
"Gs2Stamina:SetRecoverValueByUserId",
"Gs2StateMachine:StartStateMachineByUserId",
}
Type of action to be executed in the Acquire Action
acquireRequeststring
~ 524288 charsJSON string of the request used when executing the action
statusCodeint0 ~ 999Status code
acquireResultstring~ 1048576 charsResult payload

EzTransactionResult

Transaction execution results

Result of a transaction executed using the server-side automatic transaction execution feature

TypeConditionRequiredDefaultValue LimitsDescription
transactionIdstring
36 ~ 36 charsTransaction ID
verifyResultsList<EzVerifyActionResult>0 ~ 10 itemsList of verify action execution results
consumeResultsList<EzConsumeActionResult>[]0 ~ 10 itemsList of Consume Action execution results
acquireResultsList<EzAcquireActionResult>[]0 ~ 100 itemsList of Acquire Action execution results

Methods

emit

Send an event to trigger a state transition

Sends a named event to the state machine, causing it to move from the current state to the next state based on the defined transition rules.

This is the main way the game client drives the state machine forward. For example:

  • Player taps “Accept” on a quest dialog → Emit “accept” event → State changes from “Offered” to “InProgress”
  • Player defeats the boss → Emit “boss_defeated” event → State changes from “BossStage” to “Complete”
  • Player makes a choice in a story → Emit “choose_path_a” event → State branches to the chosen path

You can pass additional data as JSON arguments (args). For example, when emitting a “submit_answer” event, you might include {“answer”: “B”} as the args.

The state machine will only accept events that are valid for the current state. If the event is not defined for the current state, an error is returned and no transition occurs.

Request

TypeConditionRequiredDefaultValue LimitsDescription
namespaceNamestring
~ 128 charsNamespace name
Namespace-specific name. Specified using alphanumeric characters, hyphens (-), underscores (_), and periods (.).
gameSessionGameSession
GameSession
statusNamestring
~ 36 charsStatus name
eventNamestring
~ 36 charsEvent name
argsstring“{}”~ 4096 charsArguments to be passed to the state machine

Result

TypeDescription
itemEzStatusStatus of State Machine

Implementation Example

    var domain = gs2.StateMachine.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).Status(
        statusName: "status-0001"
    );
    var result = await domain.EmitAsync(
        eventName: "event-0001",
        args: "{\"value1\": \"value1\", \"value2\": 2.0, \"value3\": 3}"
    );
    var item = await result.ModelAsync();
    var domain = gs2.StateMachine.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).Status(
        statusName: "status-0001"
    );
    var future = domain.EmitFuture(
        eventName: "event-0001",
        args: "{\"value1\": \"value1\", \"value2\": 2.0, \"value3\": 3}"
    );
    yield return future;
    if (future.Error != null)
    {
        onError.Invoke(future.Error, null);
        yield break;
    }
    var future2 = future.Result.ModelFuture();
    yield return future2;
    if (future2.Error != null)
    {
        onError.Invoke(future2.Error, null);
        yield break;
    }
    var result = future2.Result;
    const auto Domain = Gs2->StateMachine->Namespace(
        "namespace-0001" // namespaceName
    )->Me(
        GameSession
    )->Status(
        "status-0001" // statusName
    );
    const auto Future = Domain->Emit(
        "event-0001", // eventName
        "{\"value1\": \"value1\", \"value2\": 2.0, \"value3\": 3}" // args
    );
    Future->StartSynchronousTask();
    if (Future->GetTask().IsError())
    {
        return false;
    }

    // obtain changed values / result values
    const auto Future2 = Future->GetTask().Result()->Model();
    Future2->StartSynchronousTask();
    if (Future2->GetTask().IsError())
    {
        return Future2->GetTask().Error();
    }
    const auto Result = Future2->GetTask().Result();

exit

Clean up a completed state machine

Deletes a state machine instance that has finished running. This can only be called when the state machine’s status is “Pass” (completed successfully) or “Error” (failed).

After a state machine reaches its terminal state, it remains in the system until you explicitly delete it with Exit. This gives you time to:

  • Show the player the completion result (e.g., “Quest Complete!” screen)
  • Read the final state and variables to determine rewards
  • Handle any error state and decide what to do next

Typical flow:

  1. State machine reaches terminal state → status becomes “Pass”
  2. Game reads the final state and grants rewards to the player
  3. Game shows a completion screen
  4. Player dismisses the screen → game calls Exit to clean up

You cannot call Exit on a Running state machine. If you need to forcefully stop a running state machine, that requires a server-side operation.

Request

TypeConditionRequiredDefaultValue LimitsDescription
namespaceNamestring
~ 128 charsNamespace name
Namespace-specific name. Specified using alphanumeric characters, hyphens (-), underscores (_), and periods (.).
gameSessionGameSession
GameSession
statusNamestring
~ 36 charsStatus name

Result

TypeDescription
itemEzStatusExited state machine

Implementation Example

    var domain = gs2.StateMachine.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).Status(
        statusName: "status-0001"
    );
    var result = await domain.ExitAsync(
    );
    var domain = gs2.StateMachine.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).Status(
        statusName: "status-0001"
    );
    var future = domain.ExitFuture(
    );
    yield return future;
    if (future.Error != null)
    {
        onError.Invoke(future.Error, null);
        yield break;
    }
    const auto Domain = Gs2->StateMachine->Namespace(
        "namespace-0001" // namespaceName
    )->Me(
        GameSession
    )->Status(
        "status-0001" // statusName
    );
    const auto Future = Domain->Exit(
    );
    Future->StartSynchronousTask();
    if (Future->GetTask().IsError())
    {
        return false;
    }
    const auto Result = Future->GetTask().Result();

getStatus

Get the current state of a specific state machine instance

Retrieves detailed information about a specific state machine instance, including which state it’s currently in and its stored variables.

Use this to display the current progress of a workflow to the player — for example:

  • A quest tracker showing “Current step: Defeat 3 monsters (2/3)”
  • A tutorial indicator showing which step the player is on
  • A process status showing whether it’s still running, completed, or encountered an error

The response includes:

  • Current state name: Which state the machine is in right now
  • Variables: Data stored in the state machine (e.g., progress counters, choices made)
  • Status: Whether the machine is Running, Pass (completed), or Error
  • Stack trace: The history of state transitions (useful for debugging)

Request

TypeConditionRequiredDefaultValue LimitsDescription
namespaceNamestring
~ 128 charsNamespace name
Namespace-specific name. Specified using alphanumeric characters, hyphens (-), underscores (_), and periods (.).
gameSessionGameSession
GameSession
statusNamestring
~ 36 charsStatus name

Result

TypeDescription
itemEzStatusState Machine Status

Implementation Example

    var domain = gs2.StateMachine.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).Status(
        statusName: "status-0001"
    );
    var item = await domain.ModelAsync();
    var domain = gs2.StateMachine.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).Status(
        statusName: "status-0001"
    );
    var future = domain.ModelFuture();
    yield return future;
    var item = future.Result;
    const auto Domain = Gs2->StateMachine->Namespace(
        "namespace-0001" // namespaceName
    )->Me(
        GameSession
    )->Status(
        "status-0001" // statusName
    );
    const auto Future = Domain->Model();
    Future->StartSynchronousTask();
    if (Future->GetTask().IsError())
    {
        return false;
    }
Value change event handling
    var domain = gs2.StateMachine.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).Status(
        statusName: "status-0001"
    );
    
    // Start event handling
    var callbackId = domain.Subscribe(
        value => {
            // Called when the value changes
            // The "value" is passed the value after the change.
        }
    );

    // Stop event handling
    domain.Unsubscribe(callbackId);
    var domain = gs2.StateMachine.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).Status(
        statusName: "status-0001"
    );
    
    // Start event handling
    var callbackId = domain.Subscribe(
        value => {
            // Called when the value changes
            // The "value" is passed the value after the change.
        }
    );

    // Stop event handling
    domain.Unsubscribe(callbackId);
    const auto Domain = Gs2->StateMachine->Namespace(
        "namespace-0001" // namespaceName
    )->Me(
        GameSession
    )->Status(
        "status-0001" // statusName
    );
    
    // Start event handling
    const auto CallbackId = Domain->Subscribe(
        [](TSharedPtr<Gs2::StateMachine::Model::FStatus> value) {
            // Called when the value changes
            // The "value" is passed the value after the change.
        }
    );

    // Stop event handling
    Domain->Unsubscribe(CallbackId);

listStatuses

Get a list of the player’s state machine instances

Retrieves all state machine instances belonging to the current player. A state machine is a server-managed workflow that tracks a player’s progress through a series of steps (states). Each step can trigger actions, wait for player input, or branch based on conditions.

Common use cases for state machines:

  • Quest progression: “Accept Quest” → “In Progress” → “Boss Battle” → “Complete” → “Claim Reward”
  • Tutorial flows: “Welcome” → “Move Tutorial” → “Battle Tutorial” → “Gacha Tutorial” → “Done”
  • Timed events: Multi-phase event processes with time limits

Each state machine instance has one of three statuses:

  • Running: The state machine is active and waiting for the next event
  • Pass: The state machine has completed successfully (reached a terminal state)
  • Error: The state machine encountered an error

You can filter by status — for example, to show only active (Running) state machines on the quest screen, or to find completed ones that need cleanup.

Request

TypeConditionRequiredDefaultValue LimitsDescription
namespaceNamestring
~ 128 charsNamespace name
Namespace-specific name. Specified using alphanumeric characters, hyphens (-), underscores (_), and periods (.).
gameSessionGameSession
GameSession
statusStatus
The current execution status of this state machine instance. “Running” means the machine is actively processing transitions. “Wait” means the machine is waiting for an external event (emit). “Pass” means it completed successfully. “Error” means it terminated with an error.
DefinitionDescription
“Running”Running
“Wait”Wait
“Pass”Pass
“Error”Error
pageTokenstring~ 1024 charsToken specifying the position from which to start acquiring data
limitint301 ~ 1000Number of data acquired

Result

TypeDescription
itemsList<EzStatus>List of Status of State Machine
nextPageTokenstringPage token to retrieve the rest of the listing

Implementation Example

    var domain = gs2.StateMachine.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    );
    var items = await domain.StatusesAsync(
        status: "Running"
    ).ToListAsync();
    var domain = gs2.StateMachine.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    );
    var it = domain.Statuses(
        status: "Running"
    );
    List<EzStatus> items = new List<EzStatus>();
    while (it.HasNext())
    {
        yield return it.Next();
        if (it.Error != null)
        {
            onError.Invoke(it.Error, null);
            break;
        }
        if (it.Current != null)
        {
            items.Add(it.Current);
        }
        else
        {
            break;
        }
    }
    const auto Domain = Gs2->StateMachine->Namespace(
        "namespace-0001" // namespaceName
    )->Me(
        GameSession
    );
    const auto It = Domain->Statuses(
        "Running" // status
    );
    TArray<Gs2::UE5::StateMachine::Model::FEzStatusPtr> Result;
    for (auto Item : *It)
    {
        if (Item.IsError())
        {
            return false;
        }
        Result.Add(Item.Current());
    }
Value change event handling
    var domain = gs2.StateMachine.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    );
    
    // Start event handling
    var callbackId = domain.SubscribeStatuses(
        () => {
            // Called when an element of the list changes.
        }
    );

    // Stop event handling
    domain.UnsubscribeStatuses(callbackId);
    var domain = gs2.StateMachine.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    );
    
    // Start event handling
    var callbackId = domain.SubscribeStatuses(
        () => {
            // Called when an element of the list changes.
        }
    );

    // Stop event handling
    domain.UnsubscribeStatuses(callbackId);
    const auto Domain = Gs2->StateMachine->Namespace(
        "namespace-0001" // namespaceName
    )->Me(
        GameSession
    );
    
    // Start event handling
    const auto CallbackId = Domain->SubscribeStatuses(
        []() {
            // Called when an element of the list changes.
        }
    );

    // Stop event handling
    Domain->UnsubscribeStatuses(CallbackId);

report

Submit client-side state machine execution results for server validation

Sends a batch of events that were processed locally on the game client to the server for validation. This is an optimization feature called “speculative execution” — instead of calling Emit for every single event (which adds network latency each time), the client runs the state machine locally, processes multiple events at once, and then sends all the results to the server in a single call.

How speculative execution works:

  1. The client has a local copy of the state machine definition
  2. When events occur rapidly (e.g., during gameplay), the client processes them locally without waiting for server responses
  3. After a batch of events, the client calls Report to send all events to the server
  4. The server replays the events and verifies that the final state matches what the client reported
  5. If the states match, the server accepts the result. If they don’t match (e.g., client was tampered with), a StateMismatch error is returned

This is useful for performance-sensitive scenarios like:

  • Fast-paced gameplay where waiting for server responses would cause lag
  • Offline-capable flows where the player might lose connection temporarily
  • Batch processing of many rapid state transitions

Note: Speculative execution must be enabled on the namespace for this API to work.

Request

TypeConditionRequiredDefaultValue LimitsDescription
namespaceNamestring
~ 128 charsNamespace name
Namespace-specific name. Specified using alphanumeric characters, hyphens (-), underscores (_), and periods (.).
gameSessionGameSession
GameSession
statusNamestring
~ 36 charsStatus name
eventsList<EzEvent>0 ~ 1000 itemsList of events

Result

TypeDescription
itemEzStatusStatus of State Machine

Error

Special exceptions are defined in this API. GS2-SDK for GameEngine provides specialized exceptions derived from general exceptions to facilitate handling of errors that may need to be handled in games. Please refer to the documentation here for more information on common error types and handling methods.

TypeBase TypeDescription
StateMismatchExceptionBadRequestExceptionState of the verification result of the report is inconsistent.

Implementation Example

try {
    var domain = gs2.StateMachine.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).Status(
        statusName: "status-0001"
    );
    var result = await domain.ReportAsync(
        events: new List<Gs2.Unity.Gs2StateMachine.Model.EzEvent> {
            new Gs2.Unity.Gs2StateMachine.Model.EzEvent() {
                EventType = "emit",
                EmitEvent = 
                new Gs2.Unity.Gs2StateMachine.Model.EzEvent() {
                    Event = "message",
                    Parameters = "{\"payload\": \"Hello World\"}",
                    Timestamp = 1000,
                },
            },
        }
    );
    var item = await result.ModelAsync();
} catch(Gs2.Gs2StateMachine.Exception.StateMismatchException e) {
    // State of the verification result of the report is inconsistent.
}
    var domain = gs2.StateMachine.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).Status(
        statusName: "status-0001"
    );
    var future = domain.ReportFuture(
        events: new List<Gs2.Unity.Gs2StateMachine.Model.EzEvent> {
            new Gs2.Unity.Gs2StateMachine.Model.EzEvent() {
                EventType = "emit",
                EmitEvent = 
                new Gs2.Unity.Gs2StateMachine.Model.EzEvent() {
                    Event = "message",
                    Parameters = "{\"payload\": \"Hello World\"}",
                    Timestamp = 1000,
                },
            },
        }
    );
    yield return future;
    if (future.Error != null)
    {
        if (future.Error is Gs2.Gs2StateMachine.Exception.StateMismatchException)
        {
            // State of the verification result of the report is inconsistent.
        }
        onError.Invoke(future.Error, null);
        yield break;
    }
    var future2 = future.Result.ModelFuture();
    yield return future2;
    if (future2.Error != null)
    {
        onError.Invoke(future2.Error, null);
        yield break;
    }
    var result = future2.Result;
    const auto Domain = Gs2->StateMachine->Namespace(
        "namespace-0001" // namespaceName
    )->Me(
        GameSession
    )->Status(
        "status-0001" // statusName
    );
    const auto Future = Domain->Report(
        []
        {
            auto v = MakeShared<TArray<TSharedPtr<Gs2::UE5::StateMachine::Model::FEzEvent>>>();
            v->Add(
                MakeShared<Gs2::UE5::StateMachine::Model::FEzEvent>()
                ->WithEventType(TOptional<FString>("emit"))
                ->WithEmitEvent(MakeShared<Gs2::UE5::StateMachine::Model::FEzEmitEvent>() 
                    ->WithEvent(TOptional<FString>("message"))
                    ->WithParameters(TOptional<FString>("{\"payload\": \"Hello World\"}"))
                    ->WithTimestamp(TOptional<int32>(1000))
                );
            );
            return v;
        }() // events
    );
    Future->StartSynchronousTask();
    if (Future->GetTask().IsError())
    {
        auto e = Future->GetTask().Error();
        if (e->IsChildOf(Gs2::StateMachine::Error::FStateMismatchError::Class))
        {
            // State of the verification result of the report is inconsistent.
        }
        return false;
    }

    // obtain changed values / result values
    const auto Future2 = Future->GetTask().Result()->Model();
    Future2->StartSynchronousTask();
    if (Future2->GetTask().IsError())
    {
        return Future2->GetTask().Error();
    }
    const auto Result = Future2->GetTask().Result();