Skip to content

Types

Nori’s type system maps directly to the types available in VRChat’s Udon VM. Every Nori type has a corresponding Udon type name that the compiler uses when generating assembly. There are no user-defined types, no generics, and no type inference.

Primitive types

Nori typeUdon typeDescriptionExample literal
boolSystemBooleanTrue or falsetrue, false
intSystemInt3232-bit signed integer42, -7, 0
uintSystemUInt3232-bit unsigned integer0
floatSystemSingle32-bit floating point3.14, 0.0, -1.5
doubleSystemDouble64-bit floating point0.0
stringSystemStringText"hello", ""
charSystemCharSingle character—
objectSystemObjectBase type for all objectsnull
voidSystemVoidNo value (return type only)—

The most commonly used primitives are bool, int, float, and string. Use float for most decimal numbers — it matches Unity’s conventions and most Udon externs expect SystemSingle.

Unity types

Nori typeUdon typeDescription
Vector2UnityEngineVector22D vector (x, y)
Vector3UnityEngineVector33D vector (x, y, z)
Vector4UnityEngineVector44D vector (x, y, z, w)
QuaternionUnityEngineQuaternionRotation
ColorUnityEngineColorRGBA color (float components)
Color32UnityEngineColor32RGBA color (byte components)
TransformUnityEngineTransformPosition, rotation, and scale of a GameObject
GameObjectUnityEngineGameObjectA Unity scene object
RigidbodyUnityEngineRigidbodyPhysics body
ColliderUnityEngineColliderPhysics collider
MeshRendererUnityEngineMeshRendererMesh rendering component
AudioSourceUnityEngineAudioSourceAudio playback component
AnimatorUnityEngineAnimatorAnimation controller
CollisionUnityEngineCollisionCollision event data
MaterialUnityEngineMaterialMaterial for rendering (color, shader properties)
RendererUnityEngineRendererBase renderer component
LineRendererUnityEngineLineRendererRenders lines in 3D space
ConstantForceUnityEngineConstantForceApplies constant physics force
ComponentUnityEngineComponentBase class for all components

VRChat types

Nori typeUdon typeDescription
PlayerVRCSDKBaseVRCPlayerApiA VRChat player. Use localPlayer for the local player.
SerializationResultVRCSDKBaseVRCSerializationResultResult of a serialization operation
UdonBehaviourVRCUdonUdonBehaviourA reference to another UdonBehaviour
VRCObjectPoolVRCSDK3ComponentsVRCObjectPoolPool of reusable GameObjects
VRCObjectSyncVRCSDK3ComponentsVRCObjectSyncSyncs object position/rotation across network
VRCAvatarPedestalVRCSDK3ComponentsVRCAvatarPedestalAvatar pedestal for trying avatars
VRCPickupVRCSDK3ComponentsVRCPickupPickupable object component
VRCVideoPlayerVRCSDK3VideoComponentsBaseBaseVRCVideoPlayerVideo player component
VRCUrlInputFieldVRCSDK3ComponentsVRCUrlInputFieldURL input field component
VRCUrlVRCSDKBaseVRCUrlURL value type for video/download URLs
VRCImageDownloaderVRCSDK3ImageVRCImageDownloaderDownloads images from URLs
TextureInfoVRCSDK3ImageTextureInfoTexture download configuration
TrackingDataVRCSDKBaseVRCPlayerApiTrackingDataVR tracking position and rotation data
IVRCStringDownloadVRCSDK3StringLoadingIVRCStringDownloadString download result (has .Result, .Error, .ErrorCode properties)
IVRCImageDownloadVRCSDK3ImageIVRCImageDownloadImage download result (has .Error, .ErrorMessage properties)

Player is the type you will use most often for VRChat-specific logic. It provides properties like displayName, isLocal, and isMaster.

UI types

Unity’s built-in UI components are available for creating in-world interfaces:

Nori typeUdon typeKey propertyDescription
UITextUnityEngineUIText.text: stringDisplays text in the UI
UIToggleUnityEngineUIToggle.isOn: boolCheckbox / toggle switch
UISliderUnityEngineUISlider.value: floatNumeric slider (0.0 to 1.0 by default)
UIDropdownUnityEngineUIDropdown.value: intDropdown menu (value is the selected index)
UIInputFieldUnityEngineUIInputField.text: stringText input field
pub let label: UIText = null
pub let volume_slider: UISlider = null
on Start {
label.text = "Hello!"
let vol: float = volume_slider.value
log("Volume: {vol}")
}

These correspond to Unity’s UnityEngine.UI namespace. Drag UI components from your Canvas into the Inspector fields.

Enum types

Nori supports several built-in enum types from Unity and VRChat. Access enum values using the Type.Value syntax:

Nori typeValuesDescription
KeyCodeKeyCode.Space, KeyCode.W, KeyCode.Return, KeyCode.Escape, …Keyboard key constants
TrackingDataTypeTrackingDataType.Head, .LeftHand, .RightHand, .OriginVR tracking points
PickupHandPickupHand.Left, PickupHand.RightVR hand identifier
on Update {
if Input.GetKeyDown(KeyCode.Space) {
log("Space pressed!")
}
}
on Update {
let tracking: TrackingData = localPlayer.GetTrackingData(TrackingDataType.Head)
let head_pos: Vector3 = tracking.position
log("Head at: {head_pos}")
}

You cannot define your own enum types in Nori. Only the enums recognized by the Udon VM are available.

Array types

Arrays are the only collection type available in Nori. Declare an array by adding [] after the element type:

let scores: int[] = null
let names: string[] = null
let positions: Vector3[] = null
pub let targets: GameObject[] = null

The Nori type int[] maps to the Udon type SystemInt32Array. The pattern is consistent: type[] becomes {UdonType}Array.

Array operations

Access elements by index and get the length:

let items: string[] = null
on Start {
let first: string = items[0]
let count: int = items.Length
log("First item: {first}, total: {count}")
}

Set elements by index:

let values: int[] = null
on Start {
values[0] = 42
values[1] = 100
}

Create arrays with array literal syntax:

let primes: int[] = [2, 3, 5, 7, 11]
let greetings: string[] = ["hello", "world"]

Iterate over arrays with for..in:

let names: string[] = ["Alice", "Bob", "Charlie"]
on Start {
for name in names {
log("Hello, {name}!")
}
}

Static types

Some types are used only for their static properties and methods. You never create instances of these types — you access them directly by name:

TypeDescriptionExample
TimeFrame timingTime.deltaTime, Time.time
NetworkingVRChat networkingNetworking.LocalPlayer, Networking.IsOwner()
MathfMath functionsMathf.Abs(), Mathf.Lerp(), Mathf.Clamp()
PhysicsPhysics queriesPhysics.Raycast()
Vector3Vector3 staticsVector3.zero, Vector3.Lerp(), Vector3.Distance()
Vector2Vector2 staticsVector2.zero
Vector4Vector4 statics—
QuaternionQuaternion staticsQuaternion.identity
ColorColor statics—
RandomRandom valuesRandom.value, Random.Range(), Random.ColorHSV()
InputKeyboard inputInput.GetKeyDown(), Input.GetKey(), Input.GetKeyUp()
StringString utilitiesString.Format(), String.Concat()
UtilitiesVRChat utilitiesUtilities.IsValid()
VRCPlayerApiPlayer API staticsVRCPlayerApi.GetPlayers()
VRCStringDownloaderString downloadsVRCStringDownloader.LoadUrl()
on Update {
let dt: float = Time.deltaTime
let pos: Vector3 = transform.position
let dist: float = Vector3.Distance(pos, Vector3.zero)
log("Distance from origin: {dist}")
}

Implicit conversions

Nori supports three implicit type conversions. These happen automatically when assigning or passing values:

FromToExample
intfloatlet f: float = 42 — the int 42 is converted to float
intdoublelet d: double = 42 — the int 42 is converted to double
floatdoublelet d: double = 3.14 — the float 3.14 is converted to double

These conversions also apply to operator operands. If you write 5 * 2.0, the int 5 is widened to float before the multiplication.

All other type mismatches produce a compile error (E0040).

What is NOT supported

Generics

Nori does not support generic types like List<T> or Dictionary<K,V>. Udon’s type system is based on concrete .NET types exposed through the extern whitelist, and .NET generics are not part of that whitelist.

Use typed arrays instead:

// Instead of List<int>:
let scores: int[] = [0, 0, 0, 0, 0]
// Instead of List<string>:
let names: string[] = null

See E0042 for more details.

User-defined types

There are no classes, structs, interfaces, or enums that you can define in Nori. Udon has no mechanism for user-defined types. If you need to group related data, use parallel arrays or multiple variables:

// Instead of a Player struct:
let player_names: string[] = null
let player_scores: int[] = null
let player_alive: bool[] = null

Nullable types

There is no int? or bool? syntax. Primitive types always have a value. Reference types (GameObjects, Players, etc.) can be null.

Type inference

Nori requires explicit type annotations on all declarations. There is no var or auto keyword:

let x: int = 5 // correct
let x = 5 // error

Common patterns

Type-safe references

pub let door: GameObject = null
pub let audio: AudioSource = null
pub let spawn_point: Transform = null

Assign these in the Unity Inspector by dragging objects into the fields.

Working with vectors

let velocity: Vector3 = Vector3.zero
on Update {
velocity = Vector3.Lerp(velocity, Vector3.zero, Time.deltaTime)
transform.position = transform.position + velocity * Time.deltaTime
}

See also

  • Variables — How to declare variables with types
  • Expressions — Operators that work on these types
  • Limitations — Full list of unsupported features and why