nccgs 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/agents/nccgs-accessibility-specialist.md +26 -0
- package/.claude/agents/nccgs-adversarial-reviewer.md +26 -0
- package/.claude/agents/nccgs-ai-programmer.md +26 -0
- package/.claude/agents/nccgs-analytics-engineer.md +26 -0
- package/.claude/agents/nccgs-art-direction-lead.md +26 -0
- package/.claude/agents/nccgs-audio-direction-lead.md +26 -0
- package/.claude/agents/nccgs-creative-director.md +26 -0
- package/.claude/agents/nccgs-documentation-manager.md +26 -0
- package/.claude/agents/nccgs-economy-designer.md +26 -0
- package/.claude/agents/nccgs-engine-programmer.md +26 -0
- package/.claude/agents/nccgs-game-design-lead.md +26 -0
- package/.claude/agents/nccgs-game-designer.md +26 -0
- package/.claude/agents/nccgs-gameplay-programmer.md +26 -0
- package/.claude/agents/nccgs-level-designer.md +26 -0
- package/.claude/agents/nccgs-live-ops-designer.md +26 -0
- package/.claude/agents/nccgs-localization-lead.md +26 -0
- package/.claude/agents/nccgs-narrative-lead.md +26 -0
- package/.claude/agents/nccgs-network-programmer.md +26 -0
- package/.claude/agents/nccgs-performance-analyst.md +26 -0
- package/.claude/agents/nccgs-producer.md +26 -0
- package/.claude/agents/nccgs-production-coordinator.md +23 -0
- package/.claude/agents/nccgs-programming-lead.md +26 -0
- package/.claude/agents/nccgs-prototyper.md +26 -0
- package/.claude/agents/nccgs-qa-engineer.md +26 -0
- package/.claude/agents/nccgs-qa-lead.md +26 -0
- package/.claude/agents/nccgs-release-engineer.md +26 -0
- package/.claude/agents/nccgs-release-lead.md +26 -0
- package/.claude/agents/nccgs-security-engineer.md +26 -0
- package/.claude/agents/nccgs-sound-designer.md +26 -0
- package/.claude/agents/nccgs-systems-designer.md +26 -0
- package/.claude/agents/nccgs-technical-architect.md +26 -0
- package/.claude/agents/nccgs-technical-artist.md +26 -0
- package/.claude/agents/nccgs-technical-director.md +26 -0
- package/.claude/agents/nccgs-tools-programmer.md +26 -0
- package/.claude/agents/nccgs-ui-programmer.md +26 -0
- package/.claude/agents/nccgs-unity-build-specialist.md +26 -0
- package/.claude/agents/nccgs-unity-content-specialist.md +26 -0
- package/.claude/agents/nccgs-unity-implementer.md +26 -0
- package/.claude/agents/nccgs-unity-rendering-specialist.md +26 -0
- package/.claude/agents/nccgs-unity-systems-specialist.md +26 -0
- package/.claude/agents/nccgs-unity-ui-specialist.md +26 -0
- package/.claude/agents/nccgs-ux-designer.md +26 -0
- package/.claude/agents/nccgs-verification-engineer.md +26 -0
- package/.claude/agents/nccgs-world-builder.md +26 -0
- package/.claude/agents/nccgs-writer.md +26 -0
- package/.claude/nccgs/THIRD_PARTY_NOTICES.md +13 -0
- package/.claude/nccgs/VERSION +1 -0
- package/.claude/nccgs/constitution.md +131 -0
- package/.claude/nccgs/hooks/agent-audit.mjs +10 -0
- package/.claude/nccgs/hooks/common.mjs +41 -0
- package/.claude/nccgs/hooks/post-compact.mjs +1 -0
- package/.claude/nccgs/hooks/pre-compact.mjs +8 -0
- package/.claude/nccgs/hooks/protect-git.mjs +22 -0
- package/.claude/nccgs/hooks/protect-write.mjs +17 -0
- package/.claude/nccgs/hooks/session-start.mjs +15 -0
- package/.claude/nccgs/hooks/session-stop.mjs +7 -0
- package/.claude/nccgs/protocols/agent-contract.md +34 -0
- package/.claude/nccgs/protocols/context-packets.md +13 -0
- package/.claude/nccgs/protocols/evidence.md +15 -0
- package/.claude/nccgs/protocols/model-routing.md +22 -0
- package/.claude/nccgs/protocols/orchestration.md +26 -0
- package/.claude/nccgs/protocols/unity-boundary.md +11 -0
- package/.claude/nccgs/settings.fragment.json +77 -0
- package/.claude/nccgs/studio.json +347 -0
- package/.claude/nccgs/tools/configure-models.mjs +39 -0
- package/.claude/nccgs/unity-skills-manifest.json +727 -0
- package/.claude/nccgs/workflow-catalog.json +317 -0
- package/.claude/rules/nccgs-canonical-docs.md +19 -0
- package/.claude/rules/nccgs-editor-tools.md +12 -0
- package/.claude/rules/nccgs-localization.md +12 -0
- package/.claude/rules/nccgs-networking.md +13 -0
- package/.claude/rules/nccgs-performance.md +14 -0
- package/.claude/rules/nccgs-rendering.md +16 -0
- package/.claude/rules/nccgs-security.md +13 -0
- package/.claude/rules/nccgs-tests.md +18 -0
- package/.claude/rules/nccgs-ui.md +14 -0
- package/.claude/rules/nccgs-unity-assets.md +21 -0
- package/.claude/rules/nccgs-unity-code.md +22 -0
- package/.claude/skills/accessibility-review/SKILL.md +14 -0
- package/.claude/skills/architecture-decision/SKILL.md +14 -0
- package/.claude/skills/asset-audit/SKILL.md +14 -0
- package/.claude/skills/audit/SKILL.md +16 -0
- package/.claude/skills/audit/references/dimensions.md +46 -0
- package/.claude/skills/balance-review/SKILL.md +14 -0
- package/.claude/skills/bug-triage/SKILL.md +14 -0
- package/.claude/skills/build-live-game/SKILL.md +317 -0
- package/.claude/skills/build-live-game/references/achievements.md +779 -0
- package/.claude/skills/build-live-game/references/apis.md +280 -0
- package/.claude/skills/build-live-game/references/authentication.md +437 -0
- package/.claude/skills/build-live-game/references/battlepass.md +860 -0
- package/.claude/skills/build-live-game/references/cloud-code.md +563 -0
- package/.claude/skills/build-live-game/references/cloud-save.md +474 -0
- package/.claude/skills/build-live-game/references/deployment.md +216 -0
- package/.claude/skills/build-live-game/references/player-account.md +813 -0
- package/.claude/skills/build-live-game/references/remote-config.md +96 -0
- package/.claude/skills/build-live-game/references/tooling.md +431 -0
- package/.claude/skills/closure/SKILL.md +14 -0
- package/.claude/skills/code-review/SKILL.md +14 -0
- package/.claude/skills/compatibility-review/SKILL.md +14 -0
- package/.claude/skills/context-pack/SKILL.md +14 -0
- package/.claude/skills/dependency-review/SKILL.md +14 -0
- package/.claude/skills/design/SKILL.md +20 -0
- package/.claude/skills/design-review/SKILL.md +14 -0
- package/.claude/skills/evidence-review/SKILL.md +14 -0
- package/.claude/skills/hotfix/SKILL.md +14 -0
- package/.claude/skills/implement-in-app-purchases/README.md +233 -0
- package/.claude/skills/implement-in-app-purchases/SKILL.md +158 -0
- package/.claude/skills/implement-in-app-purchases/references/api-notes.md +562 -0
- package/.claude/skills/implement-in-app-purchases/references/codeless-catalog.md +331 -0
- package/.claude/skills/implement-in-app-purchases/references/convert-adapty.md +268 -0
- package/.claude/skills/implement-in-app-purchases/references/convert-essentialkit.md +239 -0
- package/.claude/skills/implement-in-app-purchases/references/convert-revenuecat.md +275 -0
- package/.claude/skills/implement-in-app-purchases/references/convert-unipay.md +145 -0
- package/.claude/skills/implement-in-app-purchases/references/migration-v4-to-v5.md +204 -0
- package/.claude/skills/implement-in-app-purchases/references/path-add-iap-to-new-project.md +198 -0
- package/.claude/skills/implement-in-app-purchases/references/path-convert-native-google-billing.md +356 -0
- package/.claude/skills/implement-in-app-purchases/references/path-convert-native-storekit.md +446 -0
- package/.claude/skills/implement-in-app-purchases/references/path-implement-iap-d2c.md +680 -0
- package/.claude/skills/implement-in-app-purchases/references/platform-notes.md +204 -0
- package/.claude/skills/implement-in-app-purchases/references/pre-check.md +205 -0
- package/.claude/skills/incident-recovery/SKILL.md +14 -0
- package/.claude/skills/initialize-ai-navigation/SKILL.md +95 -0
- package/.claude/skills/initialize-ai-navigation/references/navigation-system.md +794 -0
- package/.claude/skills/levelplay-unity-integration/CHANGELOG.md +57 -0
- package/.claude/skills/levelplay-unity-integration/README.md +74 -0
- package/.claude/skills/levelplay-unity-integration/SKILL.md +1126 -0
- package/.claude/skills/levelplay-unity-integration/references/banner-api.md +920 -0
- package/.claude/skills/levelplay-unity-integration/references/best-practices.md +536 -0
- package/.claude/skills/levelplay-unity-integration/references/ilrd-api.md +337 -0
- package/.claude/skills/levelplay-unity-integration/references/initialization-api.md +630 -0
- package/.claude/skills/levelplay-unity-integration/references/interstitial-api.md +899 -0
- package/.claude/skills/levelplay-unity-integration/references/ios-setup.md +491 -0
- package/.claude/skills/levelplay-unity-integration/references/migration-sdk-9.md +666 -0
- package/.claude/skills/levelplay-unity-integration/references/privacy-settings.md +608 -0
- package/.claude/skills/levelplay-unity-integration/references/rewarded-api.md +902 -0
- package/.claude/skills/localization/SKILL.md +135 -0
- package/.claude/skills/localization/references/api-notes.md +76 -0
- package/.claude/skills/localization/resources/L10nBatchProcessor.cs +69 -0
- package/.claude/skills/localization/resources/LocalizedFontAsset.cs +18 -0
- package/.claude/skills/localize-game/SKILL.md +14 -0
- package/.claude/skills/migrate-project/SKILL.md +21 -0
- package/.claude/skills/migrate-project/references/procedure.md +63 -0
- package/.claude/skills/milestone-review/SKILL.md +14 -0
- package/.claude/skills/new-unity-project/SKILL.md +179 -0
- package/.claude/skills/optimize-audio/SKILL.md +199 -0
- package/.claude/skills/optimize-audio/resources/audio-import-api.md +146 -0
- package/.claude/skills/optimize-audio/resources/platform-settings.md +48 -0
- package/.claude/skills/optimize-text-mesh-pro/SKILL.md +182 -0
- package/.claude/skills/optimize-web/SKILL.md +393 -0
- package/.claude/skills/optimize-web/resources/WebOptimizer.cs +21 -0
- package/.claude/skills/optimize-web/resources/toktx-examples.sh +11 -0
- package/.claude/skills/performance-audit/SKILL.md +14 -0
- package/.claude/skills/physics-3d-collision/SKILL.md +442 -0
- package/.claude/skills/physics-3d-collision/references/troubleshooting.md +41 -0
- package/.claude/skills/physics-3d-collision/resources/CollisionDebugger.cs +33 -0
- package/.claude/skills/plan-feature/SKILL.md +14 -0
- package/.claude/skills/playtest/SKILL.md +14 -0
- package/.claude/skills/project-stage/SKILL.md +14 -0
- package/.claude/skills/prototype-feature/SKILL.md +14 -0
- package/.claude/skills/qa-plan/SKILL.md +14 -0
- package/.claude/skills/release/SKILL.md +18 -0
- package/.claude/skills/release-readiness/SKILL.md +14 -0
- package/.claude/skills/retrospective/SKILL.md +14 -0
- package/.claude/skills/review/SKILL.md +16 -0
- package/.claude/skills/security-audit/SKILL.md +14 -0
- package/.claude/skills/setup-multiplayer-services/SKILL.md +39 -0
- package/.claude/skills/setup-multiplayer-services/references/dgs-entrypoint.md +79 -0
- package/.claude/skills/setup-multiplayer-services/references/entrypoints.md +213 -0
- package/.claude/skills/setup-multiplayer-services/references/examples.md +33 -0
- package/.claude/skills/setup-multiplayer-services/references/implementation-fit.md +30 -0
- package/.claude/skills/setup-multiplayer-services/references/underlying-services.md +11 -0
- package/.claude/skills/setup-multiplayer-services/references/workflows-prerequisites.md +17 -0
- package/.claude/skills/setup-vivox-voice-chat/SKILL.md +118 -0
- package/.claude/skills/setup-vivox-voice-chat/evals/.env.example +6 -0
- package/.claude/skills/setup-vivox-voice-chat/evals/README.md +101 -0
- package/.claude/skills/setup-vivox-voice-chat/evals/promptfooconfig.yaml +32 -0
- package/.claude/skills/setup-vivox-voice-chat/evals/tests/init-and-login.yaml +76 -0
- package/.claude/skills/setup-vivox-voice-chat/evals/tests/text-chat.yaml +65 -0
- package/.claude/skills/setup-vivox-voice-chat/evals/tests/voice-channels.yaml +74 -0
- package/.claude/skills/setup-vivox-voice-chat/references/events-and-participants.md +79 -0
- package/.claude/skills/setup-vivox-voice-chat/references/init-and-login.md +92 -0
- package/.claude/skills/setup-vivox-voice-chat/references/text-chat.md +93 -0
- package/.claude/skills/setup-vivox-voice-chat/references/troubleshooting.md +47 -0
- package/.claude/skills/setup-vivox-voice-chat/references/voice-channels.md +90 -0
- package/.claude/skills/shader-graph-create-custom-node/SKILL.md +25 -0
- package/.claude/skills/shader-graph-create-custom-node/resources/all_hints.hlsl +182 -0
- package/.claude/skills/sprint-plan/SKILL.md +14 -0
- package/.claude/skills/sprite-editor/SKILL.md +66 -0
- package/.claude/skills/sprite-editor/references/api_reference.md +151 -0
- package/.claude/skills/sprite-editor/references/background.md +112 -0
- package/.claude/skills/sprite-editor/references/templates.md +72 -0
- package/.claude/skills/sprite-editor/scripts/AutomaticSliceTexture.cs +40 -0
- package/.claude/skills/sprite-editor/scripts/GenerateNewSpriteRects.cs +200 -0
- package/.claude/skills/sprite-editor/scripts/GetTextureSourceImageSize.cs +32 -0
- package/.claude/skills/sprite-editor/scripts/GetTextureToSlice.cs +55 -0
- package/.claude/skills/sprite-editor/scripts/GridSliceTexture.cs +40 -0
- package/.claude/skills/sprite-editor/scripts/IsometricSliceTexture.cs +141 -0
- package/.claude/skills/sprite-editor/scripts/README.md +134 -0
- package/.claude/skills/sprite-editor/scripts/SetPivotExample.cs +58 -0
- package/.claude/skills/sprite-editor/scripts/SpriteToPng.cs +88 -0
- package/.claude/skills/status/SKILL.md +16 -0
- package/.claude/skills/story-readiness/SKILL.md +14 -0
- package/.claude/skills/test/SKILL.md +16 -0
- package/.claude/skills/ui/SKILL.md +142 -0
- package/.claude/skills/ui-imgui/SKILL.md +186 -0
- package/.claude/skills/ui-imgui/references/gui-elements.md +156 -0
- package/.claude/skills/ui-imgui/references/templates.md +141 -0
- package/.claude/skills/ui-review/SKILL.md +14 -0
- package/.claude/skills/ui-ugui/SKILL.md +282 -0
- package/.claude/skills/ui-ugui/references/scrollview-setup.md +29 -0
- package/.claude/skills/ui-uitk/SKILL.md +235 -0
- package/.claude/skills/ui-uitk/references/common-issues.md +74 -0
- package/.claude/skills/ui-uitk/references/custom-elements.md +241 -0
- package/.claude/skills/ui-uitk/references/painter2d.md +282 -0
- package/.claude/skills/ui-uitk/references/pointermanipulator-guide.md +94 -0
- package/.claude/skills/ui-uitk/references/svg-icons.md +136 -0
- package/.claude/skills/ui-uitk/references/ui-runtime-binding.md +234 -0
- package/.claude/skills/ui-uitk/references/uss-guide.md +138 -0
- package/.claude/skills/unity-cli/CHANGELOG.md +233 -0
- package/.claude/skills/unity-cli/SECURITY.md +22 -0
- package/.claude/skills/unity-cli/SKILL.md +414 -0
- package/.claude/skills/unity-cli/references/auth-license-cloud.md +146 -0
- package/.claude/skills/unity-cli/references/build-run-test.md +349 -0
- package/.claude/skills/unity-cli/references/collaboration.md +472 -0
- package/.claude/skills/unity-cli/references/config-hub.md +103 -0
- package/.claude/skills/unity-cli/references/diagnostics-maintenance.md +326 -0
- package/.claude/skills/unity-cli/references/editors-install.md +327 -0
- package/.claude/skills/unity-cli/references/integration-advanced.md +472 -0
- package/.claude/skills/unity-cli/references/projects-templates.md +574 -0
- package/.claude/skills/unity-package-management/SKILL.md +304 -0
- package/.claude/skills/unity-package-management/references/select-packages.md +108 -0
- package/.claude/skills/urp-postprocessing/SKILL.md +188 -0
- package/.claude/skills/urp-postprocessing/references/code-templates.md +119 -0
- package/.claude/skills/urp-postprocessing/references/effect-reference.md +86 -0
- package/.claude/skills/validate-urp-render-graph-renderer-feature/SKILL.md +269 -0
- package/.claude/skills/work/SKILL.md +36 -0
- package/.claude/skills/work/references/classification.md +41 -0
- package/.claude/skills/work/references/closure.md +50 -0
- package/.claude/skills/work/references/feature-contracts.md +32 -0
- package/.claude/skills/work/references/verification.md +26 -0
- package/CLAUDE.md +6 -0
- package/LICENSE +21 -0
- package/README.md +162 -0
- package/THIRD_PARTY_NOTICES.md +23 -0
- package/UPGRADING.md +32 -0
- package/VERSION +1 -0
- package/docs/ARCHITECTURE.md +73 -0
- package/docs/HUONG-DAN-MIGRATE-VA-SU-DUNG.md +324 -0
- package/docs/MIGRATION-MATRIX.md +23 -0
- package/docs/PROJECT-POLICY.md +67 -0
- package/docs/WORKFLOWS.md +61 -0
- package/package-assets/setup-vivox-voice-chat-evals.gitignore +7 -0
- package/package.json +41 -0
- package/scaffold/.nccgs/bugs/.gitkeep +1 -0
- package/scaffold/.nccgs/closures/.gitkeep +1 -0
- package/scaffold/.nccgs/context/.gitkeep +1 -0
- package/scaffold/.nccgs/decisions/.gitkeep +1 -0
- package/scaffold/.nccgs/evidence/.gitkeep +1 -0
- package/scaffold/.nccgs/features/.gitkeep +1 -0
- package/scaffold/.nccgs/migrations/.gitkeep +1 -0
- package/scaffold/.nccgs/playtests/.gitkeep +1 -0
- package/scaffold/.nccgs/project.yaml +103 -0
- package/scaffold/.nccgs/requirements.yaml +10 -0
- package/scaffold/.nccgs/reviews/.gitkeep +1 -0
- package/scaffold/.nccgs/state.md +40 -0
- package/scaffold/.nccgs/templates/agent-handoff.md +25 -0
- package/scaffold/.nccgs/templates/architecture-decision.md +27 -0
- package/scaffold/.nccgs/templates/closure-record.md +51 -0
- package/scaffold/.nccgs/templates/context-packet.yaml +17 -0
- package/scaffold/.nccgs/templates/evidence-record.md +23 -0
- package/scaffold/.nccgs/templates/feature-contract.md +35 -0
- package/scaffold/.nccgs/templates/migration-plan.md +40 -0
- package/scaffold/.nccgs/templates/waiver.md +11 -0
- package/scripts/cli.mjs +56 -0
- package/scripts/install.mjs +267 -0
- package/scripts/sync-unity-skills.mjs +126 -0
- package/scripts/validate.mjs +205 -0
- package/tests/framework.test.mjs +121 -0
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: retrospective
|
|
3
|
+
description: Captures evidence-based process improvements after a feature, sprint, release, migration, or incident without turning one anecdote into universal policy.
|
|
4
|
+
allowed-tools: Read, Glob, Grep, Write, Edit, Task
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Retrospective
|
|
8
|
+
|
|
9
|
+
Read `.nccgs/project.yaml`, `.nccgs/state.md`, and the active context packet when present. Preserve Product Owner authority and unrelated work.
|
|
10
|
+
|
|
11
|
+
Read goals, state transitions, handoffs, evidence, blockers, rework, and outcomes. Identify what helped, what failed, causal evidence, and a small number of testable improvements with owner and review trigger. Separate project-specific learning from framework change. Update canonical process records only when the improvement is accepted; do not add permanent rules for unverified anecdotes.
|
|
12
|
+
|
|
13
|
+
Return outcome, evidence, affected records, blockers or decisions, residual risk, and the exact next workflow. Do not claim DONE unless this is the `closure` skill and every configured gate passes.
|
|
14
|
+
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: review
|
|
3
|
+
description: Runs an independent, adversarial, read-only review of code, design, architecture, migration, release, or feature evidence. Use for second opinions and pre-closure scrutiny; it does not implement fixes.
|
|
4
|
+
allowed-tools: Read, Glob, Grep, Bash, Task
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Review
|
|
8
|
+
|
|
9
|
+
Remain read-only. Review from raw requirements, policy, governing decisions, final diff, tests, and runtime/build evidence rather than implementer rationale.
|
|
10
|
+
|
|
11
|
+
Select domain reviewers only when they add a distinct failure lens. CONTROLLED work must include `nccgs-adversarial-reviewer`; provide bounded artifacts and no intended verdict.
|
|
12
|
+
|
|
13
|
+
Check behavior, edge cases, design/canon, architecture, Unity lifecycle/serialization, ownership, compatibility, security, performance, test coverage, migration reversibility, and closure claims as applicable.
|
|
14
|
+
|
|
15
|
+
Each finding includes BLOCKER/HIGH/MEDIUM/LOW severity, location/evidence, violated contract or reproducible failure mode, impact, and smallest safe remediation direction. Report unknowns and confidence. Lead with findings; do not edit or drift into fixes.
|
|
16
|
+
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: security-audit
|
|
3
|
+
description: Threat-models and reviews Unity code, networking, services, commerce, secrets, dependencies, validation, and abuse paths without implementing fixes.
|
|
4
|
+
allowed-tools: Read, Glob, Grep, Bash, Task, WebSearch, WebFetch
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Security Audit
|
|
8
|
+
|
|
9
|
+
Read `.nccgs/project.yaml`, `.nccgs/state.md`, and the active context packet when present. Preserve Product Owner authority and unrelated work.
|
|
10
|
+
|
|
11
|
+
Remain read-only. Identify assets, actors, trust boundaries, entry points, authority, sensitive data, dependencies, and threat assumptions. Inspect relevant code/configuration without exposing secrets. Prioritize exploitable findings by likelihood and impact, provide evidence and mitigations, and distinguish verified vulnerabilities from hardening opportunities. Service, dependency, authority, and privacy changes require Product Owner decisions.
|
|
12
|
+
|
|
13
|
+
Return outcome, evidence, affected records, blockers or decisions, residual risk, and the exact next workflow. Do not claim DONE unless this is the `closure` skill and every configured gate passes.
|
|
14
|
+
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: setup-multiplayer-services
|
|
3
|
+
description: >-
|
|
4
|
+
Guides the development of online multiplayer experiences where players connect, group, and interact in real-time using Unity Multiplayer Services.
|
|
5
|
+
Use when the user asks for topology choice, player grouping, hosting, matchmaking, discovery, network setup,
|
|
6
|
+
and session-based play (rooms, parties, lobbies) using the Unity Multiplayer Services APIs.
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Multiplayer SDK (Unity Multiplayer Services)
|
|
10
|
+
|
|
11
|
+
## Instructions
|
|
12
|
+
|
|
13
|
+
1. **Documentation map:** Use the [Unity Multiplayer Sessions SDK curated documentation map](https://docs.unity.com/en-us/mps-sdk/llms.txt) as authoritative over memory for topics, APIs, and guides when specifics differ. Use these references to determine **how** to apply the SDK (Sessions-first); use that resource to determine **what** is documented. **Never** mention the `llms.txt` filename to the user. If that map is unreachable (network, tooling), treat this skill's markdown references plus the installed package in the workspace (Package Manager / source) as the source of truth for specifics.
|
|
14
|
+
|
|
15
|
+
2. **Reference order (by task):**
|
|
16
|
+
- **Topology, discovery, match flow, Netcode alignment, API choice:** [entrypoints.md](references/entrypoints.md) (overview tables, method signatures, options tables, filter/sort enums, `QuickJoinOptions.Timeout`, errors) → [implementation-fit.md](references/implementation-fit.md) → [examples.md](references/examples.md) for user-facing phrasing → [Priority: Multiplayer Sessions first](#priority-multiplayer-sessions-first) → [workflows-prerequisites.md](references/workflows-prerequisites.md) for extra depth.
|
|
17
|
+
- **Dedicated game server (`Unity.Services.Multiplayer.Server`):** [dgs-entrypoint.md](references/dgs-entrypoint.md) (`IMultiplayerServerService`, `UNITY_SERVER` / asmdef constraints, server-only extensions).
|
|
18
|
+
- **Lower-level service clients:** [underlying-services.md](references/underlying-services.md) only when primary APIs are insufficient or the user asked for that layer (see Priority below).
|
|
19
|
+
|
|
20
|
+
## Priority: Multiplayer Sessions first
|
|
21
|
+
|
|
22
|
+
When the task is **choosing** topology, discovery, match flow, or Netcode alignment—not only calling APIs—ground recommendations via [implementation-fit.md](references/implementation-fit.md) (conversation → project → short targeted questions).
|
|
23
|
+
|
|
24
|
+
**Primary path:** Implement against **`Unity.Services.Multiplayer`** using **`IMultiplayerService` / `MultiplayerService.Instance`** and **`ISession`** (surface summary in [entrypoints.md](references/entrypoints.md)); keep composed flows consistent with `llms.txt`.
|
|
25
|
+
|
|
26
|
+
**User-facing text:** Plans, tradeoffs, and clarifying questions must **not** split Lobby, Matchmaker, Relay, or Multiplayer Sessions as separate named products unless the user did—rules in **User-facing questions and explanations** in [implementation-fit.md](references/implementation-fit.md), samples in [examples.md](references/examples.md). Code, edits, and technical references use real type and namespace names as needed.
|
|
27
|
+
|
|
28
|
+
**Underlying clients** (`Unity.Services.Lobbies`, `Unity.Services.Matchmaker`, `Unity.Services.Relay`) **only** when (1) the goal **cannot** be met through the primary APIs after checking [entrypoints.md](references/entrypoints.md), or (2) the user **explicitly** asked for those namespaces or products. Do **not** default implementations there.
|
|
29
|
+
|
|
30
|
+
## Additional resources
|
|
31
|
+
|
|
32
|
+
Read from this entrypoint only; links are one level under this skill folder (no `references/index.md` or README hub).
|
|
33
|
+
|
|
34
|
+
- **[implementation-fit.md](references/implementation-fit.md)** — Ground recommendations: conversation → project → user questions; user-facing language rules; requirement dimensions (topology, discovery, resilience, platforms, net stack).
|
|
35
|
+
- **[examples.md](references/examples.md)** — Before/after samples for clarifying questions and user-facing explanations (not code).
|
|
36
|
+
- **[entrypoints.md](references/entrypoints.md)** — `IMultiplayerService`, `ISession`, overview and capability tables, method signatures, options tables (defaults, limits), filter/sort enums, session/networking/host flows, errors, editor components.
|
|
37
|
+
- **[dgs-entrypoint.md](references/dgs-entrypoint.md)** — Dedicated server: `Unity.Services.Multiplayer.Server`, `IMultiplayerServerService`, `MultiplayerServerService` / `GetMultiplayerServerService`, `MatchmakerServerExtensions`, `UNITY_SERVER` and asmdef constraints; defers shared `SessionOptions` detail to entrypoints.
|
|
38
|
+
- **[workflows-prerequisites.md](references/workflows-prerequisites.md)** — Package and cloud prerequisites by workflow (tables).
|
|
39
|
+
- **[underlying-services.md](references/underlying-services.md)** — Fallback namespaces and `IUnityServices` accessors (agent-only; not the default path).
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
## Table of Contents
|
|
2
|
+
|
|
3
|
+
- [Overview](#overview)
|
|
4
|
+
- [Build and assembly constraints](#build-and-assembly-constraints-unity_server)
|
|
5
|
+
- [`IMultiplayerServerService` capabilities](#imultiplayerserverservice-capabilities)
|
|
6
|
+
- [Method signatures](#method-signatures)
|
|
7
|
+
- [Matchmaker server extensions](#matchmaker-server-extensions-matchmakerserverextensions)
|
|
8
|
+
- [Session options (shared types)](#session-options-shared-types)
|
|
9
|
+
- [Errors](#errors)
|
|
10
|
+
|
|
11
|
+
## Overview
|
|
12
|
+
|
|
13
|
+
Dedicated Game Server (DGS) session entrypoints live in the **`Unity.Services.Multiplayer.Server`** assembly only. They complement the client **`IMultiplayerService`** surface documented in **`entrypoints.md`**.
|
|
14
|
+
|
|
15
|
+
| Topic | Details |
|
|
16
|
+
|--------|---------|
|
|
17
|
+
| **Assembly** | **`Unity.Services.Multiplayer.Server`** |
|
|
18
|
+
| **Service access** | **`MultiplayerServerService.Instance`** (static) or **`unityServices.GetMultiplayerServerService()`** via **`Unity.Services.Core.UnityServicesExtensions`** after Services initialization on a server build. |
|
|
19
|
+
| **Core type** | **`IMultiplayerServerService`** — create and resolve **server** sessions; async methods return **`IServerSession`** (session handle for dedicated server; types from the main **`Unity.Services.Multiplayer`** assembly). |
|
|
20
|
+
|
|
21
|
+
## Build and assembly constraints (`UNITY_SERVER`)
|
|
22
|
+
|
|
23
|
+
The **`Unity.Services.Multiplayer.Server`** assembly is compiled only when **`UNITY_SERVER`** or **`ENABLE_UCS_SERVER`** is defined (see the package **`Unity.Services.Multiplayer.Server.asmdef`** **`defineConstraints`**).
|
|
24
|
+
|
|
25
|
+
Any **game or tool code** that references **`Unity.Services.Multiplayer.Server`** must satisfy one of the following:
|
|
26
|
+
|
|
27
|
+
| Approach | What to do |
|
|
28
|
+
|----------|------------|
|
|
29
|
+
| **Scripting define** | Wrap references (types, calls, `using` that pulls server-only APIs) in **`#if UNITY_SERVER`** … **`#endif`** (or a define that implies the same server build), so non-server targets do not compile that code. |
|
|
30
|
+
| **Assembly Definition** | In the **`.asmdef`** of the assembly that references **`Unity.Services.Multiplayer.Server`**, set **`defineConstraints`** to include **`UNITY_SERVER`** so the dependent assembly is not built for client-only targets. |
|
|
31
|
+
|
|
32
|
+
Use one or both so client/player builds never require the Server assembly to be present or linked incorrectly.
|
|
33
|
+
|
|
34
|
+
## `IMultiplayerServerService` capabilities
|
|
35
|
+
|
|
36
|
+
| Area | What to use |
|
|
37
|
+
|------|-------------|
|
|
38
|
+
| **Create session** | **`CreateSessionAsync(SessionOptions)`** — new server session from options. |
|
|
39
|
+
| **Create or join by id** | **`CreateSessionAsync(string sessionId, SessionOptions)`** — server session with a chosen session id (create if missing, join if present per SDK behavior). |
|
|
40
|
+
| **Create from matchmaker** | **`CreateMatchSessionAsync(string matchId, SessionOptions)`** — server session tied to a Matchmaker match id; uses matchmaker configuration on options when applicable. |
|
|
41
|
+
|
|
42
|
+
> **`GetSessionAsync`** exists on **`IMultiplayerServerService`** for package-internal use and is **`internal`** in the SDK source; treat the three **`Create*`** methods above as the supported public server entry surface for session creation from game code.
|
|
43
|
+
|
|
44
|
+
## Method signatures
|
|
45
|
+
|
|
46
|
+
```csharp
|
|
47
|
+
// Creates a new dedicated-server session. Returns IServerSession. Throws SessionException on failure.
|
|
48
|
+
Task<IServerSession> CreateSessionAsync(SessionOptions sessionOptions)
|
|
49
|
+
|
|
50
|
+
// Creates or joins a server session using an explicit session id.
|
|
51
|
+
Task<IServerSession> CreateSessionAsync(string sessionId, SessionOptions sessionOptions)
|
|
52
|
+
|
|
53
|
+
// Creates a server session from a Matchmaker match id and session options.
|
|
54
|
+
Task<IServerSession> CreateMatchSessionAsync(string matchId, SessionOptions sessionOptions)
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## Matchmaker server extensions (`MatchmakerServerExtensions`)
|
|
58
|
+
|
|
59
|
+
All members below are declared in **`Unity.Services.Multiplayer.Server`** (`MatchmakerServerExtensions`).
|
|
60
|
+
|
|
61
|
+
```csharp
|
|
62
|
+
// Configure backfill behavior on SessionOptions before create/match session.
|
|
63
|
+
T WithBackfillingConfiguration<T>(this T options, bool enable, bool automaticallyRemovePlayers,
|
|
64
|
+
bool autoStart, int playerConnectionTimeout, int backfillingLoopInterval) where T : SessionOptions
|
|
65
|
+
|
|
66
|
+
// Start backfilling on a matchmade session (server / session handle).
|
|
67
|
+
Task StartBackfillingAsync(this ISession session)
|
|
68
|
+
|
|
69
|
+
// Stop backfilling on a matchmade session.
|
|
70
|
+
Task StopBackfillingAsync(this ISession session)
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## Session options (shared types)
|
|
74
|
+
|
|
75
|
+
**`SessionOptions`** and related lobby/network fields are defined in **`Unity.Services.Multiplayer`**, not in the Server assembly. For property tables, fluent **`SessionOptionsExtensions`**, and networking helpers, use **`entrypoints.md`** — apply the same options when calling **`IMultiplayerServerService`** create APIs on dedicated servers.
|
|
76
|
+
|
|
77
|
+
## Errors
|
|
78
|
+
|
|
79
|
+
Async methods on **`IMultiplayerServerService`** throw **`SessionException`** on failure (same family as the client **`IMultiplayerService`** session APIs).
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
## Table of Contents
|
|
2
|
+
|
|
3
|
+
- [Overview](#overview)
|
|
4
|
+
- [IMultiplayerService capabilities](#imultiplayerservice-capabilities)
|
|
5
|
+
- [Method signatures](#method-signatures)
|
|
6
|
+
- [Options reference](#options-reference)
|
|
7
|
+
- [Session configuration](#session-configuration-sessionoptions-joinsessionoptions-basesessionoptions)
|
|
8
|
+
- [Netcode with session options](#netcode-with-withnetwork-session-options)
|
|
9
|
+
- [Networking model](#networking-model-session-side)
|
|
10
|
+
- [Host / server session](#host--server-session-ihostsession-iserversession)
|
|
11
|
+
- [Matchmaking results](#matchmaking-results-on-a-session)
|
|
12
|
+
- [Errors and observation](#errors-and-observation)
|
|
13
|
+
- [Editor / glue](#editor--glue-unityservicesmultiplayercomponents)
|
|
14
|
+
|
|
15
|
+
## Overview
|
|
16
|
+
|
|
17
|
+
| Topic | Details |
|
|
18
|
+
|--------|---------|
|
|
19
|
+
| **Service access** | `MultiplayerService.Instance` (static) or `unityServices.GetMultiplayerService()` via `UnityServicesExtensions` after Services initialization. |
|
|
20
|
+
| **Core type** | **`ISession`** — session state, players, properties, role (host/member/server), **`Network`** (client), **`LeaveAsync`**, **`ReconnectAsync`**, **`RefreshAsync`**, **`SaveCurrentPlayerDataAsync`**; cast to **`IHostSession`** / **`IServerSession`** when hosting or dedicated server. |
|
|
21
|
+
|
|
22
|
+
### `IMultiplayerService` capabilities
|
|
23
|
+
|
|
24
|
+
| Area | What to use |
|
|
25
|
+
|------|-------------|
|
|
26
|
+
| **Session registry** | `Sessions` (read-only map); events `SessionAdded`, `SessionRemoved`, `AddingSessionStarted`, `AddingSessionFailed`. |
|
|
27
|
+
| **Create / join** | `CreateSessionAsync`, `CreateOrJoinSessionAsync`, `JoinSessionByIdAsync`, `JoinSessionByCodeAsync`, `ReconnectToSessionAsync`, `GetJoinedSessionIdsAsync`. |
|
|
28
|
+
| **Matchmaking into a session** | `MatchmakeSessionAsync` with **`QuickJoinOptions`** (filters, timeout, optional create) or **`MatchmakerOptions`** (queue, ticket attributes, player properties) + **`SessionOptions`**; optional `CancellationToken` on the `MatchmakerOptions` overload. |
|
|
29
|
+
| **Discovery** | `QuerySessionsAsync` + **`QuerySessionsOptions`** (filters, sort, skip/count, continuation token); **`QuerySessionsResults`** may **`StartPolling`** / **`StopPolling`**. |
|
|
30
|
+
|
|
31
|
+
### Method signatures
|
|
32
|
+
|
|
33
|
+
```csharp
|
|
34
|
+
// Creates a new session. Returns IHostSession (host-side). Throws SessionException on failure.
|
|
35
|
+
Task<IHostSession> CreateSessionAsync(SessionOptions sessionOptions)
|
|
36
|
+
|
|
37
|
+
// Joins session by ID, or creates it if it does not exist.
|
|
38
|
+
Task<ISession> CreateOrJoinSessionAsync(string sessionId, SessionOptions sessionOptions)
|
|
39
|
+
|
|
40
|
+
// Joins an existing session by its ID.
|
|
41
|
+
Task<ISession> JoinSessionByIdAsync(string sessionId, JoinSessionOptions sessionOptions = default)
|
|
42
|
+
|
|
43
|
+
// Joins an existing session via a human-readable join code.
|
|
44
|
+
Task<ISession> JoinSessionByCodeAsync(string sessionCode, JoinSessionOptions sessionOptions = default)
|
|
45
|
+
|
|
46
|
+
// Reconnects to a previously joined session after a disconnect.
|
|
47
|
+
Task<ISession> ReconnectToSessionAsync(string sessionId, ReconnectSessionOptions options = default)
|
|
48
|
+
|
|
49
|
+
// Finds and joins a session using Unity's matchmaker service. Supports cancellation.
|
|
50
|
+
Task<ISession> MatchmakeSessionAsync(MatchmakerOptions matchOptions, SessionOptions sessionOptions, CancellationToken cancellationToken = default)
|
|
51
|
+
|
|
52
|
+
// Finds a session using session filters with retries up to a timeout. Can optionally create a session if none is found.
|
|
53
|
+
Task<ISession> MatchmakeSessionAsync(QuickJoinOptions quickJoinOptions, SessionOptions sessionOptions)
|
|
54
|
+
|
|
55
|
+
// Browses available sessions matching the provided query options.
|
|
56
|
+
Task<QuerySessionsResults> QuerySessionsAsync(QuerySessionsOptions queryOptions)
|
|
57
|
+
|
|
58
|
+
// Returns IDs of all sessions the current player is already part of.
|
|
59
|
+
Task<List<string>> GetJoinedSessionIdsAsync()
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### Options reference
|
|
63
|
+
|
|
64
|
+
#### `SessionOptions` _(create / create-or-join / matchmake)_
|
|
65
|
+
|
|
66
|
+
Inherits `BaseSessionOptions`.
|
|
67
|
+
|
|
68
|
+
| Property | Type | Default | Description |
|
|
69
|
+
|---|---|---|---|
|
|
70
|
+
| `Name` | `string` | new GUID | Session display name |
|
|
71
|
+
| `MaxPlayers` | `int` | `0` | Max players including host. Must be > 0 when creating |
|
|
72
|
+
| `IsLocked` | `bool` | `false` | Locked sessions reject new joins |
|
|
73
|
+
| `IsPrivate` | `bool` | `false` | Private sessions are hidden from queries and quick-join |
|
|
74
|
+
| `Password` | `string` | `null` | 8–64 char password required to join. Not readable back from the session |
|
|
75
|
+
| `SessionProperties` | `Dictionary<string, SessionProperty>` | empty | Custom game-specific session properties (e.g. `"map"`). Up to 20 total |
|
|
76
|
+
| `Type` | `string` _(from base)_ | new GUID | Client-side key identifying the session type |
|
|
77
|
+
| `PlayerProperties` | `Dictionary<string, PlayerProperty>` _(from base)_ | empty | Per-player properties (e.g. `"role"`). Up to 10 per player |
|
|
78
|
+
|
|
79
|
+
Fluent extensions (on `SessionOptionsExtensions`): `.WithRelayNetwork()`, `.WithDirectNetwork()`, `.WithDistributedAuthorityNetwork()`, `.WithNetworkHandler()`, `.WithHostMigration()`, `.WithPlayerName()`
|
|
80
|
+
|
|
81
|
+
---
|
|
82
|
+
|
|
83
|
+
#### `JoinSessionOptions` _(join by ID / join by code / quick-join fallback)_
|
|
84
|
+
|
|
85
|
+
Inherits `BaseSessionOptions`.
|
|
86
|
+
|
|
87
|
+
| Property | Type | Default | Description |
|
|
88
|
+
|---|---|---|---|
|
|
89
|
+
| `Password` | `string` | `null` | Password required if the session is password-protected |
|
|
90
|
+
| `Type` | `string` _(from base)_ | new GUID | Client-side session type key |
|
|
91
|
+
| `PlayerProperties` | `Dictionary<string, PlayerProperty>` _(from base)_ | empty | Per-player properties |
|
|
92
|
+
|
|
93
|
+
---
|
|
94
|
+
|
|
95
|
+
#### `ReconnectSessionOptions` _(reconnect)_
|
|
96
|
+
|
|
97
|
+
| Property | Type | Default | Description |
|
|
98
|
+
|---|---|---|---|
|
|
99
|
+
| `Type` | `string` | new GUID | Client-side session type key |
|
|
100
|
+
|
|
101
|
+
Fluent: `.WithNetworkHandler(INetworkHandler)` — disables default NGO/NfE integration.
|
|
102
|
+
|
|
103
|
+
---
|
|
104
|
+
|
|
105
|
+
#### `MatchmakerOptions` _(matchmake via Unity Matchmaker)_
|
|
106
|
+
|
|
107
|
+
| Property | Type | Default | Description |
|
|
108
|
+
|---|---|---|---|
|
|
109
|
+
| `QueueName` | `string` | `null` | Name of the Matchmaker queue |
|
|
110
|
+
| `TicketAttributes` | `Dictionary<string, object>` | empty | Attributes sent with the matchmaking ticket |
|
|
111
|
+
| `PlayerProperties` | `Dictionary<string, PlayerProperty>` | empty | Per-player properties forwarded to matchmaker |
|
|
112
|
+
|
|
113
|
+
---
|
|
114
|
+
|
|
115
|
+
#### `QuickJoinOptions` _(matchmake via filters)_
|
|
116
|
+
|
|
117
|
+
| Property | Type | Default | Description |
|
|
118
|
+
|---|---|---|---|
|
|
119
|
+
| `Filters` | `List<FilterOption>` | empty | Filters a session must satisfy to be joined |
|
|
120
|
+
| `Timeout` | `TimeSpan` | default | How long to retry before giving up and optionally creating a new session |
|
|
121
|
+
| `CreateSession` | `bool` | `false` | Create a new session if none is found within the timeout |
|
|
122
|
+
|
|
123
|
+
> Do not set `Timeout` unless explicitly requested.
|
|
124
|
+
|
|
125
|
+
---
|
|
126
|
+
|
|
127
|
+
#### `QuerySessionsOptions` _(query)_
|
|
128
|
+
|
|
129
|
+
| Property | Type | Default | Description |
|
|
130
|
+
|---|---|---|---|
|
|
131
|
+
| `Count` | `int` | `100` | Max results to return |
|
|
132
|
+
| `Skip` | `int` | `0` | Pagination offset |
|
|
133
|
+
| `FilterOptions` | `List<FilterOption>` | empty | Filters to narrow results |
|
|
134
|
+
| `SortOptions` | `List<SortOption>` | empty | Sort order for results |
|
|
135
|
+
| `ContinuationToken` | `string` | `null` | Token for fetching the next page |
|
|
136
|
+
|
|
137
|
+
---
|
|
138
|
+
|
|
139
|
+
#### `FilterOption` _(used in `QuickJoinOptions` and `QuerySessionsOptions`)_
|
|
140
|
+
|
|
141
|
+
Constructor: `FilterOption(FilterField field, string value, FilterOperation operation)`
|
|
142
|
+
|
|
143
|
+
| Enum | Values |
|
|
144
|
+
|------|--------|
|
|
145
|
+
| **`FilterField`** | `MaxPlayers`, `AvailableSlots`, `Name`, `Created` (RFC3339), `LastUpdated` (RFC3339), `IsLocked`, `HasPassword`, `StringIndex1–5`, `NumberIndex1–5` |
|
|
146
|
+
| **`FilterOperation`** | `Contains` _(Name only)_, `Equal`, `NotEqual`, `Less`, `LessOrEqual`, `Greater`, `GreaterOrEqual` |
|
|
147
|
+
|
|
148
|
+
---
|
|
149
|
+
|
|
150
|
+
#### `SortOption` _(used in `QuerySessionsOptions`)_
|
|
151
|
+
|
|
152
|
+
Constructor: `SortOption(SortOrder order, SortField field)`
|
|
153
|
+
|
|
154
|
+
| Enum | Values |
|
|
155
|
+
|------|--------|
|
|
156
|
+
| **`SortOrder`** | `Ascending`, `Descending` |
|
|
157
|
+
| **`SortField`** | `Name`, `MaxPlayers`, `AvailableSlots`, `CreationTime`, `LastUpdated`, `Id`, `StringIndex1–5`, `NumberIndex1–5` |
|
|
158
|
+
|
|
159
|
+
---
|
|
160
|
+
|
|
161
|
+
#### `AddingSessionOptions` _(event payload — read-only)_
|
|
162
|
+
|
|
163
|
+
| Property | Type | Description |
|
|
164
|
+
|---|---|---|
|
|
165
|
+
| `Type` | `string` | The session type passed to the create/join call |
|
|
166
|
+
|
|
167
|
+
---
|
|
168
|
+
|
|
169
|
+
### Session configuration (`SessionOptions`, `JoinSessionOptions`, `BaseSessionOptions`)
|
|
170
|
+
|
|
171
|
+
| Topic | Details |
|
|
172
|
+
|--------|---------|
|
|
173
|
+
| **Lobby-like fields** | Max players, name, password, locked/private flags, typed **`Type`**, **session** and **player** properties with **`VisibilityPropertyOptions`** (Public / Member / Private) and indexed slots (**`PropertyIndex`**) for query filters. |
|
|
174
|
+
| **Networking** (`SessionOptionsExtensions`) | **`WithRelayNetwork`**, **`WithDirectNetwork`** (listen/publish IP/port or **`DirectNetworkOptions`**), **`WithNetworkOptions`** (e.g. **`RelayProtocol`**), **`WithNetworkHandler`** for custom **`INetworkHandler`**. |
|
|
175
|
+
| **Host migration** | **`WithHostMigration`** + **`IMigrationDataHandler`**; on **`IHostSession`**: **`GetHostMigrationDataAsync`** / **`SetHostMigrationDataAsync`**. |
|
|
176
|
+
| **Player name** | **`WithPlayerName`** (visibility). |
|
|
177
|
+
| **Matchmaker backfill** | **`MatchmakerServerExtensions.WithBackfillingConfiguration`** on **`SessionOptions`**; on matchmade **`ISession`**: **`StartBackfillingAsync`** / **`StopBackfillingAsync`**. See **`llms.txt`** and package docs for hosting constraints. |
|
|
178
|
+
|
|
179
|
+
### Netcode with `With*Network*` session options
|
|
180
|
+
|
|
181
|
+
| Condition | Behavior |
|
|
182
|
+
|-----------|----------|
|
|
183
|
+
| **`SessionOptionsExtensions`** include gameplay networking (**`WithRelayNetwork`**, **`WithDirectNetwork`**, **`WithNetworkOptions`**, **`WithNetworkHandler`**, …) | **create / join / matchmake / reconnect** bring up **NGO** or **NFE** as configured—no separate Netcode start for that path. |
|
|
184
|
+
|
|
185
|
+
### Networking model (session side)
|
|
186
|
+
|
|
187
|
+
| Surface | Role |
|
|
188
|
+
|---------|------|
|
|
189
|
+
| **`IHostSessionNetwork`** | **`StartDirectNetworkAsync`**, **`StartRelayNetworkAsync`**, **`StopNetworkAsync`**; state and failure events; **`INetworkHandler`**. |
|
|
190
|
+
| **`IClientSessionNetwork`** | Client **`NetworkState`** and events; **`NetworkHandler`**. |
|
|
191
|
+
| **`NetworkConfiguration`** | UTP endpoints and Relay server data; **`NetworkType`**: Direct, Relay, **DistributedAuthority**; **`NetworkRole`**: Client, Server, Host. |
|
|
192
|
+
|
|
193
|
+
### Matchmaking results on a session
|
|
194
|
+
|
|
195
|
+
| API | Use when |
|
|
196
|
+
|-----|----------|
|
|
197
|
+
| **`MatchmakerExtensions.GetMatchmakingResults(ISession)`** | Stored matchmaking results are needed after a matchmade session exists. |
|
|
198
|
+
|
|
199
|
+
### Errors and observation
|
|
200
|
+
|
|
201
|
+
All async methods on **`IMultiplayerService`** throw **`SessionException`** on failure; **`SessionException`** exposes a specific session error type and message.
|
|
202
|
+
|
|
203
|
+
| Type | Role |
|
|
204
|
+
|------|------|
|
|
205
|
+
| **`SessionException`** / **`SessionError`** | Session and composed flows. |
|
|
206
|
+
| **`SessionObserver`** | Watch add/fail events for a given session **type**. |
|
|
207
|
+
|
|
208
|
+
### Editor / glue (`Unity.Services.Multiplayer.Components`)
|
|
209
|
+
|
|
210
|
+
| Item | Role |
|
|
211
|
+
|------|------|
|
|
212
|
+
| **`MultiplayerSession`** (ScriptableObject) | Holds **`ISession`** and UnityEvent groups (lifecycle, session, players). |
|
|
213
|
+
| **`SessionConnector`** / **`SessionConnectorBehaviour`** | Create or create-or-join flows (e.g. on sign-in). |
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
## Examples: user-facing language
|
|
2
|
+
|
|
3
|
+
These illustrate **User-facing questions and explanations** in [implementation-fit.md](implementation-fit.md). They are for prose to the user, not for code or file edits (those may use real API names).
|
|
4
|
+
|
|
5
|
+
### Clarifying questions
|
|
6
|
+
|
|
7
|
+
**Bad (SDK / product vocabulary):**
|
|
8
|
+
|
|
9
|
+
- "Do you want to use **Lobby** for the server list, or **Sessions** only?"
|
|
10
|
+
- "Should we call **`QuerySessionsAsync`** or **`MatchmakeSessionAsync`**?"
|
|
11
|
+
- "Do you need **Relay** or is **direct** fine?"
|
|
12
|
+
|
|
13
|
+
**Good (game / product terms):**
|
|
14
|
+
|
|
15
|
+
- "Should players **see a list of open games** and pick one, or **join with a code or invite** only?"
|
|
16
|
+
- "Should matchmaking be **automatic** (the game finds opponents for you) or **manual** (players choose a room)?"
|
|
17
|
+
- "When two players are on different home networks, is **mediated connectivity** (no open ports on a router) a requirement?"
|
|
18
|
+
|
|
19
|
+
### Explanations and plans
|
|
20
|
+
|
|
21
|
+
**Bad (splitting named backend products):**
|
|
22
|
+
|
|
23
|
+
- "We'll use **Lobby** for metadata, **Relay** for NAT traversal, and **Matchmaker** for ranked."
|
|
24
|
+
- "**Sessions** wraps **Lobby** so you don't need **Lobby** directly."
|
|
25
|
+
|
|
26
|
+
**Good (plain language, same ideas):**
|
|
27
|
+
|
|
28
|
+
- "We'll keep **room metadata** (map, rules) in one place, use **brokered connectivity** when direct links are unreliable, and **automatic pairing** for ranked."
|
|
29
|
+
- "The **main multiplayer package API** can own **room state and joins** so you don't add a second room system on top."
|
|
30
|
+
|
|
31
|
+
### When the user already named a product
|
|
32
|
+
|
|
33
|
+
If they wrote e.g. "we're on **Relay** already," you may **mirror their wording** in discussion; still avoid **extra** product enumeration they did not ask for.
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
## Implementation fit: clarify multiplayer requirements
|
|
2
|
+
|
|
3
|
+
Before recommending architecture or APIs internally, the agent **must** ground advice in the right product choices for *this* application. Map answers to [entrypoints.md](entrypoints.md) and the **Priority: Multiplayer Sessions first** section in [SKILL.md](../SKILL.md) only **after** requirements are clear (from context, project, or user). For concrete phrasing samples, see [examples.md](examples.md).
|
|
4
|
+
|
|
5
|
+
**How to obtain requirements (in order):**
|
|
6
|
+
|
|
7
|
+
1. **Conversation and task context** — Use stated goals (e.g. "2-player co-op", "ranked 5v5", "mobile", "host leaves often").
|
|
8
|
+
2. **Project state when available** — Inspect the workspace (e.g. `Packages/manifest.json` for Netcode / multiplayer packages, existing multiplayer or networking scripts, platform settings) and align recommendations with what is already chosen.
|
|
9
|
+
3. **Ask the user** — If a dimension below would **change** the recommended approach and is not inferable from (1) or (2), ask a **short, targeted** question instead of assuming. Follow **User-facing questions and explanations** below.
|
|
10
|
+
|
|
11
|
+
### User-facing questions and explanations
|
|
12
|
+
|
|
13
|
+
- **Clarifying questions** must stay **high level**: player count, how people **find or join** a game, who **runs** the match (e.g. one player's machine vs a dedicated machine), fairness/latency expectations, disconnect/reconnect and "host leaves" behavior, target platforms, and which **Unity networking stack** the project already uses **only if** the user has brought it up or it is visible in the project. Phrase questions in **game / product** terms.
|
|
14
|
+
- **Do not** name or ask about Unity **product or service** implementations in questions: e.g. avoid the terms **Sessions**, **Lobby**, **Matchmaker**, **Relay**, and avoid prompting with **API or type names** (`ISession`, `QuerySessionsAsync`, etc.). The user should not need SDK vocabulary to answer.
|
|
15
|
+
- In **explanations, summaries, and plans** addressed to the user (outside of code blocks and file edits), **do not mention** Lobby, Matchmaker, Relay, or Multiplayer **Sessions** as named products, and **do not** contrast or enumerate those **underlying services**—unless the **user explicitly** asked about them by name or asked for that level of SDK/architecture detail. Use plain language (e.g. "list of open games", "automatic pairing", "brokered connectivity when direct player-to-player links are unreliable", "the main Unity multiplayer package API") when a concept must be described.
|
|
16
|
+
- **Code, API references, and file contents** may use the exact types, namespaces, and methods from this skill and from `llms.txt` as needed for a correct implementation.
|
|
17
|
+
|
|
18
|
+
### Dimensions to consider
|
|
19
|
+
|
|
20
|
+
- **Player count and topology** — Players per match and rough scale (many small matches vs few large ones). Whether the simulation can run on a **host client** (often with mediated connectivity) or needs a **dedicated server** / server-authoritative hosting story. *Internal mapping:* relay vs direct listen/publish, host vs dedicated server roles, capacity limits on the multiplayer entrypoint APIs.
|
|
21
|
+
|
|
22
|
+
- **Casual vs competitive** — Tolerance for **host-based authority** and latency variance vs need for **stricter authority, consistency, and fairness** (often favoring dedicated servers and careful netcode choices). Informs how strongly to push dedicated hosting, tick/interpolation choices, and cheat-sensitive design (without duplicating full anti-cheat guidance here).
|
|
23
|
+
|
|
24
|
+
- **Discovery and how matches form** — Join codes or invites vs **browsing a list** of open games vs **automatic pairing**; visibility and filterable game metadata. *Internal mapping:* query/list flows, quick-join-style filters, ticket/queue flows; session properties and indexes as needed.
|
|
25
|
+
|
|
26
|
+
- **Connection model and resilience** — **NAT / home networks** (need for mediated connectivity vs published listen addresses), **reconnect** after disconnects, and **moving the host** without ending the match. *Internal mapping:* relay vs direct network options, `ReconnectAsync`, host migration hooks, network start/stop.
|
|
27
|
+
|
|
28
|
+
- **Platform constraints** — Targets (e.g. **mobile** dropouts and backgrounding, **console** networking and certification expectations) that affect match lifetime, reconnect UX, and viable connection patterns.
|
|
29
|
+
|
|
30
|
+
- **Team skills and codebase stack** — **Netcode for GameObjects** vs **Netcode for Entities** (or other networking) must match packages and patterns already in the project; prefer extending the stack in `manifest.json` and existing code rather than introducing a parallel net model without an explicit user request.
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
## Underlying services (use only when necessary)
|
|
2
|
+
|
|
3
|
+
**Agent-only reference** for implementation when the primary API is insufficient or the user explicitly requested these—**do not** surface this table or product names to the user unless they asked for them.
|
|
4
|
+
|
|
5
|
+
Summarized for reference—not the default path:
|
|
6
|
+
|
|
7
|
+
| Area | Namespace | Role |
|
|
8
|
+
|------|-----------|------|
|
|
9
|
+
| **Lobby** | `Unity.Services.Lobbies` | Standalone lobby CRUD, query, realtime lobby events, migration payloads—prefer **Sessions** unless you need lobby-only workflows. |
|
|
10
|
+
| **Matchmaker** | `Unity.Services.Matchmaker` | Low-level tickets, backfill ticket APIs, ticket status—prefer **`MatchmakeSessionAsync`** + **`MatchmakerOptions`** on **`IMultiplayerService`** first. |
|
|
11
|
+
| **Relay** | `Unity.Services.Relay` | Raw allocations and join codes—prefer **`WithRelayNetwork`** / **`StartRelayNetworkAsync`** on the session network first. |
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
## Workflow prerequisites (packages and cloud setup)
|
|
2
|
+
|
|
3
|
+
**Agent-only sanity check** before recommending a path: match the user's **intent** to **dependencies** and **live services / deployment** (see **`llms.txt`** install, init, deployment, and tutorial pages for authoritative steps). Package IDs can vary slightly by Unity/editor version—verify in Package Manager or docs when implementing.
|
|
4
|
+
|
|
5
|
+
**Which workflow applies** must be **inferred** when possible from **conversation context** and **project state** (e.g. `Packages/manifest.json`, server vs client build targets, existing multiplayer scripts, deployment assets). If more than one row in the table could fit and the choice **changes** prerequisites or APIs, **ask the user** with **high-level** questions (see **User-facing questions and explanations** in [implementation-fit.md](implementation-fit.md)), not by naming product rows from this table. This aligns with **Implementation fit** in [implementation-fit.md](implementation-fit.md): infer first, then clarify if ambiguous.
|
|
6
|
+
|
|
7
|
+
Unity Gaming Services **initialization** and **authentication** are required for all workflows.
|
|
8
|
+
|
|
9
|
+
| Workflow (what the product is doing) | Typically required |
|
|
10
|
+
|--------------------------------------|-------------------|
|
|
11
|
+
| Rooms / join-in-progress **without** starting the session **gameplay network** (metadata, codes, lists, properties only) | `com.unity.services.multiplayer`. **No** Netcode gameplay package required unless they add a custom **`INetworkHandler`** or later start **`StartRelayNetworkAsync`** / **`StartDirectNetworkAsync`**. |
|
|
12
|
+
| **Gameplay** simulation synced over the session **Network** (host/client or server roles with Relay or direct transport) | **Exactly one** gameplay stack: **NGO** — `com.unity.netcode.gameobjects` **or** **NFE** — `com.unity.netcode.entities` (Netcode for Entities). Integrate transport with session network APIs per Unity's session + Netcode guides; do not assume both stacks. |
|
|
13
|
+
| **Quick join** (filter-based auto pick / create) | Session **type** and **indexed** properties for filters; **`QuickJoinOptions`** in code. |
|
|
14
|
+
| **Ticket matchmaking** into a **player-hosted** match | A deployed **Matchmaker queue (MMQ)** (name matches **`MatchmakerOptions`**), Matchmaker **environment** / dashboard setup, and authenticated players. |
|
|
15
|
+
| **Ticket matchmaking** with a **dedicated game server (DGS)** | **MMQ** configured for the **DGS / server allocation** flow, a **server build** and **hosting** setup (e.g. Game Server Hosting / Multiplay—see **`llms.txt`** hosting and deployment topics), server process using the **server** session role where applicable, and often **`WithBackfillingConfiguration`** + **`StartBackfillingAsync`** / **`StopBackfillingAsync`** when refilling player slots on an existing allocation. |
|
|
16
|
+
| **Editor wiring** with **`MultiplayerSession`** / **`SessionConnector`** | Same multiplayer package (components assembly **`Unity.Services.Multiplayer.Components`**); still subject to the Netcode row above if gameplay networking is used. |
|
|
17
|
+
| **Deploying** Matchmaker queues or Multiplayer assets from the Editor | Unity **Deployment** window / deployment docs under **`llms.txt`** (queue, environment, multiplayer config) so cloud resources exist before code calls into them. |
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: setup-vivox-voice-chat
|
|
3
|
+
description: Add and configure in-game voice chat and text chat for Unity multiplayer games using Unity Vivox. Covers microphone setup and mic permissions on Android/iOS, voice activity detection (VAD) tuning, voice volume and mute controls in a settings UI (VoiceVadMinimumVolume, mic slider, mute button, speaking indicator), proximity/3D spatial voice for FPS/co-op games, team/party/lobby/guild voice channels, push-to-talk, muting self and other players, whisper/direct messages, in-game text chat, and Vivox SDK init + Unity Authentication sign-in. Use when the user asks to add voice chat, voice comms, microphone/mic support, a voice-chat settings UI, mute button, VAD threshold, push-to-talk, proximity or spatial voice, team voice, party chat, lobby chat, direct messages, or mentions Vivox, VivoxService, com.unity.services.vivox, JoinGroupChannelAsync, JoinPositionalChannelAsync, LoginAsync, or migrating from legacy Vivox (Client.Instance / LoginSession / AccountId).
|
|
4
|
+
required_packages:
|
|
5
|
+
com.unity.services.vivox: ">=16.4.0"
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Unity Vivox — Voice & Text Chat
|
|
9
|
+
|
|
10
|
+
Namespace: `Unity.Services.Vivox` | Package: `com.unity.services.vivox`
|
|
11
|
+
Companion packages: `Unity.Services.Core`, `Unity.Services.Authentication`
|
|
12
|
+
|
|
13
|
+
Vivox v16+ replaced the v4 `Client` / `ILoginSession` / `IChannelSession` model with a single static entry point: **`VivoxService.Instance`**. All operations — init, login, channel join, messaging, muting — go through it. Do **not** use v4 patterns (`Client.Instance`, `AccountId`, `ChannelId`, `ILoginSession`, `UnityPurchasing.*`, etc.); those are gone in v16.
|
|
14
|
+
|
|
15
|
+
## Documentation Map
|
|
16
|
+
|
|
17
|
+
Use the [Unity Vivox curated documentation map](https://docs.unity.com/en-us/vivox-unity/llms.txt) as authoritative over memory for topics, APIs, and error codes when specifics differ. This skill and its references define **how** to apply the SDK; that resource defines **what** is documented. **Never** mention the `llms.txt` filename to the user. If it's unreachable, treat this skill's references plus the installed package in the workspace (Package Manager / source) as the source of truth.
|
|
18
|
+
|
|
19
|
+
## Detailed References
|
|
20
|
+
|
|
21
|
+
Read on demand — only when you need signatures, event details, or platform gotchas beyond what's in this file.
|
|
22
|
+
|
|
23
|
+
- **Init, sign-in, and access tokens:** [references/init-and-login.md](references/init-and-login.md)
|
|
24
|
+
- **Voice channels (positional and non-positional):** [references/voice-channels.md](references/voice-channels.md)
|
|
25
|
+
- **Text chat (channel messages and directed messages):** [references/text-chat.md](references/text-chat.md)
|
|
26
|
+
- **Events, participants, and cleanup:** [references/events-and-participants.md](references/events-and-participants.md)
|
|
27
|
+
- **Troubleshooting and platform notes:** [references/troubleshooting.md](references/troubleshooting.md)
|
|
28
|
+
|
|
29
|
+
## Initialization Order (Do Not Skip Steps)
|
|
30
|
+
|
|
31
|
+
The correct order is **UGS Core → Authentication sign-in → Vivox init → Vivox login**. Skipping or reordering these fails silently or throws obscure errors.
|
|
32
|
+
|
|
33
|
+
```csharp
|
|
34
|
+
using Unity.Services.Core;
|
|
35
|
+
using Unity.Services.Authentication;
|
|
36
|
+
using Unity.Services.Vivox;
|
|
37
|
+
|
|
38
|
+
async void Start()
|
|
39
|
+
{
|
|
40
|
+
await UnityServices.InitializeAsync();
|
|
41
|
+
await AuthenticationService.Instance.SignInAnonymouslyAsync();
|
|
42
|
+
await VivoxService.Instance.InitializeAsync();
|
|
43
|
+
// subscribe to events (see table below) BEFORE calling LoginAsync
|
|
44
|
+
await VivoxService.Instance.LoginAsync(new LoginOptions { DisplayName = "Bob" });
|
|
45
|
+
}
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
- Calling `VivoxService.Instance.InitializeAsync()` twice throws `5041 VxErrorAlreadyInitialized`. Guard against re-init on scene reload.
|
|
49
|
+
- If Unity Authentication (`AuthenticationService`) is not used, the player identity falls back to a per-session GUID — display names still work but you lose cross-session identity. See [references/init-and-login.md](references/init-and-login.md) for the Vivox Access Token (VAT) alternative.
|
|
50
|
+
|
|
51
|
+
## Joining Channels
|
|
52
|
+
|
|
53
|
+
Vivox has three join methods, one per channel type. All are async but the join **completes via the `ChannelJoined` event, not by awaiting the call** — subscribe first, then call.
|
|
54
|
+
|
|
55
|
+
| Method | Purpose |
|
|
56
|
+
|---|---|
|
|
57
|
+
| `VivoxService.Instance.JoinGroupChannelAsync(name, ChatCapability, ChannelOptions?)` | Non-positional (party, team, lobby, guild) |
|
|
58
|
+
| `VivoxService.Instance.JoinEchoChannelAsync(name, ChatCapability, ChannelOptions?)` | Test channel that echoes your own audio back |
|
|
59
|
+
| `VivoxService.Instance.JoinPositionalChannelAsync(name, ChatCapability, Channel3DProperties, ChannelOptions?)` | 3D spatial audio driven by transform position |
|
|
60
|
+
|
|
61
|
+
`ChatCapability` values: `TextOnly`, `AudioOnly`, `TextAndAudio`.
|
|
62
|
+
|
|
63
|
+
**Limits:** max 10 non-positional channels per user; max 200 participants per channel. Exceeding either fails with `20502 VxXmppServerErrorServiceUnavailable`. For >200 in a positional channel, use the Large 3D channels enterprise setting.
|
|
64
|
+
|
|
65
|
+
Leave with `VivoxService.Instance.LeaveChannelAsync(channelName)` or `LeaveAllChannelsAsync()`. See [references/voice-channels.md](references/voice-channels.md) for `Channel3DProperties` fields and mic-permission handling on Android/iOS.
|
|
66
|
+
|
|
67
|
+
## Text Messaging
|
|
68
|
+
|
|
69
|
+
**Channel messages** (broadcast to all participants of a channel with `TextOnly` or `TextAndAudio`):
|
|
70
|
+
|
|
71
|
+
- Send: `VivoxService.Instance.SendChannelTextMessageAsync(string channelName, string message)`
|
|
72
|
+
- Receive: subscribe to `VivoxService.Instance.ChannelMessageReceived` (`Action<VivoxMessage>`)
|
|
73
|
+
|
|
74
|
+
**Directed messages** (peer-to-peer, no channel required):
|
|
75
|
+
|
|
76
|
+
- Send: `VivoxService.Instance.SendDirectTextMessageAsync(string playerId, string message)`
|
|
77
|
+
- Receive: subscribe to `VivoxService.Instance.DirectedMessageReceived` (`Action<VivoxMessage>`)
|
|
78
|
+
|
|
79
|
+
**Common hallucination:** the send method is `SendDirectTextMessageAsync` — **not** `SendDirectedTextMessageAsync`. The event, however, **is** `DirectedMessageReceived`. Note the asymmetry.
|
|
80
|
+
|
|
81
|
+
`VivoxMessage` fields: `ChannelName` (null for directed), `SenderDisplayName`, `SenderPlayerId`, `MessageText`, `ReceivedTime`, `Language`, `FromSelf`, `MessageId`.
|
|
82
|
+
|
|
83
|
+
Edit/delete APIs (`EditChannelTextMessageAsync`, `DeleteChannelTextMessageAsync`, `EditDirectTextMessageAsync`, `DeleteDirectTextMessageAsync`) and history (`GetChannelTextMessageHistoryAsync`, `GetDirectTextMessageHistoryAsync`) are covered in [references/text-chat.md](references/text-chat.md). Chat history retention is 7 days by default.
|
|
84
|
+
|
|
85
|
+
## Required Event Subscriptions
|
|
86
|
+
|
|
87
|
+
Subscribe to events **before** the corresponding async call. `LoggedIn` may fire immediately for reconnects; `ChannelJoined` fires as the join completes.
|
|
88
|
+
|
|
89
|
+
| Call | Success Event | Failure / Counterpart |
|
|
90
|
+
|---|---|---|
|
|
91
|
+
| `LoginAsync()` | `LoggedIn` | `LoggedOut` |
|
|
92
|
+
| `JoinGroupChannelAsync()` / `JoinEchoChannelAsync()` / `JoinPositionalChannelAsync()` | `ChannelJoined(string channelName)` | `ChannelLeft(string channelName)` |
|
|
93
|
+
| — (any joined channel) | `ParticipantAddedToChannel(VivoxParticipant)` | `ParticipantRemovedFromChannel(VivoxParticipant)` |
|
|
94
|
+
| `SendChannelTextMessageAsync()` (remote receive) | `ChannelMessageReceived(VivoxMessage)` | — |
|
|
95
|
+
| `SendDirectTextMessageAsync()` (remote receive) | `DirectedMessageReceived(VivoxMessage)` | — |
|
|
96
|
+
|
|
97
|
+
**Always unsubscribe in `OnDestroy` / `OnDisable`.** `VivoxService.Instance` is a persistent singleton — event handlers on destroyed MonoBehaviours will double-fire and NRE on scene reload.
|
|
98
|
+
|
|
99
|
+
Per-participant events (`ParticipantMuteStateChanged`, `ParticipantSpeechDetected`, `ParticipantAudioEnergyChanged`) live on the `VivoxParticipant` instance you receive from `ParticipantAddedToChannel` — not on `VivoxService.Instance`. See [references/events-and-participants.md](references/events-and-participants.md).
|
|
100
|
+
|
|
101
|
+
## Access Tokens (Brief)
|
|
102
|
+
|
|
103
|
+
The default path uses **UGS Authentication** — Vivox mints access tokens automatically from your UGS project once `AuthenticationService.Instance.SignInAnonymouslyAsync()` (or another sign-in method) has completed. **No manual token code is required** for standard flows.
|
|
104
|
+
|
|
105
|
+
Server-side Vivox Access Token (VAT) minting is only needed when you use a non-UGS identity system or when you need channel-scoped privileged tokens (kick, mute-all, transcription). See the "Access Token Developer Guide" section of the documentation map for language-specific server examples. Do not embed HMAC signing keys in the client.
|
|
106
|
+
|
|
107
|
+
## Validation
|
|
108
|
+
|
|
109
|
+
After writing code that uses this package:
|
|
110
|
+
|
|
111
|
+
1. Verify the project compiles without errors and that `using Unity.Services.Vivox;` resolves.
|
|
112
|
+
2. Confirm init order: `UnityServices.InitializeAsync` → `AuthenticationService.Instance.SignInAnonymouslyAsync` → `VivoxService.Instance.InitializeAsync` → `VivoxService.Instance.LoginAsync`.
|
|
113
|
+
3. No v4 legacy patterns: no `Client.Instance`, no `AccountId`, no `ChannelId`, no `ILoginSession`, no `IChannelSession`. All access goes through `VivoxService.Instance`.
|
|
114
|
+
4. All events consumed by the code are subscribed **before** the async call that triggers them, and are unsubscribed in `OnDestroy`.
|
|
115
|
+
5. Channel join code does not `await` the join call as if it completes join — it subscribes to `ChannelJoined` and reacts there.
|
|
116
|
+
6. Directed message send uses `SendDirectTextMessageAsync` (NOT `SendDirectedTextMessageAsync`). Directed message receive uses `DirectedMessageReceived`.
|
|
117
|
+
7. Android builds request `RECORD_AUDIO` at runtime before joining an audio channel; iOS builds have `NSMicrophoneUsageDescription` in the plist.
|
|
118
|
+
8. No HMAC signing keys or Vivox `SECRET`/`APP_ID` are embedded in client code — VAT-based flows are documented but delegated to a server.
|