关于 vrc-udon
vrc-udon 是用于使用 UdonSharp 编写 VRChat 世界脚本的开发技能,重点涵盖网络、所有权、同步,以及处理晚加入的玩家。
主要功能
- 01UdonSharp 语法与模式
- 02网络与变量同步
- 03所有权转移指导
- 04处理晚加入玩家的状态
- 05事件驱动的脚本通信
适用场景
- 01为 VRChat 世界编写 Udon 脚本
- 02在联网玩家间同步状态
- 03修改同步变量前处理所有权
- 04确保晚加入玩家看到正确世界状态
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ alexanderstephenthompson/ claude-hub --skill vrc-udon安装后在 Claude Code 中输入/vrc-udon确认已加载。
附带文件references/networking.mdassets/udon-checklist.md
详细介绍
VRChat Udon 技能
版本: 1.0 技术栈: VRChat SDK、UdonSharp
在添加网络功能之前,Udon 看起来就像常规的 Unity 脚本。之后,一切都会改变。未获取所有权就修改同步变量会悄无声息地失败——没有错误,没有警告,什么都不会发生。忘记调用 RequestSerialization,意味着更改永远不会离开你的设备。在编辑器中测试,完全无法发现网络错误,因为这里只有一名玩家。除非明确处理重新序列化,否则迟加入的玩家看到的会是默认状态,而不是当前状态。
这项技能中的每条规则,都是因为 Udon 的默认行为是悄无声息地失败。
范围和边界
此技能涵盖:
- UdonSharp 语法和模式
- 网络和同步
- 玩家交互
- 世界事件
- 常见的 Udon 行为
由其他技能负责:
unity-csharp:C# 模式和性能优化vrc-worlds:世界设置和优化
适用场景: 为 VRChat 世界编写 Udon 脚本。
核心原则
- 网络意识 — 每个同步变量都会占用带宽。
- 所有者模型 — 只有所有者才能修改同步变量。
- 迟加入玩家 — 必须确保之后加入的玩家也能获得正确状态。
- 本地与全局 — 明确区分哪些内容是本地的,哪些通过网络同步。
- 事件驱动 — 使用 SendCustomEvent,而不是轮询。
模式
基本 UdonSharp 脚本
using UdonSharp;
using UnityEngine;
using VRC.SDKBase;
using VRC.Udon;
public class MyBehavior : UdonSharpBehaviour
{
[UdonSynced] private bool _isActive;
public override void Interact()
{
// Take ownership before modifying synced var
Networking.SetOwner(Networking.LocalPlayer, gameObject);
_isActive = !_isActive;
RequestSerialization();
}
public override void OnDeserialization()
{
// Called when synced vars update from network
UpdateVisuals();
}
private void UpdateVisuals()
{
// Update based on _isActive state
}
}
所有权转移模式
public void TakeOwnershipAndModify()
{
// Always check and transfer ownership first
if (!Networking.IsOwner(gameObject))
{
Networking.SetOwner(Networking.LocalPlayer, gameObject);
}
// Now safe to modify synced variables
_syncedValue = newValue;
RequestSerialization();
}
支持迟加入玩家
[UdonSynced] private bool _doorOpen;
public override void OnPlayerJoined(VRCPlayerApi player)
{
// If we're owner, re-serialize state for the new player
if (Networking.IsOwner(gameObject))
{
RequestSerialization();
}
}
public override void OnDeserialization()
{
// Late joiners get current state here
SetDoorState(_doorOpen);
}
自定义事件通信
// Script A - sends event
public UdonBehaviour targetScript;
public void OnButtonPress()
{
targetScript.SendCustomEvent("HandleButtonPress");
}
// Script B - receives event
public void HandleButtonPress()
{
// Handle the event
}
// Network event (all players)
public void TriggerGlobalEvent()
{
SendCustomNetworkEvent(NetworkEventTarget.All, "OnGlobalEvent");
}
public void OnGlobalEvent()
{
// Runs on all players
}
反模式
| 反模式 | 问题 | 修复方法 |
|---|---|---|
| 未获取所有权就修改同步变量 | 悄无声息地失败 | 先调用 SetOwner,再修改 |
| 忘记调用 RequestSerialization | 更改无法同步 | 修改同步变量后务必调用 |
| 同步过多数据 | 网络延迟 | 尽量减少同步变量 |
| 使用 Update() 检查网络状态 | 浪费性能 | 使用 OnDeserialization 和事件 |
| 未处理迟加入玩家 | 加入者看到错误状态 | 玩家加入时重新序列化 |
检查清单
- 修改同步变量前已转移所有权
- 更改后已调用 RequestSerialization
- OnDeserialization 会更新所有视觉状态
- 已处理迟加入玩家(OnPlayerJoined + serialize)
- 全局触发器使用网络事件
- 同步变量数量尽可能少
参考资料
references/networking.md— Udon 网络、同步和所有权模式
资源
assets/udon-checklist.md— Udon 脚本开发检查清单
评论
支持 Markdown