mcpField
U
unity-vrc-udon-sharp

unity-vrc-udon-sharp

github.com/niaka3dayo开发3411.0k 次安装6 周前更新
代码仓库

关于 unity-vrc-udon-sharp

面向 VRChat 世界中 UdonSharp 编码的开发技能,说明运行时限制、同步状态所有权和晚加入者行为,帮助避免编译失败与无提示的网络错误。

主要功能

  1. 01Udon 运行时限制指南
  2. 02同步变量所有权规则
  3. 03晚加入者状态设计
  4. 04序列化与反序列化模式
  5. 05编辑器求值的初始化器指南

适用场景

  1. 01规划网络状态的所有权
  2. 02处理玩家晚加入时的状态
  3. 03避免在 Udon 运行时使用不支持的 C# 构造
  4. 04通过字段初始化器生成烘焙值

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/niaka3dayo/agent-skills-vrc-udon --skill unity-vrc-udon-sharp

安装后在 Claude Code 中输入/unity-vrc-udon-sharp确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

CHEATSHEET.md
LICENSE.txt
assets/templates/
ArrayUtils.cs
BasicInteraction.cs
BatchedSync.cs
CloggedRetrySync.cs
ContactReceiver.cs
CustomInspector.cs
DataPersistence.cs
DualCopySync.cs
EventBus.cs
MasterManagedPlayerPool.cs
PackedStateSync.cs
PlayerSettings.cs
RateLimitedSync.cs
StateMachine.cs
SyncedObject.cs
UdonSharpProgramAssetAutoGenerator.cs
UndoableGameManager.cs
hooks/
validate-udonsharp.ps1
validate-udonsharp.sh
references/
api.md
assembly-definitions.md
constraints.md
context-preservation.md
dynamics.md
editor-scripting.md
events.md
image-loading-vram.md
networking-antipatterns.md

详细介绍

UdonSharp 技能

为什么这项技能很重要

UdonSharp 看起来就像常规的 Unity C# 脚本编写,直到你撞上它隐藏的限制。许多标准 C# 功能(List<T>、async/await、try/catch、LINQ、泛型)在 Udon 运行时中运行的代码里会静默失败或无法编译。由编辑器求值的字段初始化器属于另一种上下文:它们可以使用某些普通 C# 功能来生成 Udon 能保存的最终值。网络同步则更容易出问题:修改同步变量时若不具有所有权,不会报错,只会什么也不做。忘记调用 RequestSerialization,意味着状态变化永远不会离开你的机器。标准的单人本地测试完全无法暴露这些网络同步错误,因为场景中只有一名玩家。

这项技能中的每条规则,都是因为 UdonSharp 的默认行为是静默失败。生成任何代码前,请先阅读规则。

编写网络代码前

在选择同步模式或编写任何同步变量之前,必须先做出四项架构决策。实现过程中途更改这些决策通常需要彻底重写:

  • 谁拥有此状态? 由一名所有者写入,其他人读取。如果两名玩家都能写入(例如,共享开关),就需要所有权转移协议——不具有所有权时的写入会被静默丢弃。
  • 何时转移所有权? 抓取时?交互时?游戏事件发生时?还是 OnPlayerLeft 时?调用 Networking.SetOwner 后,所有权会立即在本地生效——调用方客户端在该调用返回后同步执行 Networking.IsOwner(gameObject) 会得到 true;因此,在 IsOwner 检查的保护下,紧接着写入 [UdonSynced] 字段并调用 RequestSerialization() 是安全的。多个客户端并发调用 SetOwner 时,会按网络到达顺序处理——客户端之间不会进行仲裁,因此要接受落败一方的写入会被覆盖。
  • 迟加入者会看到什么? 仅通过一次性事件(SendCustomNetworkEvent)设置的状态,对迟加入者不可见。迟加入者可见的状态必须存储在 [UdonSynced] 变量中,这些变量会通过 OnDeserialization 自动传递;加入时无需手动调用 RequestSerialization()。
  • 所有者在会话中途离开怎么办? VRChat 会自动将所有权转移给一名剩余玩家(选择规则尚未公开说明),并在所有客户端触发 OnOwnershipTransferred。同步变量会保留,因此状态不会被冻结;请提前决定是保留当前值、重置为已知默认值,还是在 OnOwnershipTransferred 中重新应用/广播派生状态。

上下文保留

对于复杂的同步系统、与所有权相关的重构,或在压缩/交接后恢复的工作,可以考虑加载 references/context-preservation.md。 它提供了一份轻量级任务上下文记录,用于说明事实来源、传输方式、同步模式、存储、所有权、迟加入者行为以及验证依据。 这只是复杂工作的可选指导,并非小型机械式修改的步骤。 请勿在任何记录中放入私人数据或原始对话记录。

对于涉及世界场景设置,而非 UdonSharp 编译器限制的 VRChat SDK Build Panel 验证提醒、红色/黄色/白色警告或 Auto Fix 副作用,请使用 unity-vrc-world-sdk-3 并阅读 references/build-validation.md。

核心原则

  1. 约束优先 — 对于 Udon 运行时代码,在确认之前,先假设标准 C# 功能不可用。将由 Editor 计算的字段初始值设定项单独处理,并确保最终值受 Udon 支持。使用任何 API 前,请先检查 udonsharp-constraints.md。
  2. 修改前先取得所有权 — 只有对象的所有者才能修改其同步变量。始终按 SetOwner → 修改 → RequestSerialization 的顺序操作。
  3. 确保后来加入者状态正确 — 对于在事件发生后加入的玩家,状态也必须正确。应针对重新序列化进行设计,而不只是支持实时更新。
  4. 尽量减少同步 — 每个同步变量都会占用带宽(参见 udonsharp-sync-selection.md 中的数据预算)。能在本地推导的就本地推导;只同步唯一可信的数据源。
  5. 事件驱动,而非轮询 — 对于状态变化响应,请使用 OnDeserialization、[FieldChangeCallback] 和 SendCustomEvent,而不是在 Update() 中检查状态;对于热路径或周期性工作,请参见事件分发与跨行为调用开销等级。

同步数组:始终在 OnDeserialization() 中应用数组内容。数组元素的变化不会可靠地触发 FieldChangeCallback 信号;相同长度的内容变化、数组重新赋值和长度变化也遵循相同原则。让所有者在修改后立即调用同一个幂等的应用方法,然后只请求一次手动序列化。如果历史一次性副作用受版本号检查保护,后来加入者首次收到的 OnDeserialization() 会包含当前版本号,否则可能会重放该副作用。首次收到版本号时,应记录基准值而不触发副作用,但在检查基准值之前仍要运行持久化的 ApplyValues();只有后续版本号才应触发一次性操作。版本号不能用于排序或防止过期数据包。

SDK 3.10.4 事件接收器参数

SDK 3.10.5 是此 Skill 当前有效且已验证的目标版本。 SDK 3.10.4:UdonSharpBehaviour 直接实现 IUdonEventReceiver。 因此,需要接收器的 API 可以直接接收 this:

VRCStringDownloader.LoadUrl(dataUrl, this);

仍然必须提供接收器参数;只有在当前 SDK 中才不需要显式的 (IUdonEventReceiver) 强制转换。仅在历史迁移参考中保留任何 3.10.4 之前的强制转换。这符合官方 SDK 3.10.4 发布说明和 SDK 源代码声明。

公共字段:Inspector 可见性不等于持久化策略

[HideInInspector] 只会在 Inspector 中隐藏公共字段;Unity 仍会序列化该字段。当 Editor 时期的 DI、烘焙或自动装配必须将值持久化到场景/Prefab 中时,请使用 [HideInInspector] public。对于其他 UdonBehaviour 必须通过直接访问或 SetProgramVariable 访问的纯运行时值,请使用 [System.NonSerialized] public。有意使用 [HideInInspector] 时,请留下注释说明为何必须持久化该值。

编辑器求值的字段初始化器

字段初始化器会在 Unity/Editor 端作为普通 C# 代码求值,为编译后的 Udon 程序生成初始数据;其中的表达式不会在 Udon 运行时执行。初始化器中的 Random.Range 调用会在 Editor 中求值并存储为烘焙后的默认值,而不是运行时随机值。因此,即使 LINQ、lambda 或使用 List<T> 的同一行为静态辅助方法无法在 Start()、Interact() 或其他 Udon 运行时方法中使用,它们仍可用于生成数组初始化器。最终字段类型和值必须受 Udon 支持。生成过程应独立于场景、玩家和运行时状态,并且不要调用仅限主线程的 Unity API,因为字段初始化器和构造函数可能会在加载线程上运行。两种受支持的形式及其边界,请参阅 references/constraints.md。

仅对本地或每个客户端的随机性使用 Start() 或延迟初始化保护。对于对象或会话共享的种子/状态,由所有者生成并存储到 [UdonSynced] 字段中;使用 Manual 同步时,应先取得所有权,再写入并调用 RequestSerialization()。接收方可在需要时于 OnDeserialization() 中应用派生状态,但字段同步本身不要求使用此回调,且后来加入的用户会收到当前同步状态。

常见错误(绝对不要这样做)

这些 Udon 运行时和 Unity 序列化限制会导致编译时错误或静默数据错误。编写 UdonSharp 代码或序列化初始值之前,请先检查此列表。

#绝对不要这样做为什么会悄无声息地失败改用以下方式
1在 Udon 运行时代码中使用 List<T>、Dictionary<T,K> 或任何泛型集合编译错误——Udon 编译器会阻止此操作使用 T[] 数组、DataList、DataDictionary(DataDictionary.EnsureCapacity / 自定义容量要求 SDK 3.10.4+);上文提到的编辑器求值字段生成是有限的例外
2使用 async/await、System.Threading 或协程Udon 是单线程的;这些功能并不存在使用 SendCustomEventDelayedSeconds()
3在不拥有对象的情况下修改 [UdonSynced] 字段更改看起来已在本地生效,但会在下一次反序列化时悄然还原修改前调用 Networking.SetOwner(),然后调用 RequestSerialization()
4修改同步字段(Manual 同步)后忘记调用 RequestSerialization()状态更改永远不会离开本地客户端——没有错误,也没有警告修改 [UdonSynced] 字段后务必调用 RequestSerialization()
5使用 try/catch/finally/throw编译错误——异常处理会被阻止进行防御性空值检查并提前返回
6在字段初始化器中访问 Networking.LocalPlayer编辑器端初始值生成时没有玩家或 Udon 运行时状态在 Start() 中初始化,或使用延迟初始化保护
7使用 static 字段保存每个实例的状态同一客户端上的所有实例会共享静态字段,且这些字段不会同步需要同步时,使用带有 [UdonSynced] 的实例字段
8在 Manual 同步中每帧调用 RequestSerialization()会耗尽约 11 KB/s 的网络带宽预算,导致整个世界发生拥塞通过变更检测将频率限制在 1-10 Hz;检查 Networking.IsClogged
9在 Udon 运行时代码中使用 LINQ(.Where、.Select 等)或 lambda 表达式编译错误——Udon 编译器不支持使用带命名方法的手动 for 循环;上文提到的编辑器求值字段生成是有限的例外
10使用 Button.onClick.AddListener()Udon 不提供此功能——不支持运行时委托在 Inspector OnClick 中配置 SendCustomEvent
11在一个行为中混用 Continuous 和 Manual 同步相关逻辑会浪费带宽(Continuous 同步离散值),或失去控制(Continuous 中多余的 RequestSerialization)分开使用不同的行为:位置/旋转使用 Continuous,离散状态使用 Manual
12在没有 IsOwner 保护的情况下写入 [UdonSynced] 字段非所有者的写入仅在本地生效,并会在下一次从实际所有者反序列化时悄然还原如有需要,先调用 Networking.SetOwner(本地立即生效),然后在 IsOwner 条件下写入并调用 RequestSerialization()
13在低于 3.8.1 的不受支持 SDK 上使用 [NetworkCallable](仅限历史迁移)编译错误——该属性和带参数的网络事件 API 不可用使用当前 SDK 目标版本 3.10.5;对于历史迁移说明,请改用同步变量,并在 OnDeserialization/FieldChangeCallback 中响应,而不是将其与网络事件配对使用
14在低于 3.10.0 的不受支持 SDK 上使用 PhysBones/Contacts API(OnPhysBoneGrabbed、OnContactEnter 等)(仅限历史迁移)可以编译,但在运行时会被悄然忽略——3.10.0 之前不存在世界端 Dynamics,因此回调永远不会触发使用当前 SDK 目标版本 3.10.5;对于历史迁移,请确认项目使用的 SDK 至少为 3.10.0
15在低于 3.7.4 的不受支持 SDK 上使用 PlayerData 持久化 API(仅限历史迁移)编译错误——缺少符号;PlayerData、PlayerObject 和 OnPlayerRestored 是在 3.7.4 中添加的,在此之前不属于 Udon 白名单使用当前 SDK 目标版本 3.10.5;对于历史迁移,请确认项目使用的 SDK 至少为 3.7.4
16在 UdonSharpBehaviour 外使用 Unity .asmdef,却没有匹配的 U# Assembly DefinitionUnity 会编译 C# 程序集,但 UdonSharp 会报告该脚本不属于 U# 程序集对于简单的世界脚本,避免使用 asmdef;对于包/asmdef 工作流,请创建对应的 U# Assembly Definition,并将 Source Assembly 设置为 Unity .asmdef(参见 references/assembly-definitions.md)
17创建 .cs 脚本,却没有对应的 .asset 文件脚本不会被识别为 UdonBehaviour——出现“The associated script cannot be loaded”错误,且不会进行 Udon 编译每次创建 .cs 时:确认 Assets/Editor/UdonSharpProgramAssetAutoGenerator.cs 存在;若缺失,请按照 references/editor-scripting.md 安装,并通知用户(参见 rules/udonsharp-constraints.md 中的规则 8)
18在 Update()、PostLateUpdate() 或任何逐帧事件中调用 Debug.Log()VRChat 的客户端日志速率限制器会悄然丢弃超出的日志条目;每帧隐式分配字符串会造成持续的 GC 压力,导致帧率骤降。ClientSim 和 Unity Editor 会掩盖这两种问题使用 if (debugMode && Time.frameCount % 60 == 0) 添加保护条件,或将所有日志移到事件驱动的回调中
19在 GameObject、Transform、UdonBehaviour 或任何组件引用上使用 [UdonSynced]只有基本类型、值类型(Vector3、Quaternion、Color 等)、string、VRCUrl 及其简单数组可以同步。组件引用会因 SDK 版本不同而导致编译失败或永远不会被序列化同步玩家 ID(int)或场景对象索引(int),并在每个客户端本地解析实际引用
20使用 VRCUrl.Empty 初始化任何需要独立初始值的 UdonSharp VRCUrl 字段VRCUrl.Empty 是共享实例,因此 Inspector 数据可能会在使用同一 UdonSharp 程序的字段、数组元素或 GameObject 之间泄漏为 [SerializeField]、[UdonSynced] 和普通私有字段,以及每个数组元素,分别设置其自己的 new VRCUrl("");仅将 VRCUrl.Empty 用作运行时哨兵值

同步模式快速决策

Changing every frame (position, rotation)?    -> Continuous sync
Changing on user action (toggle, score)?      -> Manual sync + RequestSerialization()
No sync needed (local UI, effects)?           -> NoVariableSync
Need reliable one-shot calls with params?     -> [NetworkCallable] (introduced in SDK 3.8.1; active target 3.10.5)
Temporary effect for all players, no state?   -> SendCustomNetworkEvent (no synced vars)

如需查看详细决策树、数据预算和最小化原则,请参阅 rules/udonsharp-sync-selection.md。

3.8.1 之前的 SDK 未定义 NetworkCallable 特性或带参数的网络事件 API,因此使用这些功能的代码通常会编译失败。

[NetworkCallable] 方法必须返回 void。

同步调试快速决策

当同步“在本地看起来正确,但对其他人不起作用”时:

Remote players don't see my state change?
  ├── Did I call RequestSerialization() after writing? (Manual sync) → Add it
  ├── Does the local player own the object?                          → Networking.SetOwner() first
  └── Using Continuous sync for button/toggle state?                → Switch to Manual + RequestSerialization()

RequestSerialization() called but still not syncing?
  ├── Is Networking.IsClogged == true?           → Throttle; retry after delay
  └── Non-owner writing the field?               → Acquire ownership first — a non-owner RequestSerialization() is a silent no-op (see NEVER #12)

Late joiners don't see current state?
  ├── State set only on event (e.g., player trigger)?  → Verify the state lives in a [UdonSynced] field — synced values are delivered to late joiners automatically; SendCustomNetworkEvent calls before join are never replayed
  └── Using SendCustomNetworkEvent for persistent state? → Use [UdonSynced] variables instead

OnOwnershipTransferred not firing on a remote client?
  └── On the caller, the callback fires synchronously inside SetOwner — confirm the calling client called Networking.SetOwner(LocalPlayer, gameObject), and that remote clients resolve the same gameObject reference (scene path or prefab GUID)

参考资料加载指南

只加载所需内容。加载过多会浪费 token;加载不足则会导致关键错误。

任务必须阅读可选不要加载
编写网络/同步代码networking.md、networking-antipatterns.mdnetworking-bandwidth.md、sync-examples.mddynamics.md、web-loading.md、image-loading-vram.md
构建 UI/菜单patterns-ui.md、events.mdpatterns-core.md、api.mdnetworking-bandwidth.md、dynamics.md、web-loading.md
实现持久化(保存/加载)persistence.mdpatterns-networking.md、events.mddynamics.md、web-loading.md、image-loading-vram.md
从 Web 下载字符串/图像web-loading.mdweb-loading-advanced.md、image-loading-vram.mddynamics.md、persistence.md、networking-bandwidth.md
使用 VRCTween、可取消的延迟调用或补间清理vrctween.mdpatterns-utilities.md、api.mddynamics.md、web-loading.md、persistence.md
使用 PhysBones/Contacts/Constraints、Box Contacts、Global Avatar PhysBone Colliders 或世界中的 VRCPhysBoneCollider Udon 访问dynamics.md、events.mdpatterns-networking.md、api.mdweb-loading.md、image-loading-vram.md、persistence.md
在运行时读取/写入 VRCQualitySettingsapi.mdevents.md;场景默认值:unity-vrc-world-sdk-3networking.md、dynamics.md、web-loading.md
调整 DataList/DataDictionary 容量或使用 DataDictionary.EnsureCapacityapi.mdconstraints.md、patterns-utilities.md、web-loading.mddynamics.md、persistence.md、networking-bandwidth.md
优化性能(Update 循环)patterns-performance.mdpatterns-utilities.md、api.mddynamics.md、web-loading.md、persistence.md
构建视频播放器patterns-video.mdevents.md、web-loading.mddynamics.md、persistence.md、image-loading-vram.md
调试/故障排除troubleshooting.mdconstraints.md、networking.md、testing.mdpatterns-*.md、dynamics.md、web-loading.md
调试所有权/同步冲突networking.md、troubleshooting.mdnetworking-antipatterns.mddynamics.md、web-loading.md
在 SDK 版本间迁移/修复升级后的问题sdk-migration.mdtroubleshooting.md、networking.md、dynamics.mdweb-loading.md、image-loading-vram.md
在压缩/交接/所有权敏感的多文件重构后恢复复杂工作当前任务的主要参考资料context-preservation.md不相关领域的参考资料
编写新的 UdonSharp 脚本(不确定是否需要同步)constraints.mdnetworking.mddynamics.md、web-loading.md、image-loading-vram.md
设置新的脚本文件(.cs/.asset 连接、程序资源生成)editor-scripting.mdtroubleshooting.mdnetworking.md、dynamics.md
VPM/包/asmdef 工作流、Assembly Version Defines、U# Assembly Definition 连接、Auto Referenced 决策assembly-definitions.mdeditor-scripting.md、troubleshooting.mdnetworking.md、dynamics.md、web-loading.md
构建编辑器设置工具/放置 UX(自定义检查器、场景连接辅助工具、IEditorOnly)editor-scripting.mdconstraints.md、assembly-definitions.mdnetworking.md、dynamics.md、web-loading.md

模式选择指南

六个模式文件涵盖不同领域。使用以下快速指引选择合适的文件:

Building a UI, menu, or HUD?           -> patterns-ui.md
VR finger/touch interaction on Canvas? -> patterns-ui.md
Modular app with multiple screens?     -> patterns-ui.md
Syncing state across players?           -> patterns-networking.md
Multiple identical rooms from one model? -> patterns-networking.md (distant-room)
Optimizing Update() or heavy loops?     -> patterns-performance.md
Heavy rebuild, replay, or reset/cancel?  -> patterns-performance.md
Playing or streaming video?             -> patterns-video.md
Need array helpers, event bus, or       -> patterns-utilities.md
  pseudo-delegates?
Basic interactions, timers, audio,      -> patterns-core.md
  pickups, or teleportation?
Station + trigger zone detection?       -> troubleshooting.md

涉及多个方面?加载主要模式文件及其依赖项。例如,同步视频播放器需要同时使用 patterns-video.md 和 patterns-networking.md。

模板选择指南

17 个模板涵盖常见起点。选择最接近的模板并进行调整:

起点模板主要特性
交互与对象
可交互对象(点击/使用)BasicInteraction.cs冷却、切换、音频反馈
同步切换/共享对象SyncedObject.cs所有权保护、FieldChangeCallback、加入较晚的玩家初始化
每位玩家的移动设置PlayerSettings.cs通过触发区域设置行走/奔跑/跳跃速度
基于接触的碰撞检测ContactReceiver.csOnContactEnter/Exit、头像与世界对象区分、防抖(在 SDK 3.10.0 中引入;当前目标版本为 3.10.5)
状态与游戏逻辑
状态机/游戏流程StateMachine.cs定时转换、同步状态、确保加入较晚的玩家安全
支持撤销/历史记录的游戏UndoableGameManager.csbyte[] 历史记录、NetworkCallable _OwnerProcessMove/_OwnerUndo/_OwnerReset
对象池(玩家槽位)MasterManagedPlayerPool.csFIFO 环形缓冲区、由主控管理、OnPlayerJoined/Left
持久化与数据
保存/加载玩家数据DataPersistence.csPlayerData API、OnPlayerRestored、自动保存(在 SDK 3.7.4 中引入;当前目标版本为 3.10.5)
网络模式
限速同步(拖动滑块)RateLimitedSync.cs0.15s 冷却、最后写入优先
批量同步(快速事件)BatchedSync.cs幂等调度、0.2s 延迟、单个数据包
拥塞感知重试CloggedRetrySync.csIsClogged 检查、线性退避、MaxRetries
本地副本与同步副本并存DualCopySync.cs本地工作副本 + 同步传输、脏标记
将多个值打包到一个字段PackedStateSync.cs在一个 Vector3 中打包 3 个整数,减少同步开销
实用工具
数组辅助工具(List<T> 的替代方案)ArrayUtils.cs为数组提供 Add、Remove、Contains、FindIndex、Shuffle
事件总线(发布/订阅)EventBus.cs订阅者列表(最多 32 个)、RegisterListener/RaiseEvent
自定义编辑器检查器CustomInspector.csUdonSharpGUI、Undo、代理同步
为新脚本自动生成 .assetUdonSharpProgramAssetAutoGenerator.csAssetPostprocessor、仅域重载时运行、自动编译

有多个需求? 从最符合主要需求的模板开始,再从其他模板中选取模式。例如,支持撤销的同步游戏需要以 UndoableGameManager.cs 为基础,并加入 RateLimitedSync.cs 中用于限流的模式。

规则(约束与网络)

编译约束和网络规则定义在始终加载的规则中:

规则文件内容
rules/udonsharp-constraints.md受限功能、代码生成规则、特性、可同步类型
rules/udonsharp-networking.md所有权、同步模式、RequestSerialization、NetworkCallable、网络事件发送者授权
rules/udonsharp-sync-selection.md同步模式选择、数据预算、最小化原则

安装后,将这些文件放入 Agent 的规则目录,以便自动加载。

SDK 版本

当前支持/最后验证版本:SDK 3.10.5

从 v4.0.0 起,策略是仅支持最新稳定版 SDK;只有在本仓库验证新的稳定版后,支持版本才会更新。新稳定版不会自动获得支持。目前最后验证的目标版本:3.10.5。

下表保留了功能引入历史,供迁移参考。SDK 3.7.1-3.10.4 的条目仅为历史信息;它们不是此 Skill 当前支持或验证的目标版本。这是此 Skill 的支持范围,并不代表 VRChat 自身的 SDK 政策。除非参考资料明确标注为历史迁移案例,否则主要生成示例均以 SDK 3.10.5 为目标。

SDK 版本主要功能状态
3.7.1新增 StringBuilder、RegularExpressions、System.Random历史版本
3.7.4新增 Persistence API(PlayerData/PlayerObject)历史版本
3.7.6多平台构建与发布(同时支持 PC + Android)历史版本
3.8.0PhysBone 依赖项排序、Drone API(VRCDroneInteractable)历史版本
3.8.1[NetworkCallable] 特性、带参数的网络事件、NetworkCalling.CallingPlayer/.InNetworkCall、NetworkEventTarget.Others/.Self历史版本
3.9.0Camera Dolly API、简化 Auto Hold 拾取功能历史版本
3.10.0VRChat Worlds 动态系统(PhysBones、Contacts、VRC Constraints)历史版本
3.10.1错误修复与稳定性改进历史版本
3.10.2EventTiming 扩展、PhysBones 修复、着色器时间全局变量历史版本
3.10.3VRCPlayerApi.isVRCPlus、VRCRaycast(Avatar)、Mirror 渲染顺序修复历史版本
3.10.4VRCTween、盒形 Contacts、全局 Avatar PhysBone Colliders、世界中的 VRCPhysBoneCollider Udon 访问、DataList/DataDictionary 自定义容量、DataDictionary.EnsureCapacity、UdonSharpBehaviour 实现 IUdonEventReceiver 并接受直接接收器 this历史版本
3.10.5WorldQualitySettings、可写的 VRCQualitySettings、Assembly Version Defines、Pickup Outline Renderers、Pipeline Manager 验证当前支持/最后验证

发布时请使用 SDK 3.10.5。依赖特定版本的 API 或迁移步骤前,请查看对应版本的发行说明。

官方资源

资源URL内容
VRChat Creatorscreators.vrchat.com/worlds/udon/官方 Udon/SDK 文档
UdonSharp 文档udonsharp.docs.vrchat.comUdonSharp API 参考
VRChat 论坛ask.vrchat.com问答与解决方案
VRChat Cannyfeedback.vrchat.com错误报告、已知问题
GitHubgithub.com/vrchat-community示例与库

参考资料

文件内容搜索提示
constraints.mdUdonSharp 中 C# 功能的可用性;受限功能;可同步类型;属性;DataList 与数组的选择指南;DataList/DataDictionary 容量 API;高级变通方案(object 数组伪结构体);可同步的 VRCUrl 列表List、async、try/catch、LINQ、generics、DataList、DataDictionary、DataList capacity、DataDictionary capacity、EnsureCapacity、DataList vs array、when to use DataList、VRCUrl array、VRCUrl sync、pseudo-struct、object array cast、multi-field state container
networking.md所有权模型、同步模式、RequestSerialization、NetworkCallable、网络事件发送者授权、数据限制UdonSynced、SetOwner、BehaviourSyncMode、FieldChangeCallback、OnDeserialization、NetworkCalling、CallingPlayer、InNetworkCall、legacy event、underscore、authorization、master leave、ownership cascade
networking-bandwidth.md带宽节流、位打包、同步数据大小示例、调试、以所有者为中心的架构IsClogged、bandwidth、throttle、bit packing、data budget、IsMaster
networking-antipatterns.md应避免的 6 种反模式;附模板链接的 5 种高级同步模式anti-pattern、race condition、ownership fight、late-joiner、PackedStateSync、BatchedSync
persistence.md存储层决策树(本地/同步/PlayerData/PlayerObject);PlayerData/PlayerObject API(在 SDK 3.7.4 中引入;当前目标版本为 3.10.5);每位玩家的保存数据;存储用量查询 API(在 SDK 3.10.0 中引入;当前目标版本为 3.10.5)storage layer、decision tree、local variable、PlayerData、PlayerObject、OnPlayerRestored、SetInt、TryGetInt、GetPlayerDataStorageUsage、GetPlayerDataStorageLimit、GetPlayerObjectStorageUsage、GetPlayerObjectStorageLimit、RequestStorageUsageUpdate、OnPersistenceUsageUpdated、storage quota、storage usage、which storage、when to use PlayerData
dynamics.mdPhysBones、Contacts、VRC Constraints(在 SDK 3.10.0 中引入;当前目标版本为 3.10.5);VRCTween、盒形 Contacts、全局 Avatar PhysBone 碰撞体、通过 Udon 访问 world VRCPhysBoneCollider(SDK 3.10.4+)PhysBone、ContactReceiver、ContactSender、Box Contact、Global Avatar PhysBone Collider、VRCPhysBoneCollider、VRCTween、VRCConstraint、OnContactEnter
patterns-core.md初始化、交互、玩家检测、计时器、音频、拾取、动画、UI、传送、延迟初始化保护、远程玩家Interact、OnEnable、Initialize、AudioSource、VRCPickup、Animator、UI、TeleportTo、remote players、_GetRemotePlayers、exclude local player、FindAll alternative
patterns-networking.md对象池、NetworkCallable 发送者验证模式、持久化集成、动态交互、同步游戏状态、远距离房间伪多房间(状态/呈现分离、自有或由主玩家协调的会话仲裁)、延迟事件去抖、用于数组同步的字符串拼接pool、MasterManagedPlayerPool、NetworkCallable、CallingPlayer、InNetworkCall、sender authorization、DamageReceiver、game state、distant room、pseudo multi-room、room assignment、roomIndex、LocalRoomPresenter、RoomAssignment、NoVariableSync、TeleportTo per-client、debounce、state machine、string join、array sync、paragraph separator、U+2029
patterns-performance.mdpartial class 模式、更新处理程序、PostLateUpdate、空间查询、平台优化、帧预算 Stopwatch、繁重处理架构(重建、重放、重置/取消)、速率限制解析器、GameObject 查找成本等级Update、PostLateUpdate、Bounds、AnimatorHash、performance、mobile、PC、Stopwatch、frame budget、SendCustomEventDelayedFrames、heavy processing、rebuild、replay、reset、cancel、operation log、authoritative data、derived state、cursor rebuild、rate limit、URL scheduler、video load queue、GameObject.Find、Find cost、lookup cost tier、SerializeField vs Find、silent failure on rename、SendCustomEvent cost、cross-behaviour call、EventBus hot path、delayed loop spike、public method lookup、event dispatch tier
patterns-utilities.md数组辅助工具(List 替代方案)、事件总线、GameObject 中继通信、伪结构体双重转换、抽象类回调、可取消的延迟事件、重入保护、UdonEvent 伪委托ArrayUtils、EventBus、relay、subscriber、FindIndex、ShuffleArray、object array、pseudo struct、double cast、abstract class、callback、interface alternative、cancellable timer、re-entrance、emitting guard、UdonEvent、pseudo delegate
patterns-ui.mdUI/Canvas 模式:防止移动保护、适配 Avatar 缩放的 UI、响应 FOV 的定位、适配平台的布局、动态玩家列表、滚动输入抽象、查找表本地化、Toggle-Animator 桥接、通过 PlayerObject 持久化设置、基于监听器的菜单事件、手指触摸交互、模块化应用架构Canvas、UI、menu、Immobilize、avatar scale、FOV、platform、Quest、VR、desktop、player list、scroll、localization、language、Toggle、Animator、PlayerObject、settings、persistence、listener、broadcast、finger touch、fingertip、haptic、FingerPointer、FingerTouchCanvas、touch canvas、app architecture、AppModule、AppManager、plugin lifecycle、CanvasGroup transition
patterns-video.md视频播放器状态机、基于服务器时间的播放同步、新加入玩家同步、AVPro Blit 缓冲、出错后重试并回退、同步播放列表/队列、按平台选择 URLvideo player、AVPro、VRCUnityVideoPlayer、BaseVRCVideoPlayer、playback sync、server time、GetServerTimeInMilliseconds、late joiner、VRCGraphics.Blit、OnVideoReady、OnVideoError、retry、fallback、playlist、queue、shuffle、repeat、Quest URL
web-loading.md字符串/图片下载、VRCJson、受信任的 URLVRCStringDownloader、VRCImageDownloader、VRCJson、DataDictionary、VRCUrl
image-loading-vram.md图片加载的高级 VRAM 管理:Destroy 与 Dispose、双缓冲渐隐、stock 模式、mipmap 偏差VRAM、texture memory、memory leak、Destroy、Dispose、double buffer、fade、mipmap、TextureInfo
web-loading-advanced.md高级数据加载:通过 StringDownloader 嵌入 Base64 纹理、跨平台压缩、URL 双键索引、LRU 解码缓存Base64、LoadRawTextureData、StringDownloader texture、DXT1、ETC_RGB4、UNITY_ANDROID、LRU cache、packed resources、binary format
api.mdVRCPlayerApi、Networking、NetworkCalling 发送者上下文、枚举参考、VRCObjectPool 方法及由 Interact 驱动的所有权模式GetPlayers、playerId、isMaster、isLocal、GetPosition、SetVelocity、NetworkCalling、CallingPlayer、InNetworkCall、Drone、VRCDroneApi、VRCObjectPool、TryToSpawn、Return、Shuffle、pool owner、Interact pool、pool forwarded spawn、pool ownership transfer
events.md所有 Udon 事件(包括 OnPlayerRestored、OnContactEnter)OnPlayerJoined、OnPlayerLeft、OnPlayerTriggerEnter、OnOwnershipTransferred、OnControllerColliderHitPlayer、CharacterController、OnMasterTransferred、OnAvatarChanged、OnSpawn、VRC Economy、OnPurchaseConfirmed、OnAsyncGpuReadbackComplete
editor-scripting.md编辑器脚本、代理系统、自定义检查器、仅限编辑器的设置组件(IEditorOnly)、构建流程回调,以及 UdonSharpProgramAsset 自动生成UdonSharpEditor、UdonSharpBehaviourProxy、SerializedObject、UdonSharpProgramAsset、auto-generate、AssetPostprocessor、.asset missing、IEditorOnly、EditorOnly tag、setup helper、setup component、build exclusion、custom inspector、ContextMenu、IVRCSDKBuildRequestedCallback、OnBuildRequested、build callback、IPreprocessCallbackBehaviour、OnPreprocess
assembly-definitions.mdUdonSharp 程序集定义、Unity .asmdef 与 U# Assembly Definition、VPM 包工作流、Runtime/Editor 分离,以及 Auto Referenced 的权衡Version Defines、VRC_ENABLE_、asmdef、Assembly Definition、U# Assembly Definition、Source Assembly、VPM package、Auto Referenced、Runtime、Editor、package layout、prefab-first、code-integration API
sync-examples.md同步模式示例(Local/Events/SyncedVars)Continuous、Manual、NoVariableSync、sync example
troubleshooting.md常见错误及解决方案NullReference、compile error、sync not working、FieldChangeCallback、VRCStation、seated player、trigger zone、OnPlayerTriggerEnter not firing、station collider、position polling、OnStationEntered
sdk-migration.mdSDK 迁移指南(3.7 至 3.10)、逐版本变更与检查清单migration、deprecated、upgrade、3.7、3.8、3.9、3.10
testing.md测试与调试指南:ClientSim 编辑器测试、Build and Test(单客户端和多客户端)、Debug.Log 模式、发布前清理、测试清单ClientSim、Build and Test、multi-client、late joiner test、debug、Debug.Log、ownership test、sync test、testing checklist
context-preservation.md上下文保留指南:在上下文压缩/交接期间记录特定任务的设计意图(真实来源、同步策略、所有权、新加入玩家的行为、验证);最简任务上下文说明;隐私指南;恢复工作检查清单context preservation、design intent、compaction、handoff、resume、task context note、why this design、ownership rationale、design-context loss

模板(assets/templates/)

模板用途
BasicInteraction.cs带有 Interact() 处理程序的可交互对象
SyncedObject.cs网络同步对象(手动同步、所有权检查、晚加入者初始化标记)
PlayerSettings.cs每位玩家的移动设置(行走/奔跑/跳跃速度)
StateMachine.cs带有同步状态和状态转换的状态机
DataPersistence.csPlayerData 保存/加载及 OnPlayerRestored(在 SDK 3.7.4 中引入;当前目标版本为 3.10.5)
ContactReceiver.cs用于检测世界侧碰撞的接触接收器(在 SDK 3.10.0 中引入;当前目标版本为 3.10.5)
CustomInspector.cs使用 UdonSharpEditor 的自定义编辑器检查器
MasterManagedPlayerPool.cs用于非安全性会话仲裁的主控玩家对象池;FIFO 环形缓冲区;OnPlayerJoined/Left;主控权移交后执行 _VerifyAssignments
EventBus.cs订阅者列表事件总线(最多 32 个监听器);RegisterListener/UnregisterListener/RaiseEvent;原地压缩
ArrayUtils.csList<T> 的替代方法:针对 GameObject[] 的 Add、Contains、AddUnique、Remove、RemoveAt、Insert;针对 int[] 的 FindIndex/ShuffleArray
UndoableGameManager.cs使用 byte[] 状态历史记录进行历史/撤销同步;NetworkCallable _OwnerProcessMove/_OwnerUndo/_OwnerReset
PackedStateSync.cs将 3 个整数打包到一个 Vector3 UdonSynced 字段中;OnPreSerialization/OnDeserialization
RateLimitedSync.cs0.15 秒同步冷却时间,使用 _syncLocked/_changeCounter;_OnSyncUnlock 回调
DualCopySync.cs本地副本与同步副本,带有 _dirty 标记;严格区分 OnPreSerialization/OnDeserialization
BatchedSync.cs幂等的 ScheduleBatchedSync,BatchDelay 为 0.2 秒;_FlushBatch 延迟回调
CloggedRetrySync.cs检查 Networking.IsClogged;线性退避(RetryDelay * retryCount);MaxRetries=5
UdonSharpProgramAssetAutoGenerator.cs为新脚本自动创建 UdonSharpProgramAsset 的 AssetPostprocessor

钩子

钩子平台用途
validate-udonsharp.ps1Windows(PowerShell)PostToolUse 约束验证
validate-udonsharp.shLinux/macOS(Bash)PostToolUse 约束验证

Bash 验证器需要 jq。如果该工具不可用,钩子会原样传递输入,并输出 VALIDATOR-WARNING: validation skipped (JQ_UNAVAILABLE),而不是悄悄地报告验证成功。

快速参考

  • CHEATSHEET.md - 单页快速参考

评论

支持 Markdown