PromptAsync
PromptAsync is the cleanest way to write “wait for this player to answer” without juggling event handlers.
It moves one player to a named screen, awaits the next event from a specific widget on that screen, and (by default) restores whatever screen they were on before. The whole thing reads top-to-bottom in your game code.
Signature
Task<InputEvent> PromptAsync( string playerId, string screenName, string widgetId, TimeSpan timeout, object? data = null, bool restorePriorScreen = true, CancellationToken ct = default);
Task<T> PromptAsync<T>( string playerId, string screenName, string widgetId, TimeSpan timeout, object? data = null, bool restorePriorScreen = true, CancellationToken ct = default);Requires a FlowAsset registered on PhoneControllerManager. If you want this without a flow, use RequestAsync.
Example — drawer picks a word
var evt = await manager.PromptAsync( playerId: drawer.Id, screenName: "pick_word", widgetId: "choices", timeout: TimeSpan.FromSeconds(15));
var word = evt.GetString("choice_id");
// drawer is now back on whatever screen they were on before "pick_word"manager.ShowScreenToAll("draw", new { word });Lifecycle and cancellation
Three things end the await:
| End condition | Result |
|---|---|
Player emits an event from widgetId on screenName | Returns the InputEvent. |
| Timeout fires | Throws TimeoutException. |
| Player disconnects | Throws OperationCanceledException. |
You cancel via the CancellationToken | Throws OperationCanceledException. |
Another PromptAsync starts for the same player | The first prompt’s task is cancelled with OperationCanceledException. |
manager.DisconnectAsync() | Cancels every pending prompt. |
Wrap the await in try/catch — at minimum for TimeoutException and OperationCanceledException.
Typed payloads
PromptAsync<T> deserializes the event payload into T directly. Useful when the widget emits a structured payload:
record PickResult(string ChoiceId);
var pick = await manager.PromptAsync<PickResult>( drawer.Id, "pick_word", "choices", TimeSpan.FromSeconds(15));
Debug.Log(pick.ChoiceId);Pitfalls
restorePriorScreen: true(default) only restores the player’s screen — not their screen data. If the prior screen had data set viaUpdateScreenData, the host re-pushes the screen with the original data, not the latest. Push fresh data manually if needed.- Two
PromptAsynccalls for the same player overlap. The second call cancels the first. Don’t use this for parallel asks; useTask.WhenAll(promptA, promptB)only when each prompt targets a different player. - Catch
OperationCanceledExceptioneven if you never cancel manually. Player disconnects raise it.
Next
- Same shape, no flow required:
RequestAsync. - Lossy-stream replay (drawing canvas gap-fill):
RequestResendAsync.