语言支持

现在能编译哪些写法,以及 Udon 永远无法运行的那部分 C#。

更新于 2026-09-03

Udonite 能编译日常 C# 中相当大的一部分。下面列出的每一项都有测试覆盖:这些测试会汇编输出,并在真正的 Udon 虚拟机上运行。

能编译的部分

类型与成员

class struct interface enum 嵌套类型 把自己的类用作字段和局部变量 带约束的泛型 带默认实现的接口方法 属性 自动属性 表达式体成员 索引器 扩展方法 params 可选参数 命名参数 out / ref 参数 元组与解构 局部函数 静态工具类

record 和 record struct:位置构造、with、值相等性、ToString、解构。静态字段必须是 constreadonly(见下文)。

语句与表达式

if switch 语句 switch 表达式 for foreach while do break continue 模式匹配 类型模式 is not null 关系模式 属性模式 when 守卫 ?. ?? ??= 带格式说明符的字符串插值 nameof 算术运算符 位运算符 移位运算符 [Flags] 枚举 HasFlag char 运算 数组 多维数组 范围与索引 Array.Sort Find FindAll Exists IndexOf Resize Copy Fill ConvertAll List<T> Dictionary<K,V> HashSet<T> Queue<T> Stack<T> LINQ Action / Func 字段 方法组 多播 += / -= C# event 指向另一个 behaviour 上 public 方法的委托 作为值的 lambda StringBuilder string.Format Split Join Substring Replace Trim PadLeft 可空值类型 HasValue GetValueOrDefault

关系模式写作 is > 5 and < 10。范围与索引指 arr[^1]arr[1..3]。LINQ 可以用在数组、列表和字典上:SelectWhereOrderByThenByGroupByFirstAnyAllSumAverageMinMaxCountTakeSkipTakeWhileSkipWhileDistinctReverseConcatZipUnionIntersectExceptSequenceEqualToArrayToListToDictionaryRangeRepeat,以及它们的链式组合。传给 LINQ 以及 List<T>Array 辅助方法的 lambda 会在调用处内联展开。方法组写作 Action done = Cleanup;。指向另一个 behaviour 上 public 方法的委托,以及作为值的 lambda,两者都能编译;会捕获变量的 lambda 有一条限制,下文会说明。

Unity 与 VRChat

GetComponent<T>() TryGetComponent<T>(out T) Instantiate Destroy SetActive Transform 物理查询 Mathf Vector3 Quaternion Color Random Time 协程 yield return null WaitForSeconds WaitUntil 嵌套协程 StartCoroutine(Run()) StartCoroutine(nameof(Run)) StopAllCoroutines Invoke InvokeRepeating CancelInvoke async 方法 Task UniTask UniTaskVoid await VRCPlayerApi Networking 拾取物 座位 UdonBehaviour 引用 SendCustomEvent SetProgramVariable GetProgramVariable<T>

InvokeInvokeRepeatingCancelInvoke 可以用在 public 方法上。async 方法可以返回 voidTaskUniTaskUniTaskVoid,可以 await Task.Delay(...),也可以等待其他 async 方法。网络一页中的全部内容。

Udon 永远无法运行的部分

这些会被 UDN0011 拒绝。提示信息会说明原因,并给出替代写法。

写法 原因,以及应该改写成什么
trycatchthrow Udon 没有异常机制。请先判断条件。
可变的 static 字段 每个 behaviour 都有自己的堆,所以静态字段会变成「每个 behaviour 一份」,而不是共享的一份。请把它放在某一个 behaviour 的字段上,然后引用它。
Awake Udon 不会派发它。请使用 Start
CompareTaggameObject.tag Udon 不暴露 tag。请比较层级或名称,或者直接持有引用。
IsInvokingApplication.isPlayingTime.timeScaleAudioListenernew GameObject()ScriptableObject 的派生类 Udon 均未暴露。
在 Inspector 字段里序列化自定义类或结构体的数组 Udon 无法反序列化。请使用基元类型、Unity 类型或 behaviour 引用的数组。
指向普通对象(而非 behaviour)方法的委托,以及放在 Unity 会序列化的 public 字段中的委托 两者都无法带进世界里。
超出创建它的方法之后仍然保留的捕获型 lambda(赋值给字段、作为返回值、作为参数传出,或在循环中创建) 被捕获的变量位于 behaviour 唯一的堆上,因此保存下来的闭包在下次调用时会看到过时的状态。不捕获的 lambda 可以随意保存;捕获型的,只要作为局部变量在同一方法内调用就没问题。

暂时还不支持

这些会被 UDN0002 拒绝。它们是 Udonite 的缺口,而不是 Udon 的限制;有人提出需求的通常会被补上。

  • 列表模式(is [1, ..])。
  • 作为独立表达式的 typeof(T),以及非泛型的 GetComponent(typeof(T))
  • 递归(UDN0012)、循环内的捕获型 lambda、checked 运算。

如果某个拒绝挡住了你,请带上那一行拒绝信息提交 issue。只要说清楚是哪种写法,通常一天就能补上。

Something went wrong. Reload