Skip to main content

UdonSharp Nitpicks

I hope you enjoy reading this - but keep in mind that this isn't quite finished ✌️

Here's some things which I consider good practice when writing U# code, in no particular order. These suggestions are somewhat personal, so please let me know what you think in the comments below the article! ❤️

UdonSyncMode

By default, the sync mode of an UdonBehaviour is chosen in the Unity inspector. Which is fine, until you accidently set it to the wrong sync mode. Yikes!

Instead, use U#'s UdonSyncMode attribute to make sure your UdonBehaviour always uses the sync mode you want.

using UdonSharp;
using UnityEngine;

[UdonBehaviourSyncMode(BehaviourSyncMode.Manual)] 
public class Foo : UdonSharpBehaviour
{
  // ...
}

This will prevent you from changing the sync mode on different GameObjects reusing the same U# script.
But... does anyone actually do that? 🤔

SerializeField

If you make one of your variables public, it'll be accessible from the Unity inspector. It'll also make it accessible from any other UdonBehaviour. Most variables aren't accessed outside their own class, so making variables public makes your classes needlessly messy.

The solution? Keep those variables private instead, and just add [SerializeField] like so:

[SerializeField] private string foo;

You can also do the opposite: To hide a public variable from the inspector, use [HideInInspector].

Tooltips and Headers

U# scripts can have long and messy inspectors. Why not make them look nicer with the [Header] and [Tooltip] attributes?

[Header("References")]
[Tooltip("Reference to the mirror GameObject.")]
[SerializeField] private GameObject mirror;
[Tooltip("Transform to move the mirror to.")]
[SerializeField] private Transform targetTransform;

Cache your LocalPlayer

If you're doing something with Networking.LocalPlayer frequently, consider caching the reference in start:

private VRCPlayerApi localPlayer;

private void Start()
{
  localPlayer = Networking.LocalPlayer;
}

... and re-using that reference instead of calling Networking.LocalPlayer directly.

private void Update()
{
  Debug.Log(localPlayer.GetPosition();
}

What
else?

There's more I'd like to write,write forabout... example:

Let me know if any of these sound interesting! 😁
  • Avoid Update(), wheneveruse possibledelayed events instead.
  • Did you know that FixedUpdate() depends on your monitor's refresh rate? Yeah.
  • Use synced variables, avoid networked events, if you can.
  • FieldChangeCallback is great.
  • Name your classes and methods properly.