Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 14 additions & 11 deletions Docs/VS_Scratch_Mapping.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,17 +67,20 @@ Scratch ブロックと FUnity 独自 Visual Scripting Unit の対応関係で
## 制御
| Scratch ブロック (日本語) | FUnity Unit クラス | UnitTitle | UnitCategory | 備考 |
| --- | --- | --- | --- | --- |
| ○回繰り返す | FUnity.Runtime.Integrations.VisualScripting.Units.ScratchUnits.RepeatNUnit | ○回繰り返す | FUnity/Scratch/制御 | 指定回数ループ。定義: Runtime/.../LoopUnits.cs |
| ずっと | FUnity.Runtime.Integrations.VisualScripting.Units.ScratchUnits.ForeverUnit | ずっと | FUnity/Scratch/制御 | 永続ループ。Visual Scripting 標準の `ControlInputCoroutine` で Flow コルーチンを回し、`body` を毎フレーム実行してから 1 フレーム待機する。定義: Runtime/.../LoopUnits.cs |
| ○秒待つ | FUnity.Runtime.Integrations.VisualScripting.Units.ScratchUnits.WaitSecondsUnit | ○秒待つ | FUnity/Scratch/制御 | 指定時間待機。Visual Scripting 標準のコルーチン経由で待機し、完了後に後続フローへ進む。定義: Runtime/.../WaitSecondsUnit.cs |
| 自分のクローンを作る | FUnity.Runtime.Integrations.VisualScripting.Units.ScratchUnits.CreateCloneOfSelfUnit | 自分のクローンを作る | FUnity/Scratch/制御 | 自身を複製。定義: Runtime/.../CloneUnits.cs |
| ○のクローンを作る | FUnity.Runtime.Integrations.VisualScripting.Units.ScratchUnits.CreateCloneOfDisplayNameUnit | ○のクローンを作る | FUnity/Scratch/制御 | 指定俳優を複製。CloneAdapter 出力は廃止済み。定義: Runtime/.../CloneUnits.cs |
| クローンされたとき | FUnity.Runtime.Integrations.VisualScripting.Units.ScratchUnits.WhenIStartAsCloneUnit | クローンされたとき | Events/FUnity/Scratch/制御 | クローン生成時に発火する Scratch スクリプトの入口。`flow.StartCoroutine(trigger)` で起動後、`ScratchUnitUtil.RegisterScratchFlow` により Flow をスレッド登録して停止ブロックと連動させる。Flow の破棄は Visual Scripting のコルーチン側で行う。定義: Runtime/.../CloneUnits.cs |
| このクローンを削除する | FUnity.Runtime.Integrations.VisualScripting.Units.ScratchUnits.DeleteThisCloneUnit | このクローンを削除する | FUnity/Scratch/制御 | クローンを破棄。定義: Runtime/.../CloneUnits.cs |
| すべてを止める | FUnity.Runtime.Integrations.VisualScripting.Units.ScratchUnits.StopAllUnit | すべてを止める | FUnity/Scratch/制御 | Scratch 用スレッドテーブル経由で全スレッド停止。定義: Runtime/.../StopControlUnits.cs |
| このスクリプトを止める | FUnity.Runtime.Integrations.VisualScripting.Units.ScratchUnits.StopThisScriptUnit | このスクリプトを止める | FUnity/Scratch/制御 | Flow.variables から ActorId/ThreadId を取得し、`FUnityScriptThreadManager.StopScratchThread(actorId, threadId)` で自身のみ停止。定義: Runtime/.../StopControlUnits.cs |
| スプライトの他のスクリプトを止める | FUnity.Runtime.Integrations.VisualScripting.Units.ScratchUnits.StopOtherScriptsInSpriteUnit | スプライトの他のスクリプトを止める | FUnity/Scratch/制御 | 同俳優の他 Scratch スレッド停止。定義: Runtime/.../StopControlUnits.cs |
| もし○なら | FUnity.Runtime.Integrations.VisualScripting.Units.ScratchUnits.IfThenUnit | もし○なら | FUnity/Scratch/制御 | 条件成立時のみ本体を実行。定義: Runtime/.../ConditionUnits.cs |
| ○回繰り返す | FUnity.Runtime.Integrations.VisualScripting.Units.ScratchUnits.RepeatNUnit | ○回繰り返す | FUnity/Blocks/制御 | 指定回数ループ。定義: Runtime/.../LoopUnits.cs |
| ずっと | FUnity.Runtime.Integrations.VisualScripting.Units.ScratchUnits.ForeverUnit | ずっと | FUnity/Blocks/制御 | 永続ループ。Visual Scripting 標準の `ControlInputCoroutine` で Flow コルーチンを回し、`body` を毎フレーム実行してから 1 フレーム待機する。定義: Runtime/.../LoopUnits.cs |
| ○まで繰り返す | FUnity.Runtime.Integrations.VisualScripting.Units.ScratchUnits.RepeatUntilUnit | ○まで繰り返す | FUnity/Blocks/制御 | 条件が真になるまで body を実行し、毎反復で 1 フレーム待機する。定義: Runtime/.../LoopUnits.cs |
| ○秒待つ | FUnity.Runtime.Integrations.VisualScripting.Units.ScratchUnits.WaitSecondsUnit | ○秒待つ | FUnity/Blocks/制御 | 指定時間待機。Visual Scripting 標準のコルーチン経由で待機し、完了後に後続フローへ進む。定義: Runtime/.../WaitSecondsUnit.cs |
| ○まで待つ | FUnity.Runtime.Integrations.VisualScripting.Units.ScratchUnits.WaitUntilUnit | ○まで待つ | FUnity/Blocks/制御 | 条件成立まで 1 フレームずつ待機し、成立後に exit へ進む。定義: Runtime/.../WaitSecondsUnit.cs |
| 自分のクローンを作る | FUnity.Runtime.Integrations.VisualScripting.Units.ScratchUnits.CreateCloneOfSelfUnit | 自分のクローンを作る | FUnity/Blocks/制御 | 自身を複製。定義: Runtime/.../CloneUnits.cs |
| ○のクローンを作る | FUnity.Runtime.Integrations.VisualScripting.Units.ScratchUnits.CreateCloneOfDisplayNameUnit | ○のクローンを作る | FUnity/Blocks/制御 | 指定俳優を複製。CloneAdapter 出力は廃止済み。定義: Runtime/.../CloneUnits.cs |
| クローンされたとき | FUnity.Runtime.Integrations.VisualScripting.Units.ScratchUnits.WhenIStartAsCloneUnit | クローンされたとき | Events/FUnity/Blocks/制御 | クローン生成時に発火する Scratch スクリプトの入口。`flow.StartCoroutine(trigger)` で起動後、`ScratchUnitUtil.RegisterScratchFlow` により Flow をスレッド登録して停止ブロックと連動させる。Flow の破棄は Visual Scripting のコルーチン側で行う。定義: Runtime/.../CloneUnits.cs |
| このクローンを削除する | FUnity.Runtime.Integrations.VisualScripting.Units.ScratchUnits.DeleteThisCloneUnit | このクローンを削除する | FUnity/Blocks/制御 | クローンを破棄。定義: Runtime/.../CloneUnits.cs |
| すべてを止める | FUnity.Runtime.Integrations.VisualScripting.Units.ScratchUnits.StopAllUnit | すべてを止める | FUnity/Blocks/制御 | Scratch 用スレッドテーブル経由で全スレッド停止。定義: Runtime/.../StopControlUnits.cs |
| このスクリプトを止める | FUnity.Runtime.Integrations.VisualScripting.Units.ScratchUnits.StopThisScriptUnit | このスクリプトを止める | FUnity/Blocks/制御 | Flow.variables から ActorId/ThreadId を取得し、`FUnityScriptThreadManager.StopScratchThread(actorId, threadId)` で自身のみ停止。定義: Runtime/.../StopControlUnits.cs |
| スプライトの他のスクリプトを止める | FUnity.Runtime.Integrations.VisualScripting.Units.ScratchUnits.StopOtherScriptsInSpriteUnit | スプライトの他のスクリプトを止める | FUnity/Blocks/制御 | 同俳優の他 Scratch スレッド停止。定義: Runtime/.../StopControlUnits.cs |
| もし○なら | FUnity.Runtime.Integrations.VisualScripting.Units.ScratchUnits.IfThenUnit | もし○なら | FUnity/Blocks/制御 | 条件成立時のみ本体を実行。定義: Runtime/.../ConditionUnits.cs |
| もし○なら でなければ | FUnity.Runtime.Integrations.VisualScripting.Units.ScratchUnits.IfElseUnit | もし ○ なら でなければ | FUnity/Blocks/制御 | 条件の真偽で ifTrue/ifFalse へ分岐させる。定義: Runtime/.../ConditionUnits.cs |

### 停止ブロック

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,68 @@ private IEnumerator Run(Flow flow)
}
}

// 将来的には Scratch の「もし〇〇なら、でなければ」ブロックに対応する Unit を追加予定です。
// 追加時には IfThenUnit と同じ即時実行ポリシーを踏襲します。
/// <summary>
/// Scratch の「もし〇なら でなければ」ブロックを再現し、条件が真偽のどちらでも後続を分岐させる Unit です。
/// </summary>
[UnitTitle("もし ○ なら でなければ")]
[UnitShortTitle("もし〜なら/でなければ")]
[UnitCategory("FUnity/Blocks/制御")]
[UnitSubtitle("制御")]
[TypeIcon(typeof(FUnityScratchUnitIcon))]
public sealed class IfElseUnit : Unit
{
/// <summary>制御フローの入力ポートです。</summary>
[DoNotSerialize]
private ControlInput m_Enter;

/// <summary>条件が真のときに発火する ControlOutput です。</summary>
[DoNotSerialize]
private ControlOutput m_IfTrue;

/// <summary>条件が偽のときに発火する ControlOutput です。</summary>
[DoNotSerialize]
private ControlOutput m_IfFalse;

/// <summary>判定に使用する条件値を受け取る ValueInput です。</summary>
[DoNotSerialize]
private ValueInput m_Condition;

/// <summary>enter ポートへの参照を公開します。</summary>
public ControlInput Enter => m_Enter;

/// <summary>条件が真だった場合に進むポートへの参照を公開します。</summary>
public ControlOutput IfTrue => m_IfTrue;

/// <summary>条件が偽だった場合に進むポートへの参照を公開します。</summary>
public ControlOutput IfFalse => m_IfFalse;

/// <summary>条件入力ポートへの参照を公開します。</summary>
public ValueInput Condition => m_Condition;

/// <summary>
/// ポート定義を行い、条件評価後に真偽それぞれの出力へ遷移できるよう設定します。
/// </summary>
protected override void Definition()
{
m_Enter = ControlInput("enter", OnEnter);
m_IfTrue = ControlOutput("ifTrue");
m_IfFalse = ControlOutput("ifFalse");
m_Condition = ValueInput("condition", false);

Succession(m_Enter, m_IfTrue);
Succession(m_Enter, m_IfFalse);
Requirement(m_Condition, m_Enter);
}

/// <summary>
/// 条件を評価し、真なら ifTrue、偽なら ifFalse へ制御を分岐させます。
/// </summary>
/// <param name="flow">現在のフロー情報。</param>
/// <returns>分岐先の ControlOutput。</returns>
private ControlOutput OnEnter(Flow flow)
{
var condition = flow.GetValue<bool>(m_Condition);
return condition ? m_IfTrue : m_IfFalse;
Comment on lines +135 to +138
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Provide exit continuation from IfElseUnit branches

The new IfElseUnit only returns either ifTrue or ifFalse from OnEnter and defines no exit/control output to rejoin after the branch, so when the condition is false and the graph leaves the ifFalse port unconnected (the common case when modelling a Scratch “if/else” with an empty else), the script dead‑ends instead of continuing to the next block as Scratch does and as IfThenUnit already does with its exit output. This will halt scripts whenever the else branch is empty or not wired, diverging from Scratch control flow.

Useful? React with 👍 / 👎.

}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -125,4 +125,75 @@ private IEnumerator OnEnterCoroutine(Flow flow)
}
}
}

/// <summary>
/// Scratch の「〇まで繰り返す」ブロックを再現し、条件が成立するまで本体を反復実行するカスタム Unit です。
/// </summary>
[UnitTitle("○まで繰り返す")]
[UnitCategory("FUnity/Blocks/制御")]
[UnitSubtitle("制御")]
[TypeIcon(typeof(FUnityScratchUnitIcon))]
public sealed class RepeatUntilUnit : ScratchCoroutineUnitBase
{
/// <summary>ループ開始を受け取る ControlInput です。</summary>
[DoNotSerialize]
private ControlInput m_Enter;

/// <summary>各反復で実行する本体ポートです。</summary>
[DoNotSerialize]
private ControlOutput m_Body;

/// <summary>ループ終了後に後続へ進む ControlOutput です。</summary>
[DoNotSerialize]
private ControlOutput m_Exit;

/// <summary>終了条件を受け取る ValueInput です。</summary>
[DoNotSerialize]
private ValueInput m_Condition;

/// <summary>enter ポートへの参照を公開します。</summary>
public ControlInput Enter => m_Enter;

/// <summary>body ポートへの参照を公開します。</summary>
public ControlOutput Body => m_Body;

/// <summary>exit ポートへの参照を公開します。</summary>
public ControlOutput Exit => m_Exit;

/// <summary>condition ポートへの参照を公開します。</summary>
public ValueInput Condition => m_Condition;

/// <summary>
/// ポート定義を行い、条件成立までコルーチンで body を繰り返す設定を行います。
/// </summary>
protected override void Definition()
{
m_Exit = ControlOutput("exit");
m_Body = ControlOutput("body");
m_Condition = ValueInput("condition", false);
m_Enter = CreateScratchCoroutineInput("enter", RunCoroutine);

Succession(m_Enter, m_Body);
Succession(m_Body, m_Body);
Succession(m_Enter, m_Exit);
Requirement(m_Condition, m_Enter);
}

/// <summary>
/// 条件が真になるまで body を実行し、毎反復の終わりに 1 フレーム待機します。
/// 条件成立後は exit ポートへ制御を返します。
/// </summary>
/// <param name="flow">現在のフロー情報。</param>
/// <returns>ループ処理を行う列挙子。</returns>
private IEnumerator RunCoroutine(Flow flow)
{
while (!flow.GetValue<bool>(m_Condition))
{
yield return m_Body;
yield return null;
}

yield return m_Exit;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -70,4 +70,64 @@ private IEnumerator RunCoroutine(Flow flow)
yield return m_Exit;
}
}

/// <summary>
/// Scratch の「〇まで待つ」ブロックを再現し、条件が成立するまで毎フレーム待機するユニットです。
/// </summary>
[UnitTitle("○まで待つ")]
[UnitShortTitle("○まで待つ")]
[UnitCategory("FUnity/Blocks/制御")]
[UnitSubtitle("制御")]
[TypeIcon(typeof(FUnityScratchUnitIcon))]
public sealed class WaitUntilUnit : ScratchCoroutineUnitBase
{
/// <summary>待機を開始する ControlInput です。</summary>
[DoNotSerialize]
private ControlInput m_Enter;

/// <summary>条件成立後に後続へ進む ControlOutput です。</summary>
[DoNotSerialize]
private ControlOutput m_Exit;

/// <summary>待機判定に使用する条件値を受け取る ValueInput です。</summary>
[DoNotSerialize]
private ValueInput m_Condition;

/// <summary>enter ポートへの参照を公開します。</summary>
public ControlInput Enter => m_Enter;

/// <summary>exit ポートへの参照を公開します。</summary>
public ControlOutput Exit => m_Exit;

/// <summary>condition ポートへの参照を公開します。</summary>
public ValueInput Condition => m_Condition;

/// <summary>
/// ポート定義を行い、条件成立までコルーチンで待機する入力を登録します。
/// </summary>
protected override void Definition()
{
m_Exit = ControlOutput("exit");
m_Condition = ValueInput("condition", false);
m_Enter = CreateScratchCoroutineInput("enter", RunCoroutine);

Succession(m_Enter, m_Exit);
Requirement(m_Condition, m_Enter);
}

/// <summary>
/// 条件が true になるまで 1 フレームずつ待機し、成立後に exit へ遷移します。
/// </summary>
/// <param name="flow">現在のフロー情報。</param>
/// <returns>待機処理を行う列挙子。</returns>
private IEnumerator RunCoroutine(Flow flow)
{
while (!flow.GetValue<bool>(m_Condition))
{
yield return null;
}

yield return m_Exit;
}
}
}