Unity Scripts and VRChat Udon Basics

Unity scripts create custom components that can respond to events, change other components, and connect objects into working systems. In a normal Unity project, beginner runtime scripts commonly inherit from MonoBehaviour.

VRChat worlds use a different runtime. Logic that must run inside an uploaded world should use Udon Graph, UdonSharp, or supported built-in components—not an arbitrary MonoBehaviour.

Choose the runtime before writing code

Decide where the behaviour must run, then create the correct type of script.

  1. Use MonoBehaviour for normal Unity runtime learning or non-VRChat projects.
  2. Use Udon Graph or UdonSharpBehaviour for behaviour inside a VRChat world.
  3. Keep editor automation in editor-only scripts that are excluded from runtime builds.
  4. Compile, attach, assign references, and test one visible behaviour at a time.
VRChat runtime rule

Udon is VRChat's world scripting system. UdonSharp is included with the Worlds SDK and compiles C#-style scripts to Udon Assembly. UdonSharp supports much of basic C# syntax, but it is not fully compatible with the C# language. For world logic, inherit from UdonSharpBehaviour and check the UdonSharp documentation for supported features.

Select the Correct Script Type

Script or component type Runs where Typical use
MonoBehaviour Unity applications and Play Mode Normal Unity gameplay components and learning C#
Editor script Unity Editor only Importers, custom inspectors, project setup, and authoring tools
Udon Graph VRChat world and Unity editor testing Node-based VRChat world logic
UdonSharpBehaviour Compiled to Udon for VRChat worlds C#-style VRChat world logic
Allowlisted Unity or VRChat component VRChat world Supported behaviour that may not need custom Udon

Start by asking where the behaviour must run. A script can work perfectly in Unity Play Mode and still be unsuitable for an uploaded VRChat world.

How a Unity Script Becomes a Component

Unity creates custom component types from scripts that inherit from MonoBehaviour.

Part Role
.cs asset Source file stored in the Project window
Class Defines the component type
MonoBehaviour Connects the class to Unity's component and event systems
GameObject Holds an instance of the script component
Inspector fields Store serialized values and object references for that instance
Console Reports compiler errors, exceptions, warnings, and debug messages

Each GameObject with the component receives its own serialized field values. Editing one instance does not automatically change every other instance unless you edit a prefab asset or apply an override.

Create, Compile, and Attach a MonoBehaviour

For a normal Unity C# script:

  1. Select the intended folder in the Project window.
  2. Use Assets > Create > C# Script.
  3. Give the script its final class name immediately.
  4. Open it in the configured external code editor.
  5. Save the file and return to Unity.
  6. Wait for compilation to finish.
  7. Drag the script onto a GameObject or use Add Component.
  8. Assign its Inspector fields.
  9. Enter Play Mode and watch the Console.

A script asset sitting in the Project window does not run by itself. A MonoBehaviour must be attached to a GameObject, instantiated by other code, or otherwise used by a system that knows about it.

File Name and Class Name Must Match

Unity requires the file name and the MonoBehaviour class name to match before it can attach the script as a component.

ConsoleHello.cs:

using UnityEngine;

public class ConsoleHello : MonoBehaviour
{
    private void Start()
    {
        Debug.Log("ConsoleHello is running.", this);
    }
}

Attach the script to a GameObject and enter Play Mode. Start runs before the first frame update for that enabled script instance, and the message appears in Window > General > Console.

If you rename the class, rename the file to match. Then return to Unity and wait for a clean compilation before trying to attach it.

Understand Common Unity Events

Unity calls specially named event methods at defined points.

Event Beginner use
Start Initialize the component before its first frame update
Update Run frame-based behaviour while the component is active
OnEnable Respond when the component becomes enabled and active
Trigger and collision events Respond to configured Collider and Rigidbody interactions
Public methods Provide functions that other scripts or UnityEvents can call

Do not add an empty Update method to every script. Use it only when work genuinely needs to happen each frame.

Udon and UdonSharp expose their own supported event set. Check VRChat's event documentation rather than assuming every Unity callback behaves identically.

Expose Values in the Inspector

Unity serializes supported public fields. A private field can be made editable with [SerializeField].

using UnityEngine;

public class RotateDisplay : MonoBehaviour
{
    [SerializeField] private float degreesPerSecond = 45f;

    private void Update()
    {
        transform.Rotate(Vector3.up, degreesPerSecond * Time.deltaTime);
    }
}

After attaching this component, Degrees Per Second appears in the Inspector. Each component instance can store a different value.

Inspector fields can also reference GameObjects, components, and assets. Drag the object or asset into the matching field, and confirm the field no longer reads None.

Changes made to component values during Play Mode are normally reverted when Play Mode stops. Stop Play Mode before making values that must persist.

Check Object References

A script can compile correctly and still fail because a serialized reference is empty or points to the wrong component.

Before testing, check:

  • Every required object field has an assignment.
  • The assigned object belongs to the intended scene or prefab.
  • The field expects the correct component type.
  • Referenced GameObjects and components are enabled when required.
  • Prefab instances do not contain an unintended override.
  • The object reference will exist in the built scene.

A NullReferenceException means code attempted to use a missing object reference. Select the Console message, read the first relevant stack-trace line, and inspect the corresponding field or lookup.

Treat Compilation as a Project-Wide Check

Unity recompiles C# scripts after source files change. A compiler error can prevent new scripts from attaching and stop other editor tools from loading correctly.

Use this order:

  1. Open Window > General > Console.
  2. Enable the error filter.
  3. Select the first compiler error.
  4. Open the file and line reported by Unity.
  5. Fix that error and save.
  6. Return to Unity and wait for recompilation.
  7. Repeat until compilation succeeds.

Later errors can be consequences of the first one. Avoid editing several unrelated files before checking whether the earliest error has been resolved.

Organize Runtime and Editor Scripts

Unity treats some folder names specially.

  • Scripts under an Editor folder compile into an editor-only assembly.
  • Normal scripts elsewhere under Assets compile into runtime assemblies unless assembly definitions change that relationship.
  • Assembly Definition files can separate code into custom assemblies and control dependencies.

Code that uses the UnityEditor namespace must not be included in a player or VRChat world build. Keep custom inspectors and editor automation in an Editor folder or an editor-only assembly.

Small projects do not need Assembly Definition files immediately. Add them when the project has a clear assembly boundary or recompilation problem, and document the dependencies they introduce.

Use Udon Graph or UdonSharp for VRChat

VRChat provides two main authoring paths:

Path Authoring style Output
Udon Graph Nodes and wires in Unity Udon bytecode
UdonSharp C#-style source inheriting from UdonSharpBehaviour Compiled Udon Assembly

Create an UdonSharp script from Create > U# script in the Project window. The current Worlds SDK creates both a .cs source file and an UdonSharp Program Asset.

An UdonSharp script should normally inherit from UdonSharpBehaviour, not MonoBehaviour. Check the official supported-features list before copying standard Unity C# examples: generic collections such as List<T> and several other C# features are not supported.

For networking, local player APIs, ownership, synced variables, and network events, use the relevant VRChat documentation. A behaviour working for one local player does not prove it is synchronized for everyone.

Prefer Supported Components When They Fit

Custom code is not required for every world feature. VRChat recommends using native Unity components or VRChat SDK components when possible.

Examples include:

  • Animator and AnimationClip for repeated visual motion.
  • Audio Source with a VRChat spatial-audio component.
  • VRC Pickup and VRC Object Sync for supported pickup behaviour.
  • Playable Director for timeline-driven sequences.

VRChat publishes an allowlist of components that work in worlds, with additional Android exceptions. Check it before depending on a third-party MonoBehaviour at runtime.

Test at the Correct Level

Test Good for Limitation
Unity Play Mode Normal MonoBehaviour behaviour and editor-only testing Does not reproduce the VRChat client
ClientSim Fast local Udon and interaction testing in Unity Does not simulate every VRChat feature
VRChat Build & Test Running a local world build in the VRChat client Still requires deliberate multiplayer and platform testing
Private uploaded world Testing published-world conditions with invited users Changes require another upload

Read the Console after each test. For Udon networking, test the required number of clients and verify ownership and synchronization rather than checking only the local result.

Troubleshooting

Unity will not let me attach the script

Fix all compiler errors, confirm that the class inherits from MonoBehaviour, and make the file name match the class name exactly. Wait for compilation to finish before trying again.

The component is attached but nothing happens

Confirm the GameObject is active, the component is enabled, required Inspector references are assigned, and the event that starts the behaviour is actually reached. Add a temporary Console message at that entry point if needed.

The Console shows a NullReferenceException

Select the error and read the first relevant script line in its stack trace. Inspect object fields and lookups used on that line; one of them does not reference a valid object.

My Inspector value reset after Play Mode

Unity normally restores component values when Play Mode ends. Stop Play Mode, set the intended value again, and save the scene or prefab.

A script works in Unity but not in the uploaded VRChat world

Check whether it is an arbitrary MonoBehaviour. Runtime world logic should use Udon Graph, UdonSharpBehaviour, or an allowlisted component, then be validated and tested through the VRChat SDK.

UdonSharp rejects code from a normal C# tutorial

UdonSharp does not implement every C# feature or expose every API. Check the supported C# features and class exposure tree, then replace unsupported language features, collections, or methods.

A custom editor script breaks the world build

Ensure code using UnityEditor is in an Editor folder or editor-only assembly. VRChat's UdonSharp editor-scripting guidance also requires editor code to be excluded from the game build.

Before You Finish

  • Confirm the script type matches the runtime where it must execute.
  • Fix Console errors before attaching or testing new scripts.
  • Match MonoBehaviour file and class names.
  • Assign and verify every required Inspector reference.
  • Keep UnityEditor code out of runtime assemblies.
  • Use Udon Graph, UdonSharp, or allowlisted components for uploaded VRChat world behaviour.
  • Test multiplayer and target-platform behaviour explicitly.

Continue Learning

Official References

Next Step

Pick one visible behaviour, decide whether it belongs in MonoBehaviour or UdonSharp, then build the smallest component that proves the event, reference, and test path work.

Related Navigation