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.
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.
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"))
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.
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.