The problem I needed to solve
Match entry cost needs resolving before a scene begins. Loading first and checking coins later could create a state that should never have been entered.
Implementation in this snapshot
MatchEntryService.TryEnterMatch finds the game in MetaCatalog and calls TrySpendCoins with the MatchEntry reason. Its result includes status, game ID, scene name and cost.
The design decision and its cost
Success, NotEnoughCoins and InvalidGame are distinct paths. Finish emits the request outcome and before/after balance telemetry; the consumer decides whether to change scenes.
Current boundaries
The service does not call SceneManager or roll back a failed scene load. Successful payment and successful scene entry are separate stages and should not be conflated in reporting.
Review scenarios and contract meaning
The main scenario has two different failures: a game exists in the catalog but the player lacks coins, or the identifier does not refer to a valid game at all. The first needs a balance message; the second calls for checking the definition or menu wiring. One generic failure would hide that difference from both interface and reporting. Keeping the identifier, scene name and cost in the result lets the consumer know exactly which destination the service has authorized. Success means the fee was accepted, not that the engine necessarily loaded the scene.
This separation creates a real gap between payment and arrival. If destination loading stops, the current service does not refund automatically. The experience consequently needs an explicit message and policy for that situation; this source does not establish such a policy. In telemetry review, I also keep successful entry requests separate from started matches. A later event can clarify whether the player arrived or only paid. That distinction helps diagnose scene wiring more than applying a generic start label to every stage.
Rapid repeated taps raise another entry question. This service alone does not establish an interface lock against sequential requests; the consumer needs a clear disable and re-enable policy. I treat requesting entry, paying coins and reaching the runner as distinct signals so a flow failure is not misread as a rules problem.
What this stage taught me
For me, this entry contract turned a tap into an explainable decision. A valid game, sufficient coins and an explicit destination should exist before starting; insufficient-coin feedback follows that decision.




