GS2-StateMachine SDK for Game Engine API リファレンス

モデル

EzStatus

ステートマシンの状態

必須デフォルト値の制限説明
statusIdstring~ 1024文字ステートマシンの状態GRN
namestringUUID~ 36文字ステータス名
enableSpeculativeExecutionenum {
    “enable”,
    “disable”
}
“disable”~ 128文字投機的実行を有効にするか
stateMachineDefinitionstring{enableSpeculativeExecution} == “enable”~ 16777216文字ステートマシン定義
randomStatusEzRandomStatus{enableSpeculativeExecution} == “enable”乱数状態
stacksList<EzStackEntry>~ 1024 itemsスタック
variablesList<EzVariable>~ 1000 itemsステートマシンごとの状態変数
statusenum {
    “Running”,
    “Wait”,
    “Pass”,
    “Error”
}
“Running”~ 128文字ステータス
lastErrorstring~ 1024文字最後のエラー
transitionCountint0~ 2147483645遷移回数

enableSpeculativeExecution に指定する列挙型の定義

定義説明
enable有効
disable無効

status に指定する列挙型の定義

定義説明
Running実行中
Wait待機中
Pass終了
Errorエラー

EzStackEntry

スタック

必須デフォルト値の制限説明
stateMachineNamestring~ 128文字ステートマシン名
taskNamestring~ 128文字タスク名

EzVariable

ステートマシンごとの状態変数

必須デフォルト値の制限説明
stateMachineNamestring~ 128文字ステートマシン名
valuestring~ 1048576文字

EzChangeStateEvent

ステートの変更イベント

必須デフォルト値の制限説明
taskNamestring~ 128文字タスク名
hashstring~ 64文字ハッシュ
timestamplongタイムスタンプ (UNIX時間 単位:ミリ秒)

EzEmitEvent

メッセージの送信イベント

必須デフォルト値の制限説明
eventstring~ 128文字イベント名
parametersstring~ 1024文字パラメータ
timestamplongタイムスタンプ (UNIX時間 単位:ミリ秒)

EzEvent

イベント

必須デフォルト値の制限説明
eventTypeenum {
    “change_state”,
    “emit”
}
~ 128文字イベントの種類
changeStateEventEzChangeStateEvent{eventType} == “change_state”ステートの変更
emitEventEzEmitEvent{eventType} == “emit”メッセージの送信

eventType に指定する列挙型の定義

定義説明
change_stateステートの変更
emitメッセージの送信

EzRandomStatus

乱数の状態

必須デフォルト値の制限説明
seedlong~ 4294967294乱数シード
usedList<EzRandomUsed>~ 1000 items使用済み乱数リスト

EzRandomUsed

使用済み乱数

必須デフォルト値の制限説明
categorylong~ 4294967294カテゴリ
usedlong~ 4294967294使用済み乱数

メソッド

emit

ステートマシンにイベントを送信

Request

必須デフォルト値の制限説明
namespaceNamestring~ 128文字ネームスペース名
accessTokenstring~ 128文字ユーザーID
statusNamestring~ 36文字ステータス名
eventNamestring~ 36文字イベントの名前
argsstring“{}”~ 4096文字ステートマシンに渡す引数

Result

説明
itemEzStatusステートマシンの状態

実装例

    var domain = gs2.StateMachine.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).Status(
        statusName: "$status1.name"
    );
    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: "$status1.name"
    );
    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.Model();
    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(
        "$status1.name" // 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

終了したステートマシンを削除

Request

必須デフォルト値の制限説明
namespaceNamestring~ 128文字ネームスペース名
accessTokenstring~ 128文字ユーザーID
statusNamestring~ 36文字ステータス名

Result

説明
itemEzStatus終了したステートマシンの状態

実装例

    var domain = gs2.StateMachine.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).Status(
        statusName: "$status1.name"
    );
    var result = await domain.ExitAsync(
    );
    var domain = gs2.StateMachine.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).Status(
        statusName: "$status1.name"
    );
    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(
        "$status1.name" // statusName
    );
    const auto Future = Domain->Exit(
    );
    Future->StartSynchronousTask();
    if (Future->GetTask().IsError())
    {
        return false;
    }
    const auto Result = Future->GetTask().Result();

getStatus

ステートマシンの現在の状態を取得

Request

必須デフォルト値の制限説明
namespaceNamestring~ 128文字ネームスペース名
accessTokenstring~ 128文字ユーザーID
statusNamestring~ 36文字ステータス名

Result

説明
itemEzStatusステートマシンの状態

実装例

    var domain = gs2.StateMachine.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).Status(
        statusName: "$status1.name"
    );
    var item = await domain.ModelAsync();
    var domain = gs2.StateMachine.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).Status(
        statusName: "$status1.name"
    );
    var future = domain.Model();
    yield return future;
    var item = future.Result;
    const auto Domain = Gs2->StateMachine->Namespace(
        "namespace-0001" // namespaceName
    )->Me(
        GameSession
    )->Status(
        "$status1.name" // statusName
    );
    const auto Future = Domain->Model();
    Future->StartSynchronousTask();
    if (Future->GetTask().IsError())
    {
        return false;
    }
値の変更イベントハンドリング
    var domain = gs2.StateMachine.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).Status(
        statusName: "$status1.name"
    );
    
    // イベントハンドリングを開始
    var callbackId = domain.Subscribe(
        value => {
            // 値が変化した時に呼び出される
            // value には変更後の値が渡ってくる
        }
    );

    // イベントハンドリングを停止
    domain.Unsubscribe(callbackId);
    var domain = gs2.StateMachine.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).Status(
        statusName: "$status1.name"
    );
    var future = domain.Model();
    yield return future;
    var item = future.Result;
    const auto Domain = Gs2->StateMachine->Namespace(
        "namespace-0001" // namespaceName
    )->Me(
        GameSession
    )->Status(
        "$status1.name" // statusName
    );
    
    // イベントハンドリングを開始
    const auto CallbackId = Domain->Subscribe(
        [](TSharedPtr<Gs2::StateMachine::Model::FStatus> value) {
            // 値が変化した時に呼び出される
            // value には変更後の値が渡ってくる
        }
    );

    // イベントハンドリングを停止
    Domain->Unsubscribe(CallbackId);

listStatuses

ステートマシンの現在の状態の一覧を取得

Request

必須デフォルト値の制限説明
namespaceNamestring~ 128文字ネームスペース名
accessTokenstring~ 128文字ユーザーID
statusenum {
    “Running”,
    “Wait”,
    “Pass”,
    “Error”
}
~ 128文字ステータス
pageTokenstring~ 1024文字データの取得を開始する位置を指定するトークン
limitint301 ~ 1000データの取得件数

status に指定する列挙型の定義

定義説明
Running実行中
Wait待機中
Pass終了
Errorエラー

Result

説明
itemsList<EzStatus>ステートマシンの状態のリスト
nextPageTokenstringリストの続きを取得するためのページトークン

実装例

    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());
    }
値の変更イベントハンドリング
    var domain = gs2.StateMachine.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    );
    
    // イベントハンドリングを開始
    var callbackId = domain.SubscribeStatuses(
        () => {
            // リストの要素が変化した時に呼び出される
        }
    );

    // イベントハンドリングを停止
    domain.UnsubscribeStatuses(callbackId);
    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 CallbackId = Domain->SubscribeStatuses(
        []() {
            // リストの要素が変化した時に呼び出される
        }
    );

    // イベントハンドリングを停止
    Domain->UnsubscribeStatuses(CallbackId);

report

ステートマシンの投機的実行結果を送信

Request

必須デフォルト値の制限説明
namespaceNamestring~ 128文字ネームスペース名
accessTokenstring~ 128文字ユーザーID
statusNamestring~ 36文字ステータス名
eventsList<EzEvent>~ 1000 itemsイベントのリスト

Result

説明
itemEzStatusステートマシンの状態

Error

このAPIには特別な例外が定義されています。
GS2-SDK for GameEngine ではゲーム内でハンドリングが必要そうなエラーは一般的な例外から派生した特殊化した例外を用意することでハンドリングしやすくしています。
一般的なエラーの種類や、ハンドリング方法は こちら のドキュメントを参考にしてください。

基底クラス説明
StateMismatchExceptionBadRequestExceptionレポートの検証の結果状態が不一致となりました

実装例

try {
    var domain = gs2.StateMachine.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).Status(
        statusName: "$status1.name"
    );
    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.StateMismatch e) {
    // State of the verification result of the report is inconsistent.
}
    var domain = gs2.StateMachine.Namespace(
        namespaceName: "namespace-0001"
    ).Me(
        gameSession: GameSession
    ).Status(
        statusName: "$status1.name"
    );
    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.Model();
    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(
        "$status1.name" // 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();