StateMachine Speculative Execution Session API (Unity)

APIs for calling operations, reading state, and receiving server verification from the generated C# classes

This Session is a class for using GS2-StateMachine speculative execution from Unity. It runs the user’s progress on the client and sends the operation history to StateMachine’s Report API for verification. The game screen operates through Session methods and reads the local execution results from the View.

It is not used for Realtime room connections or syncing with other players. For the mechanism that reflects shared objects in Unity, see Unity Object Sync.

This page describes the caller-side APIs. For the game rules format, see the C# Definition Reference; for the generation steps, see the Tutorial. The Session is generated when hostProfile in the generation settings is LocalReplayV1 (the default).

CounterSession is generated from the rules class Counter. Below, its instance is written as game. The state, result, and input types are generated in the namespace from the generation settings.

PurposeAPI
Operate the gameMethods with the same names as the definition’s operations
Display the current stateView / ViewChanged
Open a game already started on the serverOpenAsync / OpenFuture
Connect to a runtime such as the previewFromExecutor
Verify the operation history on the serverConfirmAsync / ConfirmFuture

Operation Methods

Methods with the same names as the public operations in the definition are generated. The runtime passes the state, random number, and reward arguments, so they are not included in the Session-side parameters.

// Definition side: public static Step Add(CounterState state, int amount)
var outcome = game.Add(3);

The return value is InputResult<TCode>. TCode is the enum of Ignore reasons specified in the definition.

PropertyTypeDescription
AcceptedboolWhether local execution adopted the input
IgnoredboolWhether the input was rolled back by Ignore
CodeTCode?The Ignore reason. null if there is no reason or the code is unknown
RawCodeint?The original numeric value of the Ignore reason. null if there is no reason

Accepted does not mean server-verified. Verification happens separately with Confirm.

var outcome = game.Add(0);
if (outcome.Ignored)
    Debug.Log("Input was not accepted: " + outcome.Code);

Calling an operation that is not currently accepted throws an exception. Runtime errors such as division by zero are also different from Ignore and are not returned as a normal operation result.

View / ViewChanged

game.View is a snapshot of the current state. The properties of the generated state and result classes are read-only. To change the state, call operation methods.

var count = game.View.State.Count;
var canAdd = game.View.Actions.Add;
MemberDescription
View.StateThe current state. Its type is the generated class corresponding to the definition’s TState
View.ResultThe finish result. Its type is the generated class corresponding to the definition’s TResult. null while there is no result
View.Actions.<operation name>A bool indicating whether that operation is accepted at the current wait point
View.RevisionThe revision of the operation history
View.StatusThe execution status ActiveStateMachineStatus
ViewChangedAn Action<SessionView> notification fired when the View is updated

View.Actions indicates “whether you are at a point that accepts that operation”. It does not evaluate game-specific conditions checked inside the operation, such as insufficient materials.

After creating the Session, you can subscribe to update notifications as follows. ViewChanged does not fire on Ignore.

game.ViewChanged += view => Debug.Log("Count: " + view.State.Count);

Values of View.Status

ValueMeaning
InitializedBefore execution starts
RunningProcessing is running
WaitWaiting for the next operation
PassFinished normally. The definition’s End has been reached
ErrorStopped due to a runtime error

You can determine normal completion of the game with View.Status == ActiveStateMachineStatus.Pass. This is the local execution status and does not indicate that server verification is complete.

OpenAsync / OpenFuture

Opens a status already started on the server and creates a Session. You must first start the target user’s state machine with StateMachine’s start API or similar.

var game = await CounterSession.OpenAsync(
    gs2, gameSession, namespaceName, statusName);
ParameterDescription
gs2The SDK entry point Gs2Domain
gameSessionThe logged-in user’s information IGameSession
namespaceNameThe GS2-StateMachine namespace name
statusNameThe name of the started status

The Async form returns UniTask<CounterSession> and requires GS2_ENABLE_UNITASK. If you don’t use UniTask, use OpenFuture with the same arguments. Its return value is Gs2Future<CounterSession>.

On connection, the GSL hash is checked. If the Session and the registered definition do not match, it is an error. When you update the definition, regenerate the Session as well, and use the Session corresponding to the old definition for games in progress under the old definition.

FromExecutor

Connects a Session to an existing Executor. The Executor is LocalStateMachineKit’s execution class that handles GSL execution and the operation history.

var game = CounterSession.FromExecutor(executor);

The argument is a LocalStateMachineExecutor, and the return value is a CounterSession. This API also checks the definition hash.

For example, passing an Executor created with LocalStateMachineExecutor.CreatePreview(gsl, "Counter") connects to a preview without login. For a concrete creation example, see the Tutorial. The preview has no history to send to the server and cannot be handed over to the live service midway.

ConfirmAsync / ConfirmFuture

Sends the operation history so far to the server and waits for the verification result. You can call it during the game or after it finishes.

await game.ConfirmAsync(gs2, gameSession);

The arguments are the same Gs2Domain and IGameSession as Open. The Async form returns UniTask and requires GS2_ENABLE_UNITASK. If you don’t use UniTask, use ConfirmFuture. Its return value is Gs2Future.

Check local input acceptance, server verification, and reward application in the following ways.

StageHow to checkWhat you can confirm
Local executionAccepted in the operation resultThe input was adopted locally
Server verificationConfirm completes successfullyThe sent operation history was accepted by the server
Reward applicationGet the state of the granting serviceAsynchronous reward processing has been reflected in inventory, etc.

A successful Confirm alone does not mean reward application is complete.

Checking the Send State

PropertyDescription
PendingEventCountThe number of pending events
IsConfirmingWhether sending and confirmation are in progress. New input is not accepted during this time
RequiresReconciliationWhether the Session must be recreated from the latest server state

After Confirm Completes or Fails

ResultHow the history is handledWhat to do next
Completed successfullyThe sent pending history is removed as confirmedIf the game is waiting for input, you can continue operating
Failed, RequiresReconciliation is falseThe unconfirmed history is keptResolve the cause and run Confirm again on the same Session
Failed, RequiresReconciliation is trueResending and new input from the same Session are not acceptedReopen the latest server state with Open and restore the screen

The SDK keeps the history and duplication-avoidance keys for resending. You don’t need to call the operations again to reproduce them. If the resend deadline passes, RequiresReconciliation becomes true on the next Confirm, and you need to reopen.

If both IsConfirming and RequiresReconciliation are false after a failure, you can continue the currently accepted operations locally. The added history is also sent by a later Confirm. However, don’t treat unconfirmed results as finalized on the server.

Pending history is kept in memory. A reopened Session does not carry over local operations not yet verified by the server. Saving across app restarts requires a separate design.

Use the Session and Executor from Unity’s main thread.