コンテンツにスキップ

async メソッドの中に書ける構文

async / awaitの本体には、ループ・分岐・ほかのメソッドの呼び出し・イベントの送信を、await と組み合わせて書けます。ローカル変数の値は中断をまたいで保たれます。

書き方説明注意
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 と continuecontinue で飛ばした周は 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 ループの中に 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 の中に 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();
}
}

入れ子のループでは、内側のループ全体を 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();
}
}

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 と 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 の 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();
}
}

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();
}
}

ローカルに 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();
}
}

[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();
}
}

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();
}
}

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();
}
}

[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();
}
}