こんにちは、パパコーダーです。
現在、子ども向けのビジュアルプログラミング環境 「FUnity」 をUnityで開発しています。
Scratch風の操作でゲームを作れる環境を目指しており、UI ToolkitとVisual Scriptingを組み合わせながら構築中です。
今回のテーマは、Scratchにある重要な機能
==「すべてを止める」「このスクリプトを止める」「スプライトの他のスクリプトを止める」==
の実装についてです。
同じように苦労している方がいるかもしれないので、備忘録として残しておきます。
■ 今回直面した問題
Visual Scriptingで Scratch のようにスレッド(コルーチン)実行を制御しようとしたとき、
最初は単純に StartCoroutine() と StopCoroutine() で制御しようとしました。
しかし…
・StartCoroutine() の戻り値が null になることがある
・コルーチンの参照を保持し続ける必要がある
・複数Actor、複数スレッドになると管理が破綻する
・「このスクリプトだけ止める」「他のスクリプトだけ止める」判定が難しい
という壁にぶつかりました。
Scratchは実は
✔ 1つのイベントで複数スレッドが並列処理される
✔ スプライト単位でスレッドを識別し停止できる
という仕組みになっているため、単純なコルーチン方式ではうまくいきませんでした。
■ 解決への方向転換
今回思い切って、
==「Coroutine管理」から「Flow(Visual Scriptingの実行コンテキスト)管理」へ切り替える==
という方式に変更しました。
具体的な設計変更点
- Visual Scripting の
Flowに以下の2情報を保存 actorId(どのスプライトか)threadId(同一スプライト内の実行単位を一意に識別)- Flow単位でスレッドを登録
- ThreadManager として
FUnityScriptThreadManagerを用意 - 停止系ユニットで threadId に基づいて停止制御
Flow.isEndedなどの存在しないAPI参照は削除して整理
これにより、次のように実現できました:
・「すべてを止める」 → 登録されている全Flow停止
・「このスクリプトを止める」 → 自分の threadId だけ停止
・「スプライトの他のスクリプトを止める」 → actorId一致 & threadIdが違う Flow を停止
■ 実際の動作ログ
[FUnity.Thread] Register actor=actor-000001, thread=b27d041…
[FUnity.Thread] Register actor=actor-000002, thread=4402d15…
[FUnity.Thread] StopAll requested count=2
markdown
コードをコピーする
コルーチンを使っていたときは止まらなかったスクリプトが、
この方式ではきれいに制御できるようになりました。
■ 最大の学び
今回の苦労から得た教訓は
==「Unity Visual ScriptingのFlowは、実質スレッドとして扱える」==
ということでした。
最初はコルーチンの制御で回避しようとして行き詰まりましたが、
方向転換して Flow を中心に考え直すことで、一気に問題が解決しました。
「止める処理」ひとつとっても、
✨Scratchは表面上シンプルでも中身は深い✨
ということをあらためて感じました。
■ 今後の予定
- スレッド管理の最適化
- Runner生成の重複を整理して軽量化
- VSノードユニットのカテゴリ整理を継続
- AGENTS.md / VS_Scratch_Mapping.md の整備
引き続き、Scratch互換を目指してブラッシュアップしていきます。
■ さいごに
今回の件は手強かったですが、
一歩前進できて、本当に良かったです。
開発は地味に見えて、実はドラマの連続ですね。
少しでも参考になれば嬉しいです。
それではまた次回のFUnity開発ログでお会いしましょう!
パパコーダー

コメント