8. Handle network errors and repeated clicks
Try clicking the purchase button repeatedly and disconnecting the network. Continue with the same player you have been using.
Click again while a purchase is processing
- Prepare at least 20 coins. Clear quests to earn more if needed.
- Click Restore 10 stamina for 20 coins, then immediately click again.
- Check that the button is disabled during processing and cannot start another purchase.
The code sets busy to true when an operation starts and resets it to false in finally. In addition to disabling buttons, Studio’s Run() and the SDK’s RunWrite() reject calls while busy.
Clicking after the purchase completes and the button is enabled starts a new purchase.
Check the insufficient-coins message
- Buy repeatedly until your balance is below 20 coins.
- Click the purchase button again and check for the insufficient-coins message.
- Check that the failed purchase neither spends coins nor restores stamina, excluding any natural recovery.
- Start Forest exploration to check that quest controls still work, then clear it.
For insufficient coins or stamina, show the reason and allow the next operation.
Allow retries of the same purchase
When a connection drops, the server may have completed the purchase but its response may not have arrived. Sending a new purchase would spend coins again.
Assign one key to each purchase. Resend the same content with the same duplicationAvoider key, and GS2 returns the completed purchase’s result without repeating it.
Stop Play Mode and replace the matching file for your course. Keep the Inspector references.
Download AdventureStudioView.cs.
The purchase method Buy() now looks like this. purchaseId is a class field.
private string purchaseId;
private async Task Buy()
{
purchaseId ??= Guid.NewGuid().ToString();
var request = Gs2ClientHolder.Instance.Gs2.Exchange.Namespace("EnergyProduct")
.Me(Gs2GameSessionHolder.Instance.GameSession).Exchange();
var transaction = await request.ExchangeAsync(
"refill", 1, speculativeExecute: false, duplicationAvoider: purchaseId);
if (transaction != null) await transaction.WaitAsync(all: true);
purchaseId = null;
}Download AdventurePlay.cs. Keep AdventurePlayer.cs and AdventureLogin.cs as they are.
The purchase method BuyRefill() now looks like this. purchaseId is a class field.
private string purchaseId;
private async UniTask BuyRefill()
{
purchaseId ??= Guid.NewGuid().ToString();
var transaction = await player.Gs2.Exchange.Namespace("adventure-shop").Me(player.Session)
.Exchange().ExchangeAsync(
"refill", 1, speculativeExecute: false, duplicationAvoider: purchaseId);
awaitingResult = true;
if (transaction != null) await transaction.WaitAsync(all: true);
purchaseId = null;
}??= assigns a value only when none exists. A network error leaves purchaseId intact, so a retry uses the same key. Completion clears it so the next purchase gets a new key. The error handler also clears it when the purchase is rejected for insufficient coins.
After a network error, the button changes to Retry the same purchase. Until the result arrives, you can retry this purchase, but cannot start another quest or a new purchase.
Try disconnecting the network
- Enter Play Mode and log in. Prepare at least 20 coins and at most 10 stamina, then note both values.
- Disconnect your computer from the network and click the purchase button.
- Wait for a network error and the Retry the same purchase button.
- Reconnect the network and, without stopping Play Mode, click Retry the same purchase.
- Check that 20 coins are spent and 10 stamina restored, excluding natural recovery. The button returns to its normal label when the purchase completes.
Next, click purchase while connected and disconnect immediately afterward. If the response arrived first and completed the purchase, the normal purchase button returns. Reconnect and resend only if the retry button appears.
This sample keeps the key in memory during Play Mode, so do not stop Play Mode during the test. GS2 retains duplicate-avoidance results for one hour; retry as soon as you reconnect in this exercise.
Practice: write helpful status messages
Try messages that explain the current state, such as Processing, Not enough coins, or Check your connection. Edit the text in Studio’s Run(), or the SDK’s RunWrite() and WriteError().