Skip to content
Development
Skill

/unity-vrc-udon-sharp

Rules and references for VRChat UdonSharp on SDK 3.10.6, the active and verified target. UdonSharp compiles only a subset of C#, and its networking fails without an error, so load this skill before writing, reviewing, debugging, or migrating any UdonSharp or UdonBehaviour code,

From plugin
vrc-udon-skills
3684 skills1 hook

Claude Code

$ npx -y skills add niaka3dayo/agent-skills-vrc-udon --skill unity-vrc-udon-sharp --agent claude-code

SKILL.md

unity-vrc-udon-sharp.SKILL.md
name: unity-vrc-udon-sharp
description: >-
    Rules and references for VRChat UdonSharp on SDK 3.10.6, the active and verified target.
    UdonSharp compiles only a subset of C#, and its networking fails without an error, so load
    this skill before writing, reviewing, debugging, or migrating any UdonSharp or UdonBehaviour
    code, even a short script. Covers synced runtime state and ownership, NetworkCallable events,
    NetworkCalling.CallingPlayer and Udon network authorization, a local public helper or
    public-method audit, C# to Udon conversion, persistence, data containers, web loading,
    UdonSharp Assembly Version Defines, and runtime API access from Udon such as VRCTween calls,
    VRCQualitySettings, VRCBillboard, constraint source methods, PhysBone/Contact callbacks, and
    world VRCPhysBoneCollider runtime access. Not for scene setup, component setup, Build Panel
    work, layers, scene and rendering optimization, or upload; use unity-vrc-world-sdk-3 for those.
license: MIT
metadata:
    author: niaka3dayo
    version: "4.3.1"
    tags: vrchat, udonsharp, udon, networking, sync, persistence, dynamics, asmdef, vpm, assembly-definition

UdonSharp Skill

Why This Skill Matters

UdonSharp looks like regular Unity C# scripting — until you hit its hidden walls. Many standard C# features (`List<T>`, `async/await`, `try/catch`, LINQ, generics) **silently fail or refuse to compile** in code that runs in the Udon runtime. Editor-evaluated field initializers are a separate context: they can use some ordinary C# features to generate a final value that Udon can hold. Networking is even more treacherous: modifying a synced variable without ownership produces no error — it just does nothing. Forgetting `RequestSerialization` means your state changes never leave your machine. Standard single-player local testing gives zero signal about these networking bugs because there is only one player.

Every rule in this skill exists because UdonSharp's default behavior is to **fail silently**. Read the rule sheets in `rules/` before generating any code (see [Rules](#rules-read-before-generating-code)).

Before Writing Network Code

Four architectural decisions that must be made before choosing sync modes or writing any synced variable. Changing them mid-implementation typically requires a full rewrite:

  • **Who owns this state?** One owner writes; all others read. If two players can both write (e.g., a shared toggle), you need an ownership transfer protocol — writes without ownership are silently discarded.
  • **When does ownership transfer?** On grab? Interact? Game event? `OnPlayerLeft`? `Networking.SetOwner` is **locally immediate** on the calling client — `Networking.IsOwner(gameObject)` is `true` synchronously after the call, and writing `[UdonSynced]` fields plus `RequestSerialization()` immediately afterwards is safe under an `IsOwner` guard. Concurrent `SetOwner` calls from multiple clients are resolved by network arrival order — there is no client-side arbitration, so accept that the loser's write is overwritten.
  • **What do late joiners see?** State set only by one-time events (`SendCustomNetworkEvent`) is invisible to late joiners. Late-joiner-visible state must live in `[UdonSynced]` variables, which are delivered automatically via `OnDeserialization`; no manual `RequestSerialization()` on join is needed.
  • **What if the owner leaves mid-session?** VRChat automatically transfers ownership to a remaining player (selection rule is not publicly documented), and `OnOwnershipTransferred` fires on all clients. Synced variables are preserved, so state is not frozen; decide upfront whether to keep the current value, reset to a known default, or re-apply/re-broadcast derived state in `OnOwnershipTransferred`.

Core Principles

1. **Constraints First** — For Udon runtime code, assume standard C# features are blocked until verified. Treat Editor-evaluated field initializers separately and require a final Udon-supported value. Check `udonsharp-constraints.md` before using any API. 2. **Ownership Before Mutation** — Only the owner of an object can modify its synced variables. If the local player is not the owner, `SetOwner` first; then modify → `RequestSerialization` (Manual sync). 3. **Late Joiner Correctness** — State must be correct for players who join after events have occurred. Design for re-serialization, not just live updates. 4. **Sync Minimization** — Every synced variable costs bandwidth (see data budget in `udonsharp-sync-selection.md`). Derive what you can locally; sync only the source of truth. 5. **Event-Driven, Not Polling** — Use `OnDeserialization`, `[FieldChangeCallback]`, and `SendCustomEvent` instead of checking state in `Update()` **for state-change reactions; for hot-path or periodic work, see [Event Dispatch & Cross-Behaviour Call Cost Tiers](references/patterns-performance.md#event-dispatch--cross-behaviour-call-cost-tiers)**.

**Synced arrays: always apply them from `OnDeserialization()`**. Array element changes do not provide a reliable `FieldChangeCallback` signal, and the same guidance applies to same-length changes, array reassignments, and length changes. Have the owner call the same idempotent apply method immediately after mutation, then request Manual serialization once. If a revision guard protects a historical one-shot side effect, a late joiner's first `OnDeserialization()` receives the current revision and may otherwise replay that effect. Baseline the first received revision without the side effect, but run durable `ApplyValues()` before the baseline check; only later revisions should trigger the one-shot. Revision is not ordering or stale-packet protection.

Common Mistakes (NEVER List)

These Udon runtime and Unity serialization constraints cause either **compile-time failures** or **silent data errors**. Check this list before writing UdonSharp code or serialized initial values.

| # | NEVER do this | Why it fails silently | Use in

Read more
@niaka3dayo
Ships withvrc-udon-skills

Skills, rules, and validation hooks that teach AI coding agents to generate correct UdonSharp code

Stars on GitHub

Momentum

stars in total
368
Star history of niaka3dayo/agent-skills-vrc-udon on GitHub, a chart by star-history.com

Other skills on vrc-udon-skills.

release

release

Release procedure for agent-skills-vrc-udon: sync main into dev, bump the five version fields, open and merge the release PR,…

More skills from other plugins.

brainstorming
Auto-invoked

brainstorming

You MUST use this before any creative work - creating features, building components, adding functionality, modifying behavior, or…

@obra@obraInstall Skill
ask-matt

ask-matt

Ask which skill or flow fits your situation. A router over the skills in this repo.

skills2w309k
@mattpocock@mattpocockInstall Skill
accessibility
Auto-invoked

accessibility

Design, implement, and audit accessible UI to WCAG 2.2 Level AA across Web, iOS, and Android — semantic ARIA roles and labels,…

ecc2w293k
@affaan-m@affaan-mInstall Skill
compiler-commit

compiler-commit

Use when you want to verify compiler changes and commit with the correct convention. Runs tests, lint, and format, then commits…

react5d252k
@facebook@facebookInstall Skill

Questions about unity-vrc-udon-sharp.

Which coding agents can use unity-vrc-udon-sharp?
unity-vrc-udon-sharp installs in Claude Code, Codex, Cursor, Gemini CLI, GitHub Copilot, OpenCode and Windsurf with the skills CLI, using each agent's flag shown on this page. Flowy's auto-invocation, which fires a skill when your prompt matches, runs in Claude Code only.