Skip to main content

Types

Lua doesn't have a concept of types. But C# heavily relies on it. So we somehow need to bridge the gap.

Register Type

If you want to use a member of some Component, you will first need to register the Component's type. This is done by calling the registerType function, and passing the type name as an argument.

For example, doing this will allow your script to use members of the Rigidbody2D Component:

registerType("Rigidbody2D")

registerType should be the first thing to check you haven't forgetten if you get an error.

info

If the type is not a YOMG2 type, or is not directly under the UnityEngine namespace, you have to provide the full namespace path, for example:

registerType("UnityEngine.U2D.Spline")

Usually, if you've forgotten to register a type, you'll get an error like this:

ScriptRuntimeException: cannot access field X of userdata<UnityEngine.Object>

or like this

ScriptRuntimeException: cannot convert clr type HealthChangedEventArgs

or maybe something else idk. But just always make sure you've registered the type before going down a rabbit hole of debugging.

tip

You can register nested types by using '+'

registerType("EventsForModScript+Collision2DEventArgs")

Get Type

The getType function is used to get a C# type using its name. Funnily enough, it's actually used by registerType under the hood, and it's useful in a few scenarios.

Sometimes, when you are using a method from a Unity Engine Component, it expects a type as an argument.

Take this for example. This is how you'd normally add a new Component to a GameObject when coding a game in C#.

myGameObject.AddComponent(typeof(Light2D));

The AddComponent method you see here is also available for you to use in your ModScript. But notice how it takes a C# type as an argument.

Well in Lua, there are no types, so you wouldn't be able to call this method.

So I added a getType function that basically does the same thing, and in your ModScript, you can do something like this:

myGameObject.AddComponent(getType("UnityEngine.Rendering.Universal.Light2D"))
note

Primitive type names use the class or struct name, not the C# type name. For example, a float is a System.Single, an int is a System.Int32, and a string is a System.String, etc.

Whitelist

For the safety of players, there is a whitelist that dictates what types you can use in your ModScripts

Namespace whitelist

 "UnityEngine", "UnityEngine.U2D", "UnityEngine.EventSystem", "UnityEngine.InputSystem", "UnityEngine.UI", "UnityEngine.Rendering", "UnityEngine.Rendering.Universal", "UnityEngine.Audio", "UnityEngine.Animations", "UnityEngine.Events", "TMPro", "ETGgames", "ETGgames.Utils", "ETGgames.Extensions", "ETGgames.YOMG2.Extensions", "System.Collections.Generic", "System.Linq", "System.Collections"

Base Type whitelist

typeof(UnityEngine.Object), typeof(EventArgs), typeof(SettingsMemeItem)

Base type whitelist is used if the type wasn't found in the namespace whitelist, but only if it's in the YOMG2 assembly (Assembly-CSharp). It allows types that derive from the specified base types.

Singleton whitelist

typeof(PlayerManager), typeof(CameraManager), typeof(HUD), typeof(MemeUIManager), typeof(OpenNaNoorManager), typeof(PortalManager), typeof(AudioManager), typeof(GamepadInputProxies),

Singleton whitelist is used if the type is a Singleton

Assembly prefixes whitelist

 "UnityEngine.", "Unity.", "mscorlib", "netstandard", "Assembly-CSharp", "System"

Others

All YOMG2 interfaces, and all C# primitive types are allowed.


Overall, this is a very generous allowance, and should allow you to do pretty much anything you want. But if not, submit a feature request and I'll try my best to add it.

It would be nice to just allow everything in a perfect world, but we need these limitations is in place for security reasons.

tip

Make sure you look at Unity's documentation whenever you want more information about a type (class/struct). They have very good docs and examples.