Skip to main content


The idea behind modules is that they are portable between projects. They package templates, styles, and assets together and serve as a basis for resolving imports within .ui files. Modules can have dependencies on other modules.

There are no visibility rules for elements, all template / element declarations are considered to be public.

If a module (A) includes a dependency on another module (B) and (B) declares a dependency on (C), and (A) wants to reference something in (C), (A) must declare a dependency on (C), it does NOT automatically inherit (B)'s dependency on (C)

Modules are file system scoped and cannot be nested. A template & style file belong to the nearest module at the same level or above them in the file tree. If no module asset exists in the project, it is an error.

When resolving names for templates & styles, the module in which the template or style is being used is first searched. If there is a template or style that is found, then it is used. If we didn't find the target in the local module, then all of the auto imports and explicit imports are searched. If there is only one match then it is taken. If multiple matches occur then an error is shown and you need to explicitly disambiguate using a ModuleAlias::YourThing fully qualified identifier.

// some file.ui

import SomeModuleName;
import OtherModule as Lib; // import 'OtherModule' and alias it as 'Lib'

// A Module (which is an asset in Unity) can define a list of auto imports
// and these function as though the user had written `import SomeModule`
// in every file belonging to that module

template Something render {

// the scope resolution operator is used to reference elements residing in imported modules

Lib::Button(); // using the alias
OtherModule::Button(); // using the full name, same result as the line above

Button(); // if no scope resolution operator is present, resolution is as follows
// 1. If the 'current' module in which this file is defined defines
// a template called 'Button', then we us it.
// 2. If the current module does not define 'Button', we look all the
// imported modules declared in this file and search for 'Button'.
// If one is found, we use it. If multiple imported modules define
// 'Button', we throw an Ambiguous import error and the user is required
// to use the :: operator to specify which version of 'Button' to use