Skip to content

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 conditionResult
Player emits an event from widgetId on screenNameReturns the InputEvent.
Timeout firesThrows TimeoutException.
Player disconnectsThrows OperationCanceledException.
You cancel via the CancellationTokenThrows OperationCanceledException.
Another PromptAsync starts for the same playerThe 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 via UpdateScreenData, the host re-pushes the screen with the original data, not the latest. Push fresh data manually if needed.
  • Two PromptAsync calls for the same player overlap. The second call cancels the first. Don’t use this for parallel asks; use Task.WhenAll(promptA, promptB) only when each prompt targets a different player.
  • Catch OperationCanceledException even if you never cancel manually. Player disconnects raise it.

Next