Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
233 changes: 233 additions & 0 deletions skills/implement-in-app-purchases/README.md

Large diffs are not rendered by default.

69 changes: 69 additions & 0 deletions skills/levelplay-unity-integration/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
# Changelog

## v0.10.0 — 2026-08-21 — Workflow spine, and a hard install gate

Moves reference material out of `SKILL.md` and makes the SDK install a verified step rather than an assumed one.

**Changed:**
- `SKILL.md` is now the workflow spine only, going from about 1,100 lines to 435. The dependency-resolution, testing-and-validation and troubleshooting material that was inlined in it moves into `references/`. Nothing was dropped; it is read on demand instead. `SKILL.md` is loaded in full on every invocation while a reference file is read only when a step links it, so this is a saving on every run that does not need the detail.
- The reference set grows from nine files to twelve: `dependency-resolution.md`, `testing-and-validation.md` and `troubleshooting.md` are now separate files.

**Added:**
- **A hard install-verification gate at Step 3.** No LevelPlay code is written until `com.unity.services.levelplay` is confirmed present in `Packages/packages-lock.json`, read from the project rather than taken from the Package Manager window or an earlier turn. The package is easy to believe is installed: its display name is **Ads Mediation** while the recorded id is `com.unity.services.levelplay`, two similarly named packages are the wrong ones, and the install prompts for a second package partway through. Code written before the id resolves fails with `CS0246` on every LevelPlay symbol, which reads as a code problem rather than an install problem. The gate also distinguishes "the install never happened" from "Unity has not resolved it yet", because the fix differs.
- The deprecated-APIs section now states explicitly that `SetGDPRConsents(Dictionary)` is **not** deprecated on SDK 9.4.x, where it is the correct call, and only becomes `[Obsolete]` on 9.5.0+. It is kept out of the deprecated list rather than listed with a caveat, so it cannot be read the wrong way round.

## v0.9.0 — 2026-08-17 — SDK 9.x migration support

Adds guided migration to the LevelPlay 9.x SDK and the current Ad Unit (MADU) APIs.

**New:**
- "New Integration or Migration?" routing step at the start of the workflow
- Migration reference guide covering five scenarios: SDK upgrade (.unitypackage or UPM, including switching from .unitypackage to UPM), init API migration (IronSource.Agent to LevelPlay.Init), ad unit API migration (rewarded, interstitial, banner, and the ILRD handler), Maven Central dependency build failures, and Unity Ads (Advertisement Legacy) migration
- Upgrade safety flow: Developer Settings values and installed adapters are inventoried, and the user confirms, before any folder deletion; post-upgrade steps cover adapter reinstall, settings re-entry, and removal of the stale LEVELPLAY_DEPENDENCIES_INSTALLED scripting define when switching from .unitypackage to UPM
- Migration completeness checklist covering requirements that a line-by-line translation misses: placement capping checks when dashboard placements are used, an explicit rewarded load trigger, the version API mappings, correct ILRD event names, preserved logging, HideAd vs DestroyAd intent for legacy destroyBanner calls, and removal of onApplicationPause
- Compilation check after migration edits, with errors fixed before presenting results
- Skill description now also triggers on SDK upgrades, deprecated IronSource.Agent APIs, and Unity Ads migration

**Fixed:**
- Banner adaptive-size example used a constructor form that does not compile on any 9.x version; now configured through Config.Builder (verified against 9.0.0, 9.4.0, and 9.5.0 source)
- API mapping corrections: validateIntegration maps to LevelPlay.ValidateIntegration (not LaunchTestSuite); pluginVersion maps to LevelPlay.PluginVersion (distinct from UnityVersion); onApplicationPause is removed in 9.x with no replacement; the legacy ILRD subscription maps to LevelPlay.OnImpressionDataReady on SDK 9.4.x and earlier or per-instance OnAdImpressionDataReady on 9.5.0+
- Unity Ads migration now surfaces that LevelPlay.Init has no test-mode parameter (Test Suite or dashboard test mode are the equivalents) instead of dropping the flag silently
- Package edits during upgrades touch only manifest.json; packages-lock.json is never hand-edited
- Maven Central migration is mentioned only when the project actually needs it
- Corrected a consent-callback name mismatch in the privacy reference, and a banner troubleshooting example that called a method banners do not have

## v0.8.0 — 2026-08-05 — Version-aware ILRD (SDK 9.5.0), rewarded load lifecycle, and improved activation

Accuracy and activation updates reflecting current LevelPlay SDK behavior.

**Impression-level revenue (ILRD) — SDK 9.5.0 API change**
- ILRD now documents both delivery mechanisms: the single global `LevelPlay.OnImpressionDataReady` event (SDK 9.4.x and earlier) and the per-ad-instance `OnAdImpressionDataReady` events on each ad object (SDK 9.5.0+), which replace the global event.
- The global event still exists but is deprecated on SDK 9.5.0+ and generates a compiler warning.
- Updated the initialization step and the rewarded/interstitial/banner references to direct SDK 9.5.0+ users to the per-instance approach.

**Rewarded ad load lifecycle**
- Clarified that `LoadAd()` must be called explicitly; the SDK does not auto-manage rewarded loading (unlike the legacy IronSource API).
- Reframed the guidance so explicit, publisher-triggered loading is the default, with eager preloading documented as an optional pattern. Applies to `references/rewarded-api.md` and the loading-strategy guidance in `SKILL.md`.

**Description and activation**
- Reworked the skill description to increase activation on general ad and monetization requests, not only when a developer names LevelPlay.
- Added guidance at the top of the skill directing the agent to run it as an interactive, step-by-step workflow and use the reference files, rather than answering from general knowledge.

## v0.7.0 — 2026-06-12 — Initial public beta release

First release of the LevelPlay Unity integration skill, released as public beta.

**Features:**
- Step-by-step installation of the LevelPlay SDK using the Ads Mediation package in Unity Package Manager
- Native dependency resolution for Android and iOS
- SDK initialization with three code organization options
- Ad unit strategy recommendations based on business goals (revenue-focused, UX-focused, or balanced)
- Implementation guides for rewarded ads, interstitials, and banner ads
- Privacy compliance support (GDPR, CCPA, COPPA)
- iOS setup (App Tracking Transparency, SKAdNetwork)
- Impression-level revenue tracking (ILRD)
- Testing guidance using mock ads and the LevelPlay Test Suite

## Feedback

This skill is currently in beta. [Share your feedback here](https://docs.google.com/forms/d/e/1FAIpQLSe7WvWozJ67KjgOLglSBvLug8JdgEYk895nn_BHZs0HS_bWJA/viewform).
78 changes: 78 additions & 0 deletions skills/levelplay-unity-integration/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
# LevelPlay Unity Integration Skill

![Beta](https://img.shields.io/badge/status-beta-orange) ![Version](https://img.shields.io/badge/version-0.7.0-blue) ![License](https://img.shields.io/badge/license-Unity%20Companion-blue)

> 🧪 **Note:** This skill is in beta and will be shaped by your feedback. Try it out and [let us know what you think](https://docs.google.com/forms/d/e/1FAIpQLSe7WvWozJ67KjgOLglSBvLug8JdgEYk895nn_BHZs0HS_bWJA/viewform)!

A skill that guides Unity developers through integrating the LevelPlay SDK using the Ads Mediation package in Unity Package Manager: from installation to fully working rewarded ads, interstitials, and banners.

Compatible with Claude Code, GitHub Copilot, Cursor, Cline, and [50+ other agents](https://skills.sh).

## What it does

When you activate this skill, your agent walks you step by step through the complete LevelPlay integration:

1. **Installing the SDK** via the Ads Mediation package in Unity Package Manager
2. **Resolving native dependencies** for Android and iOS builds
3. **Collecting credentials** from the LevelPlay dashboard
4. **Configuring privacy compliance** (GDPR, CCPA, COPPA) if needed
5. **Initializing the SDK** in your project, with three code organization options to fit your existing setup
6. **Recommending an ad unit strategy** based on your goals (revenue-focused, UX-focused, or balanced)
7. **Implementing ad formats** — rewarded ads, interstitials, and banners — with production-ready C# code
8. **Testing and validating** using mock ads in the Unity Editor and the LevelPlay Test Suite on device

The skill also covers iOS-specific setup (App Tracking Transparency, SKAdNetwork), impression-level revenue tracking (ILRD) for analytics platforms, bid floors, and common troubleshooting.

## Requirements

- A Unity project using an LTS or actively developed version of the Unity Editor
- LevelPlay Unity package and SDK version 9.4.0+
- A LevelPlay account: [get started here](https://platform.ironsrc.com/)

Documentation for setting up the LevelPlay Unity package: see the [Unity Package Integration guide](https://docs.unity.com/en-us/grow/levelplay/sdk/unity/package-integration).

## Installation

```bash
npx skills add Unity-Technologies/skills
```

Then activate the `levelplay-unity-integration` skill in your agent.

## Using the skill

Type `/levelplay-unity-integration` to activate the skill, then describe what you want to do:

- *"I want to add rewarded ads to my Unity game"*
- *"Help me integrate LevelPlay into my project"*
- *"I need to add interstitial ads between levels"*
- *"I have LevelPlay installed, help me implement banner ads"*

You can jump in at any step. If the Unity package and SDK are already installed, your agent will pick up from where you are.

## Privacy & Legal

> **Note:** This skill provides technical integration guidance, including for LevelPlay's privacy APIs. It is not legal advice, and it does not determine which laws apply to your app — that depends on your users, your data practices, and your distribution. Consult your own legal counsel, and refer to [Regulation Advanced Settings for Unity](https://docs.unity.com/en-us/grow/levelplay/sdk/unity/regulation-advanced-settings) for the authoritative LevelPlay documentation.

## What's in this folder

```
levelplay-unity-integration/
├── SKILL.md # The workflow spine: decisions, checkpoints, questions
├── references/ # Detail read on demand, linked from the step that needs it
│ ├── initialization-api.md
│ ├── rewarded-api.md
│ ├── interstitial-api.md
│ ├── banner-api.md
│ ├── ilrd-api.md
│ ├── privacy-settings.md
│ ├── ios-setup.md
│ ├── dependency-resolution.md
│ ├── testing-and-validation.md
│ ├── troubleshooting.md
│ ├── migration-sdk-9.md
│ └── best-practices.md
├── CHANGELOG.md
└── README.md
```

6 changes: 6 additions & 0 deletions skills/setup-vivox-voice-chat/evals/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Copy this file to .env and fill in your credentials:
# cp .env.example .env
#
# Get your LiteLLM API key from: https://uai-litellm.internal.unity.com
OPENAI_API_KEY=your-litellm-api-key-here
OPENAI_BASE_URL=https://uai-litellm.internal.unity.com
7 changes: 7 additions & 0 deletions skills/setup-vivox-voice-chat/evals/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# API keys - never commit
.env

# Promptfoo output
output/
promptfoo-output/
*.html
101 changes: 101 additions & 0 deletions skills/setup-vivox-voice-chat/evals/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
# Vivox Voice & Text Chat Skill Eval Suite

Evaluation suite for the `setup-vivox-voice-chat` skill, powered by [Promptfoo](https://www.promptfoo.dev/). Validates that the skill routes the model to the correct Vivox v16 APIs (no v4/legacy hallucinations) across init, channel join, and messaging.

## Prerequisites

- **Node.js** v18 or later
- A **LiteLLM API key** (from https://uai-litellm.internal.unity.com)

## Setup

### 1. Install Promptfoo

```bash
# Option A: install globally
npm install -g promptfoo

# Option B: use npx (no install needed)
npx promptfoo@latest eval
```

### 2. Configure your API key

```bash
cd evals/
cp .env.example .env
```

Open `.env` and set your personal LiteLLM key:

```
OPENAI_API_KEY=your-litellm-api-key-here
OPENAI_BASE_URL=https://uai-litellm.internal.unity.com
```

> **Important:** Never commit your `.env` file. It is already in `.gitignore`.

## Running the evals

All commands should be run from the `evals/` directory.

Use `-j 10` to run up to 10 eval requests concurrently.

### Run the full suite

```bash
promptfoo eval -j 10
```

### Run a specific test file

```bash
promptfoo eval --tests tests/init-and-login.yaml -j 10
promptfoo eval --tests tests/voice-channels.yaml -j 10
promptfoo eval --tests tests/text-chat.yaml -j 10
```

## Viewing results

### Terminal output

Results are printed to the terminal with pass/fail per assertion.

### Interactive web UI

```bash
promptfoo view
```

Opens a local UI (usually `http://localhost:15500`) for browsing results, filtering, and comparing runs.

## Assertions used

| Type | What it checks |
|---|---|
| `icontains` | Response contains a substring (case-insensitive), e.g. an exact Vivox API name |
| `not-icontains` | Response does NOT contain a substring (used to catch v4 legacy names like `Client.Instance`) |
| `llm-rubric` | An LLM judges whether the response meets a semantic requirement (e.g. correct init order) |

## Adding new tests

1. Create a new YAML file in `tests/`:

```yaml
- description: "Short description of what is being tested"
vars:
user_message: "The user request to test"
reference_content: "file://../references/your-reference.md" # optional
assert:
- type: icontains
value: "VivoxService.Instance.JoinGroupChannelAsync"
- type: not-icontains
value: "SendDirectedTextMessageAsync"
- type: llm-rubric
value: |
Describe the semantic requirement the response must meet.
```

2. Add the file to `promptfooconfig.yaml` under `tests:`.

3. Run it: `promptfoo eval --tests tests/your-new-test.yaml`.
32 changes: 32 additions & 0 deletions skills/setup-vivox-voice-chat/evals/promptfooconfig.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
description: "Vivox Voice & Text Chat Skill Eval Suite"

providers:
# Evaluated model: used by the test itself
- id: openai:chat:claude-sonnet-4-5
config:
max_tokens: 2048

prompts:
- id: eval-prompt
label: "Eval prompt"
raw: "{{skill_content}}\n\n{{reference_content}}\n\n{{custom_instructions}}\n\n## User Request\n\n{{user_message}}"

defaultTest:
options:
# Assertion judge: used by llm-rubric
provider: openai:chat:claude-sonnet-4-6
vars:
skill_content: file://../SKILL.md
reference_content: ""
custom_instructions: |
IMPORTANT:
- This is a planning eval. Do not emit MCP XML/tool-call tags.
- Refer to APIs with their exact names as documented in the provided skill and references. Do not invent or paraphrase symbol names.
- Do not mention tool names you will not call. If a step is inapplicable, explain the behavior without naming the omitted API.
- Always present the complete plan up front. If a step requires a user action, describe what you will do after it succeeds and what happens if it fails, in a single response.
- Answer only the step or phase requested by the user message. Do not include unrelated setup or migration content that was not asked for.

tests:
- file://tests/init-and-login.yaml
- file://tests/voice-channels.yaml
- file://tests/text-chat.yaml
76 changes: 76 additions & 0 deletions skills/setup-vivox-voice-chat/evals/tests/init-and-login.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
# ============================================================
# WORKFLOW: Init + Login — correct order and re-init guard
# ============================================================

- description: "Cold-start init: UGS Core -> Auth -> Vivox Init -> Vivox Login, in order"
vars:
user_message: |
I'm adding Vivox to a fresh Unity project. Walk me through
the initialization from an empty MonoBehaviour Start method.
reference_content: file://../references/init-and-login.md
assert:
- type: icontains
value: "UnityServices.InitializeAsync"
- type: icontains
value: "AuthenticationService.Instance.SignInAnonymouslyAsync"
- type: icontains
value: "VivoxService.Instance.InitializeAsync"
- type: icontains
value: "VivoxService.Instance.LoginAsync"
- type: llm-rubric
value: |
The response MUST describe the four initialization calls in this
exact order:
1. UnityServices.InitializeAsync
2. AuthenticationService.Instance.SignInAnonymouslyAsync
3. VivoxService.Instance.InitializeAsync
4. VivoxService.Instance.LoginAsync
Any other ordering (e.g. Vivox init before UGS init, or Login
before Vivox init) is a failure.
The response MUST NOT use v4 legacy patterns (Client.Instance,
ILoginSession, AccountId, ChannelId) as callable code. It is
fine — even helpful — to mention those names in a "don't use
these" warning or migration note; a failure is only when the
code samples or step-by-step instructions actually invoke them.

- description: "Login with display name: LoginOptions.DisplayName"
vars:
user_message: |
After Vivox is initialized, sign the player in with the display name
"Sunbeam" and enable text-to-speech.
reference_content: file://../references/init-and-login.md
assert:
- type: icontains
value: "LoginOptions"
- type: icontains
value: "DisplayName"
- type: icontains
value: "EnableTTS"
- type: icontains
value: "VivoxService.Instance.LoginAsync"
- type: llm-rubric
value: |
The response must construct a LoginOptions with DisplayName set to
"Sunbeam" and EnableTTS set to true, then pass it to
VivoxService.Instance.LoginAsync. It must not USE the v4 AccountId
or ILoginSession types as callable code (mentioning them in a
"don't use" warning is acceptable — failure is only when the code
actually invokes them).

- description: "Double-init must warn about VxErrorAlreadyInitialized (5041)"
vars:
user_message: |
My Start method runs every time the main scene reloads and I'm
seeing Vivox errors. How do I stop it from re-initializing?
reference_content: file://../references/init-and-login.md
assert:
- type: icontains
value: "5041"
- type: llm-rubric
value: |
The response must identify the underlying issue as
VivoxService.Instance.InitializeAsync being called more than once,
cite the 5041 VxErrorAlreadyInitialized error, and propose a fix
such as guarding with IsInitialized or making the bootstrap
object DontDestroyOnLoad. The fix must NOT be to catch and
swallow the exception.
Loading