What exactly is an EXTERN in Udon, why is it so slow, and how should I think about minimizing it?

An EXTERN is an operation of Udon Assembly (uasm), as far as I understand. But it’s one of those things that gets casually talked about by folks more trained and comfortable with computer science, and never really explained for folks who are still learning.

So, what exactly is an EXTERN in Udon, why is it so slow, and how should I think about minimizing it?


An extern is anything that is ran outside the virtual machine. When you hear virtual machine you may think something like windows running in a window… No. The udon virtual machine is a deceptively simple bit of code that just runs assembly. It only natively supports a very small handful of operations like setting variables, getting variables, jumping around to different code, and externs. This means that basically any operation from basic addition to raycasts are externs. Udon itself has no idea what addition is, all it knows is that it can ask unity for the answer.

One of the reasons (and certainly not the only reason) why udon is slow is that it doesn’t trust externs. When udon receives back the results of an extern, it has to run a security check to make sure the object isn’t part of the UI or players or anything else that’s protected. The security check can sometimes be more expensive than the function itself. Though if it’s a primitive type like a bool or float, it can skip a large part of that but it still has to check it’s type.

In most cases, the cost of an extern is generally just something that has to be accepted. The performance has and will continue to increase over time.

However, it’s still worth knowing about externs because it highlights the usefulness of one particular thing that you can actually do: caching. If you’re working with an object that you receive from an extern, it is a bit cheaper to store it in a variable inside udon rather than doing an extern to get the same thing over and over again. If it’s stored as a variable in udon, udon knows it can already be trusted so it does not perform the security check every time it’s accessed.

The most common example is Networking.LocalPlayer. that is an extern, and it would be cheaper to just do that once on start and store it in a variable somewhere.