{"id":13676103,"url":"https://github.com/k-okawa/UniTaskStateMachine","last_synced_at":"2025-04-29T03:30:33.161Z","repository":{"id":37098102,"uuid":"394295144","full_name":"k-okawa/UniTaskStateMachine","owner":"k-okawa","description":"StateMachine for UniTask. StateMachine Editor Included.","archived":false,"fork":false,"pushed_at":"2022-10-26T09:45:04.000Z","size":177,"stargazers_count":97,"open_issues_count":0,"forks_count":15,"subscribers_count":5,"default_branch":"master","last_synced_at":"2024-11-11T17:45:44.166Z","etag":null,"topics":["asynchronous","csharp","state-machine","task","thread","unitask","unity","unityeditor"],"latest_commit_sha":null,"homepage":"","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/k-okawa.png","metadata":{"files":{"readme":"README.ja.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2021-08-09T13:07:56.000Z","updated_at":"2024-10-25T04:24:38.000Z","dependencies_parsed_at":"2023-01-19T10:24:53.418Z","dependency_job_id":null,"html_url":"https://github.com/k-okawa/UniTaskStateMachine","commit_stats":null,"previous_names":[],"tags_count":6,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/k-okawa%2FUniTaskStateMachine","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/k-okawa%2FUniTaskStateMachine/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/k-okawa%2FUniTaskStateMachine/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/k-okawa%2FUniTaskStateMachine/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/k-okawa","download_url":"https://codeload.github.com/k-okawa/UniTaskStateMachine/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":251426697,"owners_count":21587633,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["asynchronous","csharp","state-machine","task","thread","unitask","unity","unityeditor"],"created_at":"2024-08-02T13:00:18.386Z","updated_at":"2025-04-29T03:30:32.519Z","avatar_url":"https://github.com/k-okawa.png","language":"C#","funding_links":[],"categories":["Open Source Repositories"],"sub_categories":["AI"],"readme":"# UniTaskStateMachine\n\n[[English](https://github.com/k-okawa/UniTaskStateMachine/blob/master/README.md)]\n\n[![openupm](https://img.shields.io/npm/v/com.bg.unitaskstatemachine?label=openupm\u0026registry_uri=https://package.openupm.com)](https://openupm.com/packages/com.bg.unitaskstatemachine/)\n\n以下のように戻り値がUniTaskになっているので、非同期に対応したステートマシーンを利用することができます。\n```c#\npublic interface IState\n{\n    void Init(BaseNode baseNode);\n    UniTask OnEnter(CancellationToken ct = default);\n    UniTask OnUpdate(CancellationToken ct = default);\n    UniTask OnExit(CancellationToken ct = default);\n}\n```\n\nそのため以下の特徴があります\n- OnEnterが終了するまでOnUpdateのループが始まらない\n- OnExitが終了するまで次のステートに移行しない\n- OnUpdateは１フレームごとに呼ばれるがawaitしている間は呼ばれない\n\nまたステートの移行方法は以下を対応しています\n- Transition(矢印)に判定を持たせ、条件が一致したときに移行\n- TransitionIDを指定して次のステートに移行\n  - 現在のステートが指定されたTransitionIDを持っていない場合は無視される\n  \nEditorツールも提供しているので、簡単にステートを組むことが可能です。\n\n(スクリプト上で組むことも可能です)\n\n![image](https://user-images.githubusercontent.com/49301086/183348165-6042c870-ac33-479a-b5fa-af210f345352.png)\n\n\n## インストール\n### 依存関係\nパッケージ内でUniTaskを使用しているので、UniTaskがプロジェクト内に追加されている必要があります。\n\n[UniTask](https://github.com/Cysharp/UniTask)\n\nPackageManager,unitypackageのどちらで追加しても動作します。\n\nUniRxから分割される前のUniTask(UniRx.Async)を使用している場合は、\n\nProjectSettings/Player/OtherSettings/ScriptingDefineSymbolで以下を定義することで使用可能になります。\n\n```\nBG_USE_UNIRX_ASYNC\n```\n\n### PackageManager\n\n### GitHub経由でインストール\n\nWindow/Package Managerを開き、add package from git URL...で以下を入力して追加してください。\n\n```\nhttps://github.com/k-okawa/UniTaskStateMachine.git?path=Assets/Bg/UniTaskStateMachine\n```\n\n### OpenUPM経由でインストール\n\n```\nopenupm add com.bg.unitaskstatemachine\n```\n\n### UnityPackage\n\n[リリースページ](https://github.com/k-okawa/UniTaskStateMachine/releases)からダウンロード可能です。\n\n## 使い方\n### 1.StateMachineBehaviour追加\nStateMachineBehaviourをAddComponentします。\n\n![image](https://user-images.githubusercontent.com/49301086/143770544-d014aac1-e8a1-4c54-b1bf-d2945216f480.png)\n\n### 2.GraphEditorを開く\n1で追加したStateMachineBehaviourのGraphEditorOpen、\n\nまたはWindow/BG UniTaskStateMachine/StateMachineGraphでグラフエディタを開くことができます。\n\n![image](https://user-images.githubusercontent.com/49301086/183349573-556b2bfb-968c-40ef-91b9-acde45bf5f65.png)\n\n### 3.State追加方法\n#### 3-1.StateBehaviourを追加\nStateMachineBehaviourがアタッチされているGameObjectにBaseStateComponentを継承したComponentを追加します。\n\n※BaseStateComponentを継承したクラスをさらに継承はしないでください。\n\n※BaseStateComponentを直接AddComponentしないでください。\n\n※同じStateComponentを同じゲームオブジェクトにAddComponentしないでください。\n\n**例**\n```c#\nnamespace Bg.UniTaskStateMachine.Tests.BasicSceneTest\n{\n    public class StartState : BaseStateComponent\n    {\n        public override async UniTask OnEnter(CancellationToken ct = default)\n        {\n\n        }\n\n        public override async UniTask OnUpdate(CancellationToken ct = default)\n        {\n\n        }\n\n        public override async UniTask OnExit(CancellationToken ct = default)\n        {\n\n        }\n    }\n}\n```\n\n![image](https://user-images.githubusercontent.com/49301086/143770911-aa150949-1ece-4ea1-833d-1de973e09c0e.png)\n\n#### 3-2.追加したStateBehaviourを指定\n\nGraphエディタ上で右クリックし、CreateStateでState追加\n\n![image](https://user-images.githubusercontent.com/49301086/183352350-6de6bec5-b304-4a1a-b668-049c6841a9eb.png)\n\n追加されているクラス名が表示され選択可能になります。\n\n![image](https://user-images.githubusercontent.com/49301086/143771064-9915284a-fd38-4b00-b0f7-2a22c120c972.png)\n\nNoneを選択した場合何もしないステートになります。\n\n### 4.Transition追加方法\n追加されているStateの上で右クリックし、MakeTransitionを選択することでTransitionを追加することができます。\n\n![image](https://user-images.githubusercontent.com/49301086/143771406-b0e40166-fd07-4091-8e98-a5cac1ba83f2.png)\n\nStateMachineBehaviourがアタッチされているGameObjectのComponentの中のpublicで戻り値がbool、引数なしの関数をステートの遷移条件として使用することができます。\n\n![image](https://user-images.githubusercontent.com/49301086/143771235-8a12410e-21af-47d5-a7bb-bf1e9c03d1ae.png)\n\nIsNegativeにチェックを入れることで条件を反対にすることができます。\n\nまたMethodNameの指定をNoneにすると、常に条件を満たさないTransitionになります。\n\n後述するTriggerNextTransitionを呼び出すことでスクリプトから強制的に遷移を実行することも可能です。\n\n\n![image](https://user-images.githubusercontent.com/49301086/143771269-6ffcd819-480a-4783-8f9f-ae28171c3036.png)\n\n### 5.EntryState指定\n最初に実行するStateを必ず指定する必要があります。\n\nStateを右クリックし、Set as Entryを選択することで設定することができます。\n\n![image](https://user-images.githubusercontent.com/49301086/143771406-b0e40166-fd07-4091-8e98-a5cac1ba83f2.png)\n\n### TriggerNextTransition\n\nトランジションに条件を指定する以外にも、IDを指定してステートを遷移させることが可能です。\n\nトランジションIDはC#のフィールド名で使用可能なアッパーキャメルケースを推奨します。\n\nすべてのトランジションIDを決めた後、GenerateTransitionIdConstボタンを使用して定数のテンプレートコードを生成できます。\n\n![image](https://user-images.githubusercontent.com/49301086/183354384-8c33ea1d-53a3-4bae-95f1-2011c0ddd660.png)\n\n最後に、\"StateMachine.TriggerNextTransition(string transitionId)\"を呼び出すだけで好きなタイミングでステート遷移が可能です\n\n引数に文字列を直接渡すことができますが、生成されたクラスの読み取り専用のフィールドで渡すことを推奨します。\n\n## API Reference\n### StateMachine\nStateMachineBehaviourのStateMachineプロパティからアクセスできます。\n\n#### プロパティ\n\n```c#\n// エントリーステート\npublic BaseNode EntryNode;\n\n// 現在のステートノード\npublic BaseNode CurrentNode { get; private set; }\n\n// 現在のStateMachineの実行状態(STOP,START,PAUSE)\npublic State CurrentState { get; private set; } = State.STOP;\n\n// OnUpdateを呼ぶタイミング\npublic PlayerLoopTiming LoopTiming = PlayerLoopTiming.Update;\n```\n\n#### メソッド\n\n```c#\n/// \u003csummary\u003e\n/// ステートマシンを開始する\n/// \u003c/summary\u003e\npublic async void Start();\n\n/// \u003csummary\u003e\n/// ステートマシーンを完全に停止する\n/// \u003c/summary\u003e\npublic void Stop();\n\n/// \u003csummary\u003e\n/// 現在のステートを一時停止状態にする\n/// \u003c/summary\u003e\npublic void Pause();\n\n/// \u003csummary\u003e\n/// 現在のステートを再開する\n/// \u003c/summary\u003e\npublic void Resume();\n\n/// \u003csummary\u003e\n/// エントリーステートからステートマシンを再実行\n/// \u003c/summary\u003e\npublic async UniTask ReStart(CancellationToken ct = default);\n\n/// \u003csummary\u003e\n/// 強制的に次のステートに遷移させる\n/// \u003c/summary\u003e\n/// \u003cparam name=\"transitionId\"\u003eGraphエディターで指定したtransitionId\u003c/param\u003e\npublic void TriggerNextTransition(string transitionId);\n\n/// \u003csummary\u003e\n/// 現在実行中のステートと等しいかどうか調べる\n/// \u003c/summary\u003e\n/// \u003cparam name=\"type\"\u003eステートタイプ\u003c/param\u003e\n/// \u003creturns\u003e現在のステートが引数のtypeと一致した場合trueを返す\u003c/returns\u003e\npublic bool IsMatchCurrentStateType(Type type);\n\n/// \u003csummary\u003e\n/// ほとんどIsMatchCurrentStateTypeと同じ\n/// 違いは引数が可変長引数になっていること\n/// \u003c/summary\u003e\n/// \u003cparam name=\"types\"\u003eステートタイプ\u003c/param\u003e\n/// \u003creturns\u003e現在のステートが引数のいずれかのtypeと一致した場合trueを返す\u003c/returns\u003e\npublic bool IsMatchAnyCurrentStateType(params Type[] types);\n```\n\n### BaseStateComponent\n#### プロパティ\n\n```c#\n// 現在のステートのNode(StateとTransitionが一緒になっているもの)\nprotected BaseNode baseNode;\n```\n\n#### メソッド\n\n```c#\npublic virtual void Init(BaseNode baseNode);\npublic virtual async UniTask OnEnter(CancellationToken ct = default);\npublic virtual async UniTask OnUpdate(CancellationToken ct = default);\npublic virtual async UniTask OnExit(CancellationToken ct = default);\n```\n\n### BaseNode\n\n#### プロパティ\n\n```c#\npublic readonly string Id;\npublic readonly StateMachine StateMachine;\npublic bool IsUpdate { get; private set; } = true;\n```\n\n#### メソッド\n\n```c#\n/// \u003csummary\u003e\n/// いずれかの遷移条件がマッチしているか\n/// \u003c/summary\u003e\n/// \u003creturns\u003eひとつでも遷移条件にマッチしているものがあればtrueを返す\u003c/returns\u003e\npublic bool IsMatchAnyCondition();\n\n/// \u003csummary\u003e\n/// TriggerNextTransitionによって強制的に遷移する状態になっているか\n/// \u003c/summary\u003e\n/// \u003creturns\u003eひとつでも強制的に遷移する状態のものがあればtrueを返す\u003c/returns\u003e\npublic bool IsExistForceTransition();\n\n/// \u003csummary\u003e\n/// Graphエディター上の矢印(Transition)の基底クラスを取得する\n/// \u003c/summary\u003e\n/// \u003cparam name=\"id\"\u003eGraphエディター上のTransitionId\u003c/param\u003e\npublic BaseCondition GetCondition(string id);\n\n/// \u003csummary\u003e\n/// Nodeが持っているTransitionのIdをすべて取得する\n/// \u003c/summary\u003e\npublic IEnumerable\u003cstring\u003e GetTransitionIds();\n```\n\n### BaseCondition\n#### プロパティ\n\n```c#\npublic BaseNode NextNode { get; }\npublic Func\u003cbool\u003e ConditionCheckCallback { get; }\npublic string TransitionId { get; }\npublic bool IsNegative =\u003e isNegative;\npublic bool IsForceTransition =\u003e isForceTransition;\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fk-okawa%2FUniTaskStateMachine","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fk-okawa%2FUniTaskStateMachine","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fk-okawa%2FUniTaskStateMachine/lists"}