Tutorial 5: Why import()?
Built from the confirmed, live-tested explanation already in the Glossary — this page’s contribution is walking through the failure case yourself instead of just reading about it.
In Tutorial 2, MrxTutorialManager needed an import("MrxTutorialManager") line before you could call it. In Tutorial 3, Player and Object needed nothing at all. That inconsistency isn’t an accident, and it isn’t optional to understand — get it wrong in a real script and the failure won’t be obvious.
Reproduce the error on purpose
Create scripts/OnKey/why_import.lua:
local KEYVAL = "insert" -- must be in the first 10 lines
MrxTutorialManager.ShowMessage("This should fail!")
Notice: no import("MrxTutorialManager") line. Load into a level and press Insert. Nothing shows up on screen — no popup, no crash you can see. Open lua_loader_printf.log anyway (the log file writes error messages too, not just your own Loader.Printf calls):
attempt to index global 'MrxTutorialManager' (a nil value)
[Image placeholder —
../img/importerror.png] Screenshot oflua_loader_printf.logshowing theattempt to index global 'MrxTutorialManager' (a nil value)error line, in context with a few normalLoader.Printflines from earlier tutorials above it for comparison.
That error is Lua telling you, plainly: MrxTutorialManager doesn’t exist as far as this script is concerned — it’s nil, and you can’t call .ShowMessage on nil.
The fix
local KEYVAL = "insert"
import("MrxTutorialManager")
MrxTutorialManager.ShowMessage("This should work now!")
Press Insert again. The popup appears, exactly like Tutorial 2.
What’s actually happening
This game’s Lua code comes in two flavors that look identical to call but behave very differently:
- Engine namespaces —
Player,Object,Event,Pg, and others. These are built into the engine itself and are always globally available, from any script, with zero setup. This is why Tutorial 3’sPlayer.GetCash()andObject.GetPosition(...)just worked. - Resident modules —
MrxTutorialManager,MrxPmc, and roughly 226 others. These are.luafiles the game itself loads (you can browse them under Resident Modules), and by default they’re only visible inside their own file.import("Name")is what pulls one into your script’s environment so you can call it too. Skip it, and the name is simplynilwhere you are — which is exactly the error above.
There’s no way to tell which is which just by how a call looks — Player.GetCash() and MrxTutorialManager.ShowMessage(...) are syntactically identical. When in doubt, check the Resident Modules index: if it’s listed there, it needs import().
Try it yourself
- Try importing a name that doesn’t exist at all —
import("NotARealModule")— and see what happens versus forgetting the import line entirely. Are the two errors the same, or different? - Remove the
import("MrxTutorialManager")line again, but this time wrap the call inpcall(function() MrxTutorialManager.ShowMessage("test") end). Does the error still show up in your log? (Tutorial 6 is entirely about whatpcallchanges here and why.) - Check the Resident Modules index for
MrxPmc(used back in Your First Mod) — confirm for yourself that it’s listed there as a module, which is exactly why that tutorial’s script also needed its ownimport("MrxPmc")line.
Where this comes from
- Glossary:
import("Name")— the full explanation, including the one exception (functions a module explicitly publishes to_Gdon’t need importing). - Glossary: engine namespace — the other half of the distinction.
- Resident Modules — the landing page explaining the module system in full, and the index of every module that needs
import().
Next: Tutorial 6: Don’t Let One Bad Line Kill Your Script — that error you just caused didn’t crash the game, but it silently stopped your script cold. Here’s how to stop that from happening.