async メソッドの中に書ける構文
async / awaitの本体には、ループ・分岐・ほかのメソッドの呼び出し・イベントの送信を、await と組み合わせて書けます。ローカル変数の値は中断をまたいで保たれます。
対応(12)
Section titled “対応(12)”| 書き方 | 説明 | 注意 |
|---|---|---|
while (running) { ...; await Async.Frames(60); } | while ループ | |
foreach (GameObject lamp in lamps) | foreach ループ | この例では、lamps の要素が 5 フレームおきに 1 つずつ有効になります。 |
for (y ...) { for (x ...) { ... } await Async.Frame(); } | 入れ子のループ | |
if (items[i] < 0) continue; | break と continue | continue で飛ばした周は await に到達しないので、フレームを消費しません。 |
if (slow) { await Async.Frames(120); } else { await Async.Frame(); } | if による分岐 | 分岐の後の文は、どちらを通った場合も待ちが終わってから実行されます。 |
case 0: await Async.Frame(); done = 1; break; | switch による分岐 | await を含まない default は中断せず、同じフレームのうちに終わります。 |
if (skip) return; | 途中の return | |
int[] work = new int[8]; await Async.Frame(); | ローカルの配列 | |
level = Step(level); | メソッドの呼び出し | 呼び出し先は中断せず、呼んだ位置で終わりまで実行されます。 |
SendCustomEvent(nameof(Bump)); | イベントの送信 | |
SendCustomNetworkEvent(NetworkEventTarget.All, nameof(Chime)); | ネットワークイベント | 待ちを数えるのは送信側だけで、受信側はさらに通信の遅延の後に実行されます。 |
phase = 1; RequestSerialization(); | 同期フィールドの更新 | RequestSerialization() で値が送信されるのはオーナーだけです(同期)。 |
while ループ
Section titled “while ループ”while ループの中に await を書けます。
using UnityEngine;using Tsukimi;
public class ParFlowWhile : TsukimiBehaviour{ public bool running; public int ticks;
private async FrameTask Pulse() { while (running) { ticks = ticks + 1; await Async.Frames(60); } }
void Start() { running = true; Pulse(); }}foreach ループ
Section titled “foreach ループ”配列への foreach の中に await を書けます。
using UnityEngine;using Tsukimi;
public class ParFlowForeach : TsukimiBehaviour{ public GameObject[] lamps;
private async FrameTask LightUp() { foreach (GameObject lamp in lamps) { lamp.SetActive(true); await Async.Frames(5); } }
public override void Interact() { LightUp(); }}入れ子のループ
Section titled “入れ子のループ”入れ子のループでは、内側のループ全体を 1 フレームで進め、外側の 1 周ごとに中断できます。
using UnityEngine;using Tsukimi;
public class ParFlowNested : TsukimiBehaviour{ public int[,] grid; public int sum;
private async FrameTask Total() { for (int y = 0; y < grid.GetLength(0); y++) { for (int x = 0; x < grid.GetLength(1); x++) { sum += grid[y, x]; } await Async.Frame(); } }
public override void Interact() { Total(); }}break と continue
Section titled “break と continue”await を含むループでも break と continue を使えます。
using UnityEngine;using Tsukimi;
public class ParFlowBreakContinue : TsukimiBehaviour{ public int[] items; public int sum;
private async FrameTask Scan() { for (int i = 0; i < items.Length; i++) { if (items[i] < 0) continue; if (items[i] > 100) break; sum += items[i]; await Async.Frame(); } }
public override void Interact() { Scan(); }}if による分岐
Section titled “if による分岐”if と else のそれぞれに、待つフレーム数の違う await を書けます。
using UnityEngine;using Tsukimi;
public class ParFlowBranch : TsukimiBehaviour{ public bool slow; public int done;
private async FrameTask Run() { if (slow) { await Async.Frames(120); } else { await Async.Frame(); } done = done + 1; }
public override void Interact() { Run(); }}switch による分岐
Section titled “switch による分岐”switch の case の中に await を書けます。
using UnityEngine;using Tsukimi;
public class ParFlowSwitch : TsukimiBehaviour{ public int mode; public int done;
private async FrameTask Run() { switch (mode) { case 0: await Async.Frame(); done = 1; break; case 1: await Async.Frames(30); done = 2; break; default: done = 3; break; } }
public override void Interact() { Run(); }}途中の return
Section titled “途中の return”await の手前で return すると、中断せずにそのフレームで終わります。
using UnityEngine;using Tsukimi;
public class ParFlowEarlyReturn : TsukimiBehaviour{ public bool skip; public int done;
private async FrameTask Run() { if (skip) return; await Async.Frames(10); done = done + 1; }
public override void Interact() { Run(); }}値の持ち越し
Section titled “値の持ち越し”ローカルの配列
Section titled “ローカルの配列”ローカルに new で作った配列は、中断をまたいで中身を保ちます。
using UnityEngine;using Tsukimi;
public class ParFlowArrayAcross : TsukimiBehaviour{ public int total;
private async FrameTask Fold() { int[] work = new int[8]; for (int i = 0; i < work.Length; i++) { work[i] = i * i; } await Async.Frame(); for (int i = 0; i < work.Length; i++) { total += work[i]; } }
public override void Interact() { Fold(); }}メソッドの呼び出し
Section titled “メソッドの呼び出し”[MaxTasks] の付いていないメソッドを、中断の前と後のどちらからでも呼べます。
using UnityEngine;using Tsukimi;
public class ParFlowCallMethod : TsukimiBehaviour{ public int level;
private int Step(int v) { return v + 1; }
private async FrameTask Climb() { level = Step(level); await Async.Frame(); level = Step(level); }
public override void Interact() { Climb(); }}イベントの送信
Section titled “イベントの送信”SendCustomEvent を、中断の前と後の両方で呼べます。
using UnityEngine;using Tsukimi;
public class ParFlowSendEvent : TsukimiBehaviour{ public int hits;
public void Bump() { hits = hits + 1; }
private async FrameTask Knock() { SendCustomEvent(nameof(Bump)); await Async.Frames(30); SendCustomEvent(nameof(Bump)); }
public override void Interact() { Knock(); }}ネットワークイベント
Section titled “ネットワークイベント”await の後に SendCustomNetworkEvent を送れます。
using UnityEngine;using VRC.Udon.Common.Interfaces;using Tsukimi;
public class ParFlowNetworkEvent : TsukimiBehaviour{ public int chimes;
public void Chime() { chimes = chimes + 1; }
private async FrameTask Delay() { await Async.Frames(90); SendCustomNetworkEvent(NetworkEventTarget.All, nameof(Chime)); }
public override void Interact() { Delay(); }}同期フィールドの更新
Section titled “同期フィールドの更新”[UdonSynced] のフィールドへの代入と RequestSerialization() を、中断をはさんで繰り返せます。
using UnityEngine;using Tsukimi;
public class ParFlowSynced : TsukimiBehaviour{ [UdonSynced] public int phase;
private async FrameTask Advance() { phase = 1; RequestSerialization(); await Async.Frames(60); phase = 2; RequestSerialization(); }
public override void Interact() { Advance(); }}