# Tools

Just as much as I like making games, I love to make tools.

<table data-column-title-hidden data-view="cards" data-full-width="false"><thead><tr><th></th><th data-hidden data-card-target data-type="content-ref"></th><th data-hidden align="center">Title</th><th data-hidden data-card-cover data-type="image">Cover image</th></tr></thead><tbody><tr><td>Safer Prefab workflows for the whole team</td><td><a href="/spaces/zOOVmLdEeVhfPmrcckJe">/spaces/zOOVmLdEeVhfPmrcckJe</a></td><td align="center">BlackBox</td><td><a href="/files/FzekO8Tog5Vz0mcidlBg">/files/FzekO8Tog5Vz0mcidlBg</a></td></tr><tr><td>Workflows to make sub-assets nice and easy to use</td><td><a href="/spaces/WP70ItOegbJjXGyNP2E7">/spaces/WP70ItOegbJjXGyNP2E7</a></td><td align="center"></td><td><a href="/files/GaYzEEyVIFtyTfLUE42w">/files/GaYzEEyVIFtyTfLUE42w</a></td></tr><tr><td>Components for scenes!</td><td><a href="https://tools.continis.io/superscenes">https://tools.continis.io/superscenes</a></td><td align="center"></td><td><a href="/files/Ckhw4vJa1JwIHv8fW7Si">/files/Ckhw4vJa1JwIHv8fW7Si</a></td></tr><tr><td>Change Unity's appearance based on the current task</td><td><a href="/spaces/JbMi1RQ5OkWEfZdkCUEX">/spaces/JbMi1RQ5OkWEfZdkCUEX</a></td><td align="center"></td><td><a href="/files/cmD4Ozak8uxueI1r9aEl">/files/cmD4Ozak8uxueI1r9aEl</a></td></tr><tr><td>ScriptableObjects as cross-scene communication</td><td><a href="/spaces/c9UAjX7t2Dyuj3l9jfRm">/spaces/c9UAjX7t2Dyuj3l9jfRm</a></td><td align="center">ScriptableObject Tools</td><td><a href="/files/BsQYPwnlyFFzEJWtbhJC">/files/BsQYPwnlyFFzEJWtbhJC</a></td></tr><tr><td>All my editor tools in one go</td><td><a href="https://bit.ly/editorassetsbundle_as">https://bit.ly/editorassetsbundle_as</a></td><td align="center"></td><td><a href="/files/xNL5WAiZlx3yUu6fazrA">/files/xNL5WAiZlx3yUu6fazrA</a></td></tr><tr><td>Put notes directly in the 3D space</td><td><a href="/spaces/f2fYPDIaF7cUuVyaE6CE">/spaces/f2fYPDIaF7cUuVyaE6CE</a></td><td align="center">Scene Notes</td><td><a href="/files/QgnknURyG3dJos9RQMTC">/files/QgnknURyG3dJos9RQMTC</a></td></tr><tr><td>Codecks tasks directly within Unity scenes</td><td><a href="/spaces/1WFLYsqEXV27nqQXHqyF">/spaces/1WFLYsqEXV27nqQXHqyF</a></td><td align="center">Codecks Scene Notes</td><td><a href="/files/tQV2OU15ipVNBZqvtFWH">/files/tQV2OU15ipVNBZqvtFWH</a></td></tr><tr><td>A ShaderGraph shader in the look of Zelda BotW</td><td><a href="https://assetstore.unity.com/packages/vfx/shaders/urp-toon-shader-259777">https://assetstore.unity.com/packages/vfx/shaders/urp-toon-shader-259777</a></td><td align="center">Zelda Toon Shader</td><td><a href="/files/YqbNsIKzyvION61QLzeE">/files/YqbNsIKzyvION61QLzeE</a></td></tr></tbody></table>

## Support

### Discord

If you use Discord, come have a chat about my assets! You can join using [this Discord link](https://discord.gg/rCRug7Szr8).

### Unity Asset Store

If you have downloaded or purchased [one of my tools](https://assetstore.unity.com/publishers/87819) on the Unity’s Asset Store and you need assistance with it, feel free to contact me via email at <buoybase@gmail.com>. I’ll reply as quick as I can.

## Design principles

When I structure a framework or code library, I try to follow one guiding principle:

I believe it is (almost) impossible to make a generic tool that covers every need its users might have, without making it very complex to use.

(you have certainly seen plenty of software that sooner or later reached this point)

If you imagine ease-of-use and quantity-of-features as the two extremes on a scale, personally I prefer to stop roughly 70% of the way: provide a solid framework to start with, but not make it bloated with features, in order to keep it usable but most importantly, understandable.

I believe that providing a tool that can be easily understood and customised lends serves people better than one that tries to do all the things, but is inflexible.

For this reason my tools usually don’t look like an omni-comprehensive solution that weights 100MB and costs 120€. They aim to be **small**, **easy to pick up** and – if you were to need more from them – **easy to extend**.

While I love suggestions, I hope you'll understand if maybe a certain feature that you think it would really, really benefit your project, ultimately does not fit the roadmap :pray:

I have confidence that this way they can become the perfect tool in the hands of a capable programmer, rather than me trying to guess every possible use and make them too big.


# Intro

<figure><img src="/files/oIVGPxbYqkAbXBBgHqg8" alt=""><figcaption></figcaption></figure>

Hats enables the concept of *workspaces* in Unity. You can switch to a workspace at any moment to customise the appearance or the behaviour of the Editor according to the task you are performing.

<figure><img src="/files/IDNag5K24xBYn5RTFaxF" alt=""><figcaption><p>The Workspace Switcher UI</p></figcaption></figure>

By switching workspaces, the Editor can be made to load a specialised layout, open one or more scenes, hide or lock objects in the open scene, hide specific components, and more. Third-party tools can be made to work differently. And you can create [custom behaviour](/hats/building-on-hats/building-hats-based-tools) as a result of a workspace switch.

{% hint style="info" %}
For instance, an indie developer could create workspaces for Level Design, Set Dressing, Cinematics, Testing...

* When the Level Design workspace becomes active, it loads the main game scene and hides some components.
* When the Testing workspace is activated, it loads the Initialisation scene, so the developer can immediately enter Play Mode and test the game from the main menu.
* When Cinematics loads, it opens the main scene
  {% endhint %}

Hats can make the Unity Editor more streamlined, so you get focus – whichever hat you're wearing at the moment.


# Changelog

## 2.0.0 - New Rules!

(24/05/26)

**Added**

* Added a bunch of new rules:
  * Execute Menu Item
  * Open Prefab
  * Hide or Lock Layers
  * Set 2D Mode
  * Set Game View Size
  * Set Hierarchy Filter
  * Set Project View Filter
  * Switch Build Target
  * Toggle Overlay
* Load Layout rule now also allows to load a saved Overlays Layout to setup the Scene View.
* It is now impossible to edit the rules of a Workspace when said workspace is active. This prevents issues with rules leaving the workspace dirty or messed up.
* The Teams functionality can now be disabled (and it starts disabled). Users can enable it in Project Settings.

**Changed**

* IRule has been removed, new rules can now simply inherit from RuleBase.
* Lock Objects rule has been renamed Hide or Lock Objects.
* Select Folder and Select Packages Folder have been merged into one rule.

**Fixes**

* Fixed all issues with reordering/adding to/removing from the Workspaces list in Project Settings.
* Fixed the Button Group in the Main Toolbar not updating when the Workspaces list in Project Settings was changed.

**Warning:** This update introduces breaking changes. Some rules will break, and need to be manually set up again (the Workspace Inspector will show that clearly).

### 1.2.0

(26/05/26)

* Fixed issue with the reordering/adding in Workspace list.
* Button Group in Main Toolbar now updates when Workspaces change.

### 1.1.0

(09/02/26)

* Fixed the Toolbar Switcher UI for Unity 6.3. Now the Switcher UI matches the new toolbar standards required by Unity. In previous versions of Unity, the Switcher UI is unchanged.

### 1.0.4

(17/11/25)

* Fixed random Workspace list items becoming Null on item removal in the Project Settings window.
* Removed warning regarding drag and drop handler in Unity 6.3.

### 1.0.3

(12/08/25)

* Added Select Packages Folder rule.
* Improved dropdown menu to select Rule to add to Workspace.

### 1.0.2

(08/06/2025)

* Fixed issue with the LockObjects rule property drawer
* Catching PackageManager in both Unity 6 and 6.1, in LockMenuItem rule

### 1.0.1

(05/12/2024)

* Redesigned [Lock/Hide Objects rule](/hats/workspaces/workspace-rules/hide-or-lock-objects): now it's possible to look for objects by name, by tag, or by a component.
* Better error handling and logging.
* Workspace Inspector now shows if a workspace is currently active, as personal or as part of a Team.

## 1.0.0 - First release

(26/11/2024)

* [Workspace](/hats/workspaces/workspaces) creation and switching, [rule](/hats/workspaces/workspace-rules) system.
* [Teams](/hats/teams/teams) system. Switch workspaces automatically based on the team you're part of.
* Workspace [Switcher UI](/hats/workspaces/switching-workspaces), also available in the Unity toolbar.
* Added `[DisplayForTeam]` and `[HideForTeam]` attributes.


# Workspaces

The main feature of Hats is to create workspaces. A **workspace** can be seen as similar to an Editor layout, but is much more powerful, thanks to a variety of [rules](/hats/workspaces/workspace-rules) that can trigger when the workspace is enabled.

{% hint style="info" %}
**Build on Hats**

In addition to using workspaces to trigger rules, you can also [build tools](/hats/building-on-hats/building-hats-based-tools) that modify their appearance or behaviour depending on the active workspace.
{% endhint %}

## Default workspace

When you first start Hats, a Default workspace is created and activated. This workspace has no rules, meaning that the Editor is not modified in any way.

When you remove an active workspace or something "bad" happens (i.e. the active workspace asset is deleted), Hats reverts to the Default workspace.

## Create a workspace

Workspaces are personal, so each user on the project can have their own set. workspaces are represented by a ScriptableObject of type `Workspace`.

To create one, simply right-click in the Project window and choose **Create > Hats > Workspace**.

<figure><img src="/files/KleTjA007vPEGAlJOxXG" alt="" width="563"><figcaption></figcaption></figure>

Once created, you can modify its properties:

<figure><img src="/files/1gOamTdNXFhkMzIMxGXt" alt="" width="563"><figcaption><p>The Inspector of a Workspace ScriptableObject</p></figcaption></figure>

Notice that **identifier**, **icon** and **colour** are all important because they appear in the Workspace[ Switcher UI](/hats/workspaces/switching-workspaces#switcher-ui), and help you identify which workspace is active at the moment.

{% hint style="info" %}
The **identifier** property is the one used in the UI. You can name the asset itself a more compact name, or add who the Workspace belongs to, if you're sharing them with the team.

**i.e.** "Level Design" as the identifier, vs. `Jonathan_LevelDesign` as the filename
{% endhint %}

The **rules** list contains [workspace rules](/hats/workspaces/workspace-rules) that trigger when the workspace becomes active. Click on the plus button to explore available types (and read all about them in the [Rules section](/hats/workspaces/workspace-rules)).

Once the file is setup, it's time to enable it.

{% hint style="success" %}
**Sharing workspaces**

Even though workspaces are personal, because they are assets they *could* be shared with the rest of the team. It's up to you and the team to decide whether workspaces are personal or shared.

If you want to keep them personal, you might want to save them all in a designated folder (for instance :open\_file\_folder: `Assets/Settings/Hats/Workspaces`) and ignore that folder in your version control.
{% endhint %}

## Enable workspaces

To assign a workspace to your list, go to **Project Settings > Hats**, and add it to the list of **Personal Workspaces**.

<figure><img src="/files/51iOirF9mmNk9kocHv5M" alt="" width="563"><figcaption><p>The list of available workspaces, in Project Settings</p></figcaption></figure>

As you add workspaces, you will notice that they become available in the Switcher UI at the top (next to **Active Workspace**).

Once at least 1 workspace is added to the list, you can now [switch between them](/hats/workspaces/switching-workspaces).

To understand if or how a workspace is used, select it and look at the bottom of its Inspector. You will find a series of messaging detailing whether the Workspace is in use, or if it's associated to [a Team](/hats/teams/teams):

<figure><img src="/files/T6X5Y4Wu1QfrNpz9RezF" alt="" width="563"><figcaption><p>This workspace is available for switching, and currently active.</p></figcaption></figure>

## Remove a workspace

To remove a workspace from the available ones, you do so in **Project Settings > Hats**. You just need to remove it from the list.

Removing a workspace from the list doesn't delete the asset. So you can safely remove workspaces to disable them, keep the asset, and re-enable them at a later point.

{% hint style="success" %}
If you remove an active workspace, Hats automatically switches to [the Default workspace](#the-default-workspace).
{% endhint %}


# Switching workspaces

You can move between workspaces in different ways.

## Switcher UI

The Switcher UI is a small widget that comes in two flavours: as a strip of buttons, or as a dropdown. You can see it at the top of the **Hats** **Project Settings** window:

<div><figure><img src="/files/IDNag5K24xBYn5RTFaxF" alt="" width="344"><figcaption><p>The Buttons Switcher UI</p></figcaption></figure> <figure><img src="/files/3L3uh9nQbFV0BMfypi1b" alt="" width="345"><figcaption><p>The Dropdown Switcher UI</p></figcaption></figure></div>

In the same window, you can decide which one to use, using the property **Switcher Style**.

## Main Toolbar

If you want to see the Switcher UI in the main Unity Toolbar (i.e. where the Cloud, Layouts, Search buttons are), simply enable it in **Project Settings > Hats** under the **Display in Toolbar** property.

<div><figure><img src="/files/h6ME2RqZHvTzywAIInEg" alt="" width="153"><figcaption><p>Toolbar UI as Buttons</p></figcaption></figure> <figure><img src="/files/smKxg4lXOtFy9F4DU3rO" alt="" width="180"><figcaption><p>Toolbar UI as Dropdown</p></figcaption></figure></div>

Like the regular widget, the Toolbar UI also comes both as a button strip or as a dropdown.

## Shortcuts

Hats also offers shortcuts to switch workspaces. By default, you get:

* Alt + Shift + 1: Change to the Default workspace
* Alt + Shift + 2-9: Change to other workspaces
* Alt + Shift + Right arrow: Next workspace
* Alt + Shift + Left arrow: Previous workspace

{% hint style="info" %}
For **Mac** users, all shortcuts use Option + Shift.
{% endhint %}

You can customise these shortcuts in the [Unity Shortcut manager](https://docs.unity3d.com/Manual/UnityHotkeys.html).

## Workspace Switcher window

If you'd rather have the Switcher UI in a different spot in your Unity Editor, you can also open it as a dockable window by going to **Tools > Hats > Workspace Switcher Window**.

The window will contain whatever style of widget was set in the **Hats** **Project Settings**.


# Workspace rules

Workspace rules are actions that trigger when a workspace is activated. They can be one-off (like opening a scene), or a more permanent condition that is activated with the workspace and deactivated when you switch away (like for instance, locked folders).

To add rules to a workspace, you can do so by inspecting the workspace asset itself, and add to the rules list.

<figure><img src="/files/VTNPGHDpkGbHkRxEuVIZ" alt="" width="563"><figcaption><p>Adding a new Select Folder rule to a workspace</p></figcaption></figure>

{% hint style="info" %}
Read the **sub-pages in this section** to understand the behaviour of each rule type.
{% endhint %}


# Disable Menu Item

Use this rule to render some menu items inaccessible.

<figure><img src="/files/iPV0ueFGD8Ii2Uf5Tv8a" alt="" width="563"><figcaption></figcaption></figure>

### On workspace enabled

The specified menu item gets disabled, and won't be clickable.

### On workspace disabled

The disabled menu item is enabled again.

{% hint style="warning" %}
Not all menu items can be disabled. For instance, you can't disable the ones under **File** or **Edit**.
{% endhint %}

### Setup

This rule is **a bit special**, in that it doesn't have Inspector properties you can set. This is because the trick used to disable a menu item requires the item to be compiled in code, so it can't be an Inspector property. The default one, provided as an example, disables the Package Manager menu item (across both Unity 6 and Unity 6.1, where its path differs).

To use this rule, duplicate the `DisableMenuItem.cs` script contained in :open\_file\_folder: `Packages/Hats/Editor/Rules/`, and modify the code inside to include any menu item you need to disable.

The code you need to change is clearly highlighted:

```csharp
// -- Start of customisable block
private const string MenuPath = "Window/Package Manager"; // For Unity 6
private const string MenuPath2 = "Window/My Assets"; // For Unity 6
private const string MenuPath3 = "Window/Package Management/Package Manager"; // For Unity 6.1
private const string MenuPath4 = "Window/Package Management/My Assets"; // For Unity 6.1
private const string MenuPath5 = "Window/Package Management/Services %0"; // For Unity 6.1

[MenuItem(MenuPath, true)]
[MenuItem(MenuPath2, true)]
[MenuItem(MenuPath3, true)]
[MenuItem(MenuPath4, true)]
[MenuItem(MenuPath5, true)]
private static bool ValidateMenuItem() => !_itemIsActive;

// -- End of customisable block
```

Change the value of the `MenuPath` constants to the items you want to disable, and add or remove `[MenuItem(..., true)]` attributes to match.

You can also duplicate that whole block and disable multiple menu items in one go (you need to rename the method to avoid name clashes). Alternatively, duplicate the script again and repeat the process.


# Execute Menu Item

Use this rule to automatically run one or more Editor menu items when a workspace becomes active.

### On workspace enabled

The listed menu items are executed, in order.

### On workspace disabled

No behaviour.

{% hint style="info" %}
Add the full menu paths, for example `Window/Analysis/Profiler` or `GameObject/Align View to Selected`.
{% endhint %}

{% hint style="warning" %}
Some menu items (such as those under **File** or **Edit**) can't be executed this way.
{% endhint %}


# Hide or Lock Layers

Use this rule to hide or lock entire layers in the Scene View.

### On workspace enabled

The selected layers are hidden from the Scene View and/or locked, so objects on them can't be picked, depending on the toggles.

### On workspace disabled

The previous visibility and lock state of the layers is restored.

{% hint style="info" %}
Use the **Hide** and **Disable picking** toggles to choose whether the selected layers are hidden, locked, or both.
{% endhint %}


# Hide or Lock Objects

Use this rule to hide or lock one or more GameObjects in the scene. You can filter by name, tag, or component.

<figure><img src="/files/c5nhcEpmsnWx7XsgTSN6" alt="" width="563"><figcaption></figcaption></figure>

{% hint style="info" %}
**No scene changes**

Note that hiding is done via [Scene Visibility](https://docs.unity3d.com/Manual/SceneVisibility.html), and locking via [Scene Picking](https://docs.unity3d.com/Manual/ScenePicking.html), and not via the GameObject's active flag. As such, enabling this rule doesn't modify the scene.
{% endhint %}

### On workspace enabled

All the GameObjects in the open scenes found as part of the search are hidden and/or have their picking disabled (locked), depending on the toggles.

### On workspace disabled

All the GameObjects found in the search are set to visible and pickable again.

{% hint style="info" %}
Use the **Hide** and **Disable picking** toggles to choose whether matching objects are hidden, locked, or both.

When filtering by name, the match is exact.
{% endhint %}

{% hint style="warning" %}
**Inactive objects**

If looking for objects by **name** or by **tag**, ensure that the objects you want to be affected are active, as Unity can't find inactive ones this way. If you want to lock or hide inactive objects, filter by **component** instead, which also finds inactive objects.
{% endhint %}


# Highlight Gizmos

Use this rule to give more visibility to the gizmos of specific types that you need to work with.

<figure><img src="/files/uVe5p820o7ULweJg9I6I" alt="" width="563"><figcaption></figcaption></figure>

### On workspace enabled

All icons and gizmos for all types get disabled in the Scene View, except the ones for the types specified in this rule.

### On workspace disabled

All previously hidden gizmos are re-enabled. Gizmos that were not enabled in the first place are not enabled again.

{% hint style="info" %}
Add the Component type names using their full type name, without spaces and without the assembly name. For example: `ReflectionProbe`, `Light`, `AudioSource`.
{% endhint %}


# Load Layout

Use this rule to load an Editor or Overlays layout as part of your workspace switch.

<figure><img src="/files/D3XP4zidMzGe4dZhSnm7" alt="" width="563"><figcaption></figcaption></figure>

### On workspace enabled

The specified window layout and/or Scene View overlays layout get loaded.

### On workspace disabled

No behaviour.

{% hint style="info" %}
Both fields are optional, so you can assign just one or both.
{% endhint %}

#### Setup

**Windows Layout (.wlt)**

Ensure the Editor is in the state you want (windows, focused windows, window size, etc.) and choose **Save Layout to File...** from the Layouts button in the top-right corner of the Unity toolbar:

<figure><img src="/files/ZLcugimRKBudWUTKrff7" alt="" width="326"><figcaption></figcaption></figure>

Save the `.wlt` file in a location of your choice, and then reference it in the Load Layout rule.

**Overlays Layout (.overlay)**

Arrange the Scene View overlays as you like, then save them to a `.overlay` preset file kept inside your project. Reference that file in the Load Layout rule.


# Lock Folders

Use this rule to prevent access to certain folders in the project.

<figure><img src="/files/oXd6qJzl33EYYTuf7lf9" alt="" width="563"><figcaption></figcaption></figure>

### On workspace enabled

The specified folders get disabled and greyed out in the Project view. You won't be able to select, move, rename them; or to drag/drop items onto them.

<figure><img src="/files/wrqB89NF52WOkSJkcPF5" alt="" width="375"><figcaption><p>Art, Audio and Samples folder are disabled</p></figcaption></figure>

### On workspace disabled

The disabled folders are enabled again.

{% hint style="info" %}
You can specify an **entire path** by chaining folders with a "/" character. Make sure to enter the folder's path without the "Assets/" part.

Note that all sub-folders will be disabled too.
{% endhint %}

{% hint style="warning" %}
Note that **certain operations are** **still possible** on disabled folders, like for instance saving a file into them, or moving files into them using the OS File Manager. The disabling is purely a UI lock in Unity's Project view.
{% endhint %}


# Open Scenes

Use this rule to quickly jump into scenes you visit often.

<figure><img src="/files/XPMgZe2A85jTo4sSAQEp" alt="" width="563"><figcaption></figcaption></figure>

### On workspace enabled

The specified Unity scene(s) get opened.

If more than one scene is listed the first one becomes [the active scene](https://docs.unity3d.com/ScriptReference/SceneManagement.SceneManager.SetActiveScene.html), and the others are opened [additively](https://docs.unity3d.com/ScriptReference/SceneManagement.OpenSceneMode.Additive.html).

### On workspace disabled

No behaviour.

{% hint style="info" %}
If you have unsaved changes when the workspace switches, Unity will first ask you to save them. If you choose not to, the scenes won't be opened.

If you were editing a Prefab in isolation (Prefab Mode) when this workspace was activated, that Prefab is reopened automatically when the workspace is deactivated.
{% endhint %}


# Open Prefab

Use this rule to jump straight into a Prefab you work on often.

### On workspace enabled

The referenced Prefab is opened in isolation (Prefab Mode).

### On workspace disabled

The Editor returns to the Main Stage.


# Scene Camera to Position

Use this rule to bring the camera to a useful spot in the scene.

<figure><img src="/files/OPPK4WwQvCDbvBFVaw7q" alt="" width="563"><figcaption></figcaption></figure>

### On workspace enabled

The camera in the Scene View is transported to the specified position, rotation, and distance from a focus point.

{% hint style="info" %}
To set the values you can move the camera into position, then use the **Record Camera Position** button in the rule's Inspector.
{% endhint %}

### On workspace disabled

No behaviour.


# Select Folder

Use this rule to quickly go back to a folder you need to visit often.

<figure><img src="/files/XdbsFqKNPaK5XIFQ81FA" alt="" width="563"><figcaption></figcaption></figure>

### On workspace enabled

The specified folder is selected and opened in the Project window.

### On workspace disabled

No behaviour.

{% hint style="info" %}
Use the dropdown to choose whether the folder lives under **Assets** or **Packages**, then type the path to the folder relative to that root.

You can specify an entire path by chaining folders with a "/" character. Make sure to enter the path without the leading "Assets/" or "Packages/" part.
{% endhint %}


# Set 2D Mode

Use this rule to switch the Scene View into 2D (or 3D) mode for the kind of work you're doing.

### On workspace enabled

The Scene View is switched into 2D (or 3D) mode, depending on the toggle.

### On workspace disabled

The Scene View's previous mode is restored.


# Set Game View Size

Use this rule to set the Game View to a specific resolution or aspect ratio.

### On workspace enabled

The Game View is set to the chosen resolution or aspect ratio.

### On workspace disabled

No behaviour.

{% hint style="info" %}
Pick one of the presets (1080p, 4K, 720p, 16:9, 16:10, 4:3, 21:9), or choose **Custom** to enter your own fixed resolution or aspect ratio.

If the size doesn't already exist, it's added to the current platform's Game View size list.
{% endhint %}


# Set Hierarchy Filter

Use this rule to focus the Hierarchy window on the objects that matter for a given workspace.

### On workspace enabled

A search filter is applied to the Hierarchy window.

### On workspace disabled

The filter is cleared again, unless it has since been changed by hand.

{% hint style="info" %}
Choose **By Name** to search by GameObject name, or **By Type** to search by Component type (for example `Light`, `Camera` or `CinemachineCamera`).
{% endhint %}


# Set Project View Filter

Use this rule to focus the Project window on the assets that matter for a given workspace.

### On workspace enabled

A search filter is applied to the Project window.

### On workspace disabled

The filter is cleared again, unless it has since been changed by hand.

{% hint style="info" %}
Choose **By Name** to search by asset name, or **By Type** to search by asset type (for example `Texture`, `Prefab`, `Material` or `Model`).
{% endhint %}


# Toggle Overlay

Use this rule to show or hide a specific Scene View overlay for a given workspace.

### On workspace enabled

The selected Scene View overlay is shown (or hidden, depending on the toggle).

### On workspace disabled

The overlay's previous state is restored.

{% hint style="info" %}
Pick the overlay from the list. The list reflects the overlays currently available in the Editor, so package-provided overlays (such as AI Navigation) appear once their package is installed.
{% endhint %}


# Switch Build Target

Use this rule to switch the active build target (platform) when a workspace becomes active.

### On workspace enabled

The active Build Target is switched to the selected platform.

### On workspace disabled

No behaviour.

{% hint style="warning" %}
Switching platform can trigger a reimport of assets and may take a while. The selected platform's module must be installed for the switch to succeed.
{% endhint %}


# Teams

Teams **categorise users in groups**, using their Unity ID (i.e. their email).

If a user is signed in and their email is listed as a user of a Hats Team, they are *part of that* Team. This happens as soon as the Editor is launched. Users can then jump to other Teams if they so wish.

{% hint style="success" %}
**Build on Hats**

In addition to using Teams to put users into workspaces, you can also [build tools](/hats/building-on-hats/building-hats-based-tools) that modify their appearance or behaviour depending on the active Team.
{% endhint %}

## Enabling Teams

The Teams functionality can be enabled and disabled at will, and is disabled by default. To use Teams, go to **Project Settings > Hats** and check the checkbox **Enable Teams**.

## Managing Teams

<figure><img src="/files/v8VFcFg0uWjUoPgbUifE" alt=""><figcaption><p>The Teams section in Project Settings > Hats</p></figcaption></figure>

By going to **Project Settings > Hats** and scrolling down, you can see the Teams section of Hats. Here you can see which Team you're currently part of.

By default, new users are in "No Team", meaning the Editor is not affected by Teams. After you have created Teams you can join a different one, or even return to No Team.

## The Team Catalog

In Hats, available Teams are contained in a catalog ScriptableObject.

This asset is created automatically in :open\_file\_folder: `Assets/Settings/Hats` the first time the project is loaded. After this, you can add Teams to the catalog by simply selecting the SO and adding to its Teams list:

<figure><img src="/files/juW9bgmcMOkhPH03eIZB" alt="" width="563"><figcaption><p>The TeamsCatalog Inspector, with 4 Teams in it</p></figcaption></figure>

Individual Teams are sub-assets of the Catalog, and they are automatically managed for you.

<figure><img src="/files/XrOK3mF0bEVFQGl4JxM0" alt="" width="221"><figcaption><p>The Teams as sub-assets of the Catalog</p></figcaption></figure>

{% hint style="info" %}
The Teams Catalog is meant to be shared and under version control, as you want everyone working on the project to have the same Teams.
{% endhint %}

## Setup a Team

<figure><img src="/files/FOQkdWmtV4fhc9sYTy6Z" alt="" width="563"><figcaption><p>The Inspector of a Team asset</p></figcaption></figure>

As you add Teams to the Catalog, you can change their properties

### Team Workspace

Each Team can have a workspace associated with it. This workspace is applied as soon as the editor starts, and cannot be switched unless one where to switch Teams.

Differently from personal workspaces, Team workspaces are enabled by default for all users who are part of the team. You can think of Team workspaces as an underlying layer: first the Team workspace is applied, then any active personal workspace is applied on top.

### Members

Members of a team are emails (Unity ID emails) that are associated to the team. If a user is logged in as that Unity ID upon launching the editor, the team becomes *their* team and its workspace (if present) is enabled.

Member emails can be tweaked manually, or you can add yours to a team by [switching to it](/hats/teams/switching-teams).


# Switching Teams

Differently from workspaces, Teams are not meant to be switched all the time. Theoretically, one would enter a Team and never move to another one for the course of the project. That's why there is no "Team Switcher UI".

However, it is possible to change teams. Doing so removes your email from the current Team's members list, and automatically adds it to the Team you join.

{% hint style="warning" %}
Because switching Teams modifies the [Team Catalog](/hats/teams/teams#the-team-catalog), if you are working with version control you need to remember to push the modifications to other users.
{% endhint %}


# Building Hats-based tools

In addition to the built-in functionality, Hats provides API so you can create tools that provide a tailored experienced to their users.

## How to create your own tool

In general, the idea is to create tools (or, more specifically, their UI) that looks or acts differently based on which Team or Workspace is enabled.

This usually requires two steps:

1. Define which Workspace or Team to look for. You can either:
   * Hardcode the information in C#.
   * Allow the user to choose from a UI, using a Dropdown or some other control that allows to specify what to look for (see [UI elements](#ui-elements) below). This way you would be creating a tool that the user can configure for themselves.
2. Use this information to tweak the tool's behaviour, by using Hats' [public API](#api).

{% hint style="info" %}
For instance, in the custom Inspector for a component, one could display or hide parts of it based on whether the user is part of a specific Team.
{% endhint %}

## UI elements

To facilitate the task of creating tools, Hats comes with UI Elements that you can use in your UIs to allow the user to choose a workspace or a Team.

{% hint style="danger" %}
The built-in UI elements are only available for **UI Toolkit**. For IMGUI components, you will need to build them yourself.
{% endhint %}

### Team Picker Dropdown

This UI automatically displays existing teams in a dropdown. Like other `MaskField` in Unity, the value is stored as an `int` bitmask, where 0 means no Team, and -1 means all Teams.

To use it, add an element of class `TeamPickerDropdown` to your UIs.

<figure><img src="/files/UW5A7ywSqq7efCW8HyGH" alt="" width="393"><figcaption><p>The TeamPickerDropdown in action</p></figcaption></figure>

{% hint style="info" %}
The constructor allows to pass a `bool` parameter to visualise the No Teams option or to hide it. This can be used to ensure that at least a Team is selected.
{% endhint %}

### Workspace Selector UI

{% hint style="info" %}
A workspace selector UI will come in a future version of Hats.
{% endhint %}

## API

Hats provides a host of public API to query the current state of workspaces and Teams.

Look into the static classes `Workspaces` and `Teams` in the `Hats.Editor` namespace for the full list of public API.


# Property attributes

A few attributes are available to decorate the fields of your rules. They change how those fields look or behave in the Inspector. Add them on a serialized field, just like Unity's own `[Range]` or `[Tooltip]`.

#### \[DisplayOnlyForTeam]

Only shows the field if one of the given teams is currently active. Pass one or more team identifiers. If none of them is active, the field is hidden entirely.

```csharp
[DisplayOnlyForTeam("artists", "tech-art")] public string texturesFolder;
```

#### \[HideForTeam]

Hides the field if one of the given teams is active, and shows it otherwise.

```csharp
[HideForTeam("programmers")] public bool showAdvancedHelpers;
```

{% hint style="info" %}
The team identifiers are the ones you set up in the **Teams** feature. The two team attributes only have an effect when Teams is enabled in the Hats project settings.
{% endhint %}


# Adding new rules

The set of rules is open: you can write your own and they'll show up in the workspace's rule list automatically, right next to the built-in ones. A rule is just a small C# class.

## How to create a new rule

A rule needs four things:

1. It must live in an **Editor** assembly (an `Editor` folder, or an asmdef that references `Hats.Editor`).
2. It must inherit from `RuleBase` and be marked `[System.Serializable]`.
3. It must carry a `[RuleInteractionType(...)]` attribute that says **when** it acts.
4. It must implement `RuleName`, `RuleDescription`, `OnBecameActive` and `OnBecameInactive`.

That's it. Public serializable fields appear in the Inspector on their own, and the rule is added to the **+** menu of Workspaces automatically.

An example of a simple custom Rule:

```csharp
using Hats.Editor;
using Hats.Editor.Attributes;
using Hats.Editor.Rules;

namespace MyGame.HatsRules
{
    [System.Serializable]
    [RuleInteractionType(RuleInteractionType.OnWorkspaceActivated)]
    public class MyRule : RuleBase
    {
        public override string RuleName => "My Rule";

        public override string RuleDescription =>
            "A short explanation of what this rule does. " +
            "It's shown in the (?) tooltip next to the rule in the Inspector.";

        public override bool OnBecameActive(Hats.ChangeReason reason)
        {
            // Do the thing here.
            // Return true if it worked, false if it couldn't run.
            return true;
        }

        public override bool OnBecameInactive() => true;
    }
}
```

#### Interaction type

The `[RuleInteractionType(...)]` attribute is required, and decides which submenu the rule lands in:

* `OnWorkspaceActivated` — the rule does something only when the workspace is turned on (**On Activation**).
* `OnWorkspaceDeactivated` — the rule does something only when the workspace is turned off (**On Deactivation**).
* `OnOff` — the rule does something on activation and undoes it on deactivation (**On & Off**).

{% hint style="warning" %}
Don't forget the attribute. A rule without `[RuleInteractionType(...)]` won't be picked up correctly by the **+** menu.
{% endhint %}

#### Return values

`OnBecameActive` and `OnBecameInactive` return a `bool`: return `true` when the rule applied successfully, and `false` when it couldn't (for example because a required field is empty or the Prefab it was trying to load has been destroyed, etc.). When returning `false`, it's good practice to log a warning prefixed with `(Hats)` so the user knows why nothing happened.

Also, the return is used to decide whether to execute following rules in the Workspace. This is to avoid that if a rule doesn't execute correctly, following rules fail too.

#### Handling recompiles

`OnBecameActive` is also called after a domain reload (a script recompile) for whichever workspace is active, with `reason == Hats.ChangeReason.Recompile`.

Many rules early-return in that case, because whatever they did is already in place, but rules can be set to act again after a recompile if that makes sense.

If you don't need a rule to act again on recompile, you can early exit using this line:

```csharp
if (reason == Hats.ChangeReason.Recompile) return true;
```

#### Remembering previous state

Since rules are not serialised by default, an `OnOff` rule that needs to restore something to a previous state might lose the original state if a recompile happens while it's active.

As such, a good idea is to store the state value in a `ScriptableSingleton`, so that the value will survive a recompile:

```csharp
[RuleInteractionType(RuleInteractionType.OnOff)]
[System.Serializable]
public class MyToggleRule : RuleBase
{
    public override string RuleName => "My Toggle Rule";
    public override string RuleDescription => "...";

    public override bool OnBecameActive(Hats.ChangeReason reason)
    {
        // On recompile, don't overwrite the value we already stored.
        if (reason != Hats.ChangeReason.Recompile)
        {
            MyRuleMemory.instance.previousValue = SomeSetting;
            MyRuleMemory.instance.hasStored = true;
        }

        SomeSetting = myDesiredValue;
        return true;
    }

    public override bool OnBecameInactive()
    {
        if (!MyRuleMemory.instance.hasStored) return true;

        SomeSetting = MyRuleMemory.instance.previousValue;
        MyRuleMemory.instance.hasStored = false;
        return true;
    }
}

public class MyRuleMemory : ScriptableSingleton<MyRuleMemory>
{
    public bool previousValue;
    public bool hasStored;
}
```

{% hint style="info" %}
Some Editor APIs aren't ready the instant a workspace switches (the Scene View, for example). If you hit this, defer the work with `EditorApplication.delayCall += () => { ... };`.
{% endhint %}

#### Renaming a rule later

If you rename a rule's class after it's already been used in some workspaces, add the `[MovedFrom]` attribute so existing references keep working:

```csharp
using UnityEngine.Scripting.APIUpdating;

[System.Serializable]
[MovedFrom(true, sourceClassName: "OldRuleName")]
[RuleInteractionType(RuleInteractionType.OnOff)]
public class NewRuleName : RuleBase { /* ... */ }
```

## Custom Inspector (optional)

By default the rule's fields are drawn with Unity's standard property field, and the `(?)` tooltip is filled from `RuleDescription`. If you want a custom layout (extra buttons, a different control), add a drawer that inherits from `RulePropertyDrawer` and override `CreateMainElement` (to replace the body) or `AddExtraElements` (to append to the foldout).

{% hint style="info" icon="lightbulb" %}
For instance, the **Scene Camera to Position** rule does this to add its **Record Camera Position** button.
{% endhint %}


# BlackBox for Prefabs


# Intro

<figure><picture><source srcset="/files/52uz3ZxXOd7VPIjGf5Rm" media="(prefers-color-scheme: dark)"><img src="/files/7aY7y6wdXvQYny8Nzwq4" alt=""></picture><figcaption></figcaption></figure>

:link: Find BlackBox 1.x on the [**Unity Asset Store**](https://bit.ly/blackbox_as)

:link: Find BlackBox 2.0 on the [**Unity Asset Store**](https://assetstore.unity.com/packages/tools/utilities/blackbox-2-redefined-prefab-workflow-389198)

**BlackBox** enables a workflow that is often referred to as "turning a Prefab into a black box", or "encapsulating", "collapsing" or "locking" it (there is no official name).

A [locked Prefab](/black-box/main-features/locking-prefabs) will appear to the user as if it was a single GameObject, with no additional components. This prevents unwanted overrides and simplifies workflows in a team.

However, BlackBox offers more tools than just locking. You can [reveal important properties](/black-box/main-features/reveal) that you need to override, and even [prevent the user from Applying](/black-box/main-features/disable-apply) those overrides.

{% embed url="<https://youtu.be/xv2GMUSP9u4>" fullWidth="false" %}

{% hint style="success" %}
BlackBox is **purely an Editor extension**. When building the game, the BlackBox components are stripped from Prefabs, so you can be sure that they will not interfere or have any impact on your builds.
{% endhint %}


# Changelog

### 2.0.2

(26/07/26)

**Changed**

* Changes in behaviour when Locking is disabled on the global level (Preferences > BlackBox > Unlock All Prefabs):
  * Revealed properties are now visible (they were not displayed before).
  * It now makes Overrides dropdown available even if Disable Apply is on. This is meant to facilitate override removal when the feature is used as a global debug toggle.

**Fixed**

* Better handling of selection in case Inspector is locked.
* Toggling global Disable Locking preferences now refreshes the Blackbox Inspector of the selected object.
* Fixed issue with BlackBox header not clickable that was affecting Unity 6.0 when gizmo visibility is disconnected from component header clicking (by setting Preferences > Scene View > Auto-hide Gizmos to false). Now clicking the header will correctly expand/contract the BlackBox Inspector in Unity 6.0.

## 2.0.0 - BlackBox 2.0

(02/07/26)

**Added**

* Child GameObjects [can now be revealed](/black-box/main-features/reveal/child-gameobjects) in the Hierarchy. When revealed, they appear in the Hierarchy exactly as they normally would. Their parent and ancestor objects are also shown (disabled), unless they are explicitly revealed as well.
* BlackBoxed Prefabs now can act as if unlocked while in PlayMode, meaning that all children and all components become visible. This can be useful when using the search feature of the hierarchy, as invisible objects wouldn't show up otherwise. This behaviour can be configured in [Project Settings](/black-box/other/project-settings).
* It is now possible to override both the properties of the BlackBox component and the lists revealed. This means that if you have a Prefab with a BlackBox and is configured in a certain way (say, it's unlocked, and has Disable Apply on); you can then use that Prefab as the base for a Variant, and override those settings only for the Variant. You can also add/remove elements to reveal lists in the variant or on nested instances. This allows to reveal properties or components on the Variant that were not present in the base Prefab.
* UX improvements:
  * Revealed elements of a list are now visualised as part of a reorderable list. This means they can be reordered easily, and you can multi-select more than one to remove them in bulk.
  * The last selected Reveal list is now remembered after recompilation, or if jumping between Prefabs that have the same source asset.
* New reveal types to annotate/decorate the BlackBox Inspector:
  * Header: adds a bold header, very much like the `[Header]` attribute on properties.
  * Comment: allows to add a comment, which appears as a HelpBox. Supports rich text and hyperlinks.
  * Separator: displays a thin line.
* Working with multiple selection: if all selected Prefabs are instances of the same asset, then Revealed items are visible and modifiable. The user can also Revert or Apply any override to them.
* New defaults in [Project Settings](/black-box/other/project-settings):
  * Whether newly added BlackBox components are locked by default.
  * Which [selection type](/black-box/other/selection-type) they use by default.

**Changed**

* The visibility of Reveal Lists has been reworked: while before each list was just either visible or not, now they can be configured to show or hide depending on where the list is being visualised. You have full power to choose where each lists is shown: scene instances of the Prefab, when the Prefab is used as a Variant root, when the Prefab is nested, or any combination of these contexts. This allows to fine-tune the workflows around lists.
* The UI for a Revealed method now says "Method" at the beginning in the internal Inspector – for consistency with other Reveal types.
* When [revealing methods](/black-box/main-features/reveal/methods), public methods from parent classes are displayed and can now be revealed as a button.
* BlackBox now has a presence in both Project Settings and Preferences. Settings are split between the two as it makes sense.
* Revealed localRotation fields now show the custom name chosen by the user.

**Fixed / Performance improvements**

* Checks on selection change have been optimised, now they only run when needed.
* Fixed revealing GO references showing up as broken.
* Much better handling of Undo, Redo, Apply and Revert. Now using these actions correctly updates the selected BlackBox's Inspector.
* Duplicating a Prefab that has no BlackBox no longer adds the component (even if Project Setting says to add it to new Prefabs).
* Plenty of bug fixes here and there.

### 1.9.1

(24/05/26)

* Fixed Method button randomly becoming very tiny on hover.
* Hide the Hats teams field if Teams are disabled in Hats 2.0.0.

## 1.9.0 - 2D Update

(11/11/25)

* It is now possible to set the [Selection Type](/black-box/other/selection-type) property to Use Sprite Renderers, to ensure that BlackBoxed Prefabs that contain SpriteRenderers select correctly in the Scene View.
* When [revealed](/black-box/main-features/reveal), properties of type SortingLayer now display with the correct dropdown field, which will allow the user to select the SortingLayer to use.
* Improved the reaction to changes to "Unlock All Prefabs" Project Setting. Even when switching the setting using the shortcut (Ctrl+Shift+U by default), BlackBoxed Prefabs in the scene or in Prefab Mode now react and update accordingly.
* Improved tooltip to Selection Type property, to make it clear that gizmos need to be on.

### 1.8.3

(17/04/25)

* Renamed setting "Disable Locking globally" to "Unlock all Prefabs"
* Menu item and shortcut to toggle Unlock All Prefabs.
* Better handling of Unlock All Prefabs value in the lock icon shown in the BlackBox Inspector.
* (Unity 2021) Removed click-catcher functionality to prevent 2021 users from ending up with a collapsed Inspector that they can't expand.

### 1.8.2

(30/12/24)

* Fixed a bug that prevented from orbiting the scene view camera or panning, on BlackBox instances where HideTransform was active.
* Now when Temp Unlocking the object is automatically expanded in the hierarchy.

### 1.8.1

(28/12/24)

* Fixed a bug with some components becoming invisible when Temp Unlocking a Prefab with a MeshRenderer on its root.
* Fixed an issue that made it possible to Temp Unlock Prefab assets.
* Improved how Material inspectors are hidden/shown for locked Prefabs.

## 1.8.0 - Temp Unlock & Hats integration

(17/12/24)

* Added Temp Unlock! Now, each BlackBox in the scene has a button that you can click to temporarily unlock it. Upon clicking away or changing scene, the Prefab is locked back automatically. This can be a huge timesaver if you frequently make overrides to specific Blackboxed Prefab instances.
* Added Hide Transform. You now have the ability to have BlackBox hide the Transform component too. This can be used to create unmovable Prefabs whose position can't be overridden.
* Initial integration with [Hats: Workspaces and Teams](https://tools.continis.io/hats) (Note: Hats is available as a [separate package](https://assetstore.unity.com/packages/slug/hats-workspaces-and-teams-283644) so this functionality is only visible if you also have Hats installed). Upon configuring a Prefab, you can now choose which Teams are allowed to edit it.
* When Disable Apply is on and the overrides dropdown is greyed out, now there is a tooltip that explains why.
* The component header for BlackBox now can be clicked, and it expands/collapses the component as expected. The Documentation button also works as expected.
* Reorganised all BlackBox secondary properties (that is: Hide Transform, Unlock If, Selection Type...) into one foldout, instead of two like before.
* Many more options in Project Settings to customise defaults.
* The BlackBox component icon is now more visible in the Inspector.

### 1.7.1

(24/11/24)

* BlackBox is now compatible with Unity 2021.3 (with [some caveats](https://tools.continis.io/black-box/pages/PzR6ZARYWl6g8X9VLvva#is-blackbox-compatible-with-unity-2021.3)).

## 1.7.0 - Object References

(19/08/24)

* Added Object References! Now in addition to properties, methods and entire component Inspectors, you can reveal a reference to a Component or a GameObject. This allows to assign that object as a reference by copy/pasting it in other locations, even if the object itself isn't visible.
* Behaviour of BlackBox can now be customised so it stays unlocked when nested in another Prefab.
* It can also be customised so it stays unlocked when used as the root of a Prefab Variant.
* You can now multi-select Prefab assets that have BlackBox, and mass-edit their base properties (Locked, Disable Apply, Hide Transform, etc.)
* Clicking on a GameObject header now pings the object in the hierarchy (if visible).
* Better handling of unlocked child BlackBoxes of unlocked BlackBoxes.
* Better handling of hiding components when selecting a Prefab asset that has BlackBox.
* Temporarily hiding the HideTransform property due to an Inspector issue. This will be re-enabled in the future. You can still modify the property by going into the Debug Inspector.

### 1.6.2

(09/08/24)

* Added the HideTransform property, to allow the user to choose to hide the BlackBox's own Transform or RectTransform alongside the other components (so that only the BlackBox component is visible).
* Inactive locked Prefabs are now correctly locked not only on scene load, but also when Unity is launched.
* Fixed a buggy behaviour that made RectTransforms disappear. They now stay visible.
* Fixed a bug with components added as an override just disappearing. They now stay visible also on locked BlackBox Prefabs.
* Improved handling of when BlackBox is added to a GameObject, which also solves the case of a Prefab using BlackBox that is unpacked in the scene.
* Fixed an error stating "SerializedObject of SerializedProperty has been Disposed" related to the BlackBox Inspector being destroyed.

### 1.6.1

(01/08/24)

* Added the ability to reveal all of the properties of a particular component, one by one, with one click. The user can then proceed to remove the ones they don't need. This helps with components that have tons of properties.
* Reveal all properties can also be invoked with a right-click on a component's header.
* More concise wording in contextual menus (i.e. "BlackBox > Reveal in...").
* Totally reworked look of GameObject headers.
* Revealed entire components now display as a foldout that can be collapsed. The foldout will remember its state, so the same component on the same Prefab will stay collapsed/expanded on all instances of that Prefab.
* Locked BlackBox Prefabs that have a MeshRenderer on the root now don't display empty Material editor blocks at the end of the Inspector.

## 1.6.0 - Reveal lists

(29/07/24)

* Each BlackBox component can now expose one or more lists of revealed items (up to 10), instead of only one list as before. Lists can be used to create different sets of revealed properties for different personas, like for instance, one for each sub-team in the company (designers, programmers, etc) or for each person on the team.
* Each list can have a name, which will be displayed on buttons that allow to switch between lists while working.
* A new button has been added to the component in Prefab Mode, to enter list editing mode. This mode allows to rename revealed lists and change their properties.
* Lists can be made invisible, so the button representing it won't show.
* For each list, you can specify whether or not to group the revealed items by the GameObject they belong to. Lists that don't group by GameObject won't show the GameObject headers, so all revealed items will be shown one after the other with no space in between.
* While editing lists, the revealed items of each list can now be easily reordered, just by using drag and drop.
* Right-clicking on the property of a child object now allows to choose which list to reveal the property in.
* Right-clicking on a component now allows to reveal that component on the first list.
* Improved creation of selection mesh for Prefabs that contain meshes with sub-meshes.

### 1.5.3

(18/07/24)

* Fixed an annoying bug with GUID clashes, happening when using BlackBox together with other assets.

### 1.5.2

(25/06/24)

* Added icon to the BlackBox component, but it's hidden by default in the scene (can be enabled in the Gizmos panel).
* New welcome screen, with useful links to documentation, email support, and more.

### 1.5.1

(18/06/24)

* Fixed external component breaking due to a UI rename.
* Removed custom indent for all properties. Now all Revealed properties use their original indentation.

## 1.5.0 - Reveal methods and components

(15/06/24)

* Added the ability to reveal public methods from components as buttons, alongside Revealed properties.
* Added the ability to reveal entire components on the BlackBox, using the original component's Inspector.
* A new mini-label in the Prefab Mode inspector makes it easy to identify what is the component that a certain property or method comes from, just by hovering over it.
* Added the ability to reveal UnityEvents as buttons, by decorating them with the attribute \[RevealEventAsButton].
* MUCH better error handling. Now the BlackBox will keep working even in case of missing properties and methods. In addition it will display their name before you remove them, so you can reconnect them again.
* Fixed a ton of inconsistencies in spacing.

## 1.4.0 - Odin Inspector support

(28/05/24)

* Added support for Odin Inspector! If a revealed property has an Odin Inspector attribute, you can ensure it draws correctly inside BlackBox by simply adding a \[RevealWithOdin] attribute to it.
* Better spacing for properties while being revealed (only in Prefab Mode).

### 1.3.2

(08/05/24)

* The header of the BlackBox component now appears as disabled in the scene, to discourage users from disabling or removing the component.
* Improved handling of Revealed properties that have been renamed or removed on the original component.

### 1.3.1

(25/04/24)

* Fixed selection mesh Gizmo not being drawn after a Prefab is selected for the first time.
* Added new selection type "Use SkinnedMeshRenderers". Useful for Prefabs representing characters.

## 1.3.0 - Disable Apply

(24/04/24)

* Added the ability to disable Applying overrides! It's a per-Prefab setting, that prevents the user from Applying overrides back to the source asset.
* Added a Project Setting to control whether newly-created BlackBox Prefabs have Apply disabled by default (this can be changed later, on each individual Prefab).
* Now it's possible to reveal the Active flag property for child GameObjects.
* Better styling, better tooltips, improved stability.

### 1.2.1

(06/04/24)

* Fixed BlackBox not hiding upon drag and drop directly into the scene.
* The component is now stripped from the build even for unlocked BlackBoxes.
* Fixed issue with Prefab being quickly dragged in and out of the Scene view.
* Fixed issue with selection mesh, when MeshFilter has null mesh.

## 1.2.0 - GameObject properties

(03/04/24)

* Added support for revealing GameObjects's basic properties (layers, GI flags, name, tag).
* Added support for revealing properties from child Transform components.

## 1.1.0 - Original release

(18/03/24)

<br>


# Troubleshooting

### I can't select BlackBox Prefabs in the scene

To be able to select a locked Prefab by its children, you need to have Gizmos enabled. You can enable them in the top-right corner of the Scene view.


# Locking Prefabs

The main feature of BlackBox is to lock Prefabs, to hide their complexity from the user.

<figure><img src="/files/97PAmYX1232rSw4q91PZ" alt="" width="563"><figcaption><p>The UI of the BlackBox of a locked Prefab</p></figcaption></figure>

A locked Prefab has two main characteristics:

* **Only the root GameObject** is displayed in the Hierarchy window, no children.
* **No components visible** in the Inspector other than the Transform and BlackBox itself.

This prevents creating overrides on the invisible objects and components by mistake. It is only possible to override the Transform's and the GameObject's base properties (static flags, layers, tags).

## How to lock a Prefab

Locking a Prefab is done by just adding the BlackBox component to it.

You can either:

* Open the Prefab in Prefab mode, and add the BlackBox component.
* Alternatively, you can add the BlackBox component to a GameObject in the scene and then turn it into a Prefab by dragging it into the Project view.

Both cases lead to the same result: the Prefab is now **locked** **for edits**.

<figure><img src="/files/SSwBgUUQWcgyyCZ1cmO7" alt=""><figcaption><p>A Prefab made of several objects, locked, appears as one GameObject in the scene</p></figcaption></figure>

Entering Prefab mode reveals the hidden aspects:

<figure><img src="/files/zNSNMDMQKgoPEpeWT86O" alt=""><figcaption><p>The same locked Prefab, now seen "from the inside"</p></figcaption></figure>

In Prefab mode, all children and root components become visible again, and editable.

{% hint style="success" %}
**Tip:** BlackBox has full support for Prefab nesting and Variants. Try nesting locked Prefabs, and see what happens!
{% endhint %}

## Unlocking a Prefab

While in Prefab mode, you can unlock the Prefab by just unchecking the **Locked** property in the Inspector. The Prefab now shows again all its children and components when seen outside of Prefab mode, but the BlackBox component is still there so it can be used at a later stage.


# Temp Unlock

In addition to fully [unlocking a Prefab](/black-box/main-features/locking-prefabs#unlocking-a-prefab), you can unlock a Prefab instance *temporarily*. While this can sound very similar, it has a few differences.

<figure><img src="/files/YO4JljpcEZC9Fhat4ndB" alt=""><figcaption></figcaption></figure>

Temp unlock displays the Prefab *as if it were* unlocked, without actually modifying its **Locked** property value. It's a great way to quickly make a few edits to a particular instance in the scene, then go back to locked state.

While a Prefab is temporarily unlocked, you can also operate on any of its children. Selecting another GameObject or asset will result in the Prefab re-locking again.

{% hint style="warning" %}
Only one Prefab instance at a time can be temporarily unlocked. Trying to temp unlock other instances will result in re-locking the first one.
{% endhint %}

{% hint style="warning" %}
You cannot temporarily unlock children of a temporarily unlocked Prefab. You can only temp-unlock a root.
{% endhint %}

## Unlocking a Prefab temporarily

To unlock a Prefab temporarily, simply click on the lock icon in the Inspector:

<figure><img src="/files/97PAmYX1232rSw4q91PZ" alt="" width="563"><figcaption><p>A locked Prefab displaying the Temp Unlock icon</p></figcaption></figure>

This unlocks the Prefab temporarily, revealing its components and children:

<figure><img src="/files/wt6yDQiSrLn9CiEBy2yA" alt="" width="563"><figcaption><p>A Prefab now temporarily unlocked, displaying two of its root components</p></figcaption></figure>

## Re-locking

As soon as you focus the selection on another Prefab or GameObject, open another scene or enter Prefab Mode, the temp unlocked Prefab goes back to its locked state.

You can also explicitly re-lock the Prefab by clicking on the Temp Unlock button shown above.

## Temp Unlocking using shortcuts

You can temporarily unlock and re-lock a Prefab using the **U** key shortcut. This shortcut can be modified from Unity's [Shortcut Manager](https://docs.unity3d.com/Manual/ShortcutsManager.html).

Using a shortcut is a great way to re-lock a Prefab from one of its children.

***

{% hint style="warning" %}
**Note:** Some Prefabs cannot be temporarily unlocked. This can happen if they are already fully unlocked, or if locking has been [disable altogether](/black-box/other/project-settings#disable-locking) in the Project Settings.

When a Prefab cannot be temporarily unlocked it will display an unlocked icon but no button:
{% endhint %}

<figure><img src="/files/5aKinF3OYSwCejnwGAMK" alt="" width="563"><figcaption><p>This Prefab cannot be temporarily unlocked</p></figcaption></figure>


# Extra locking options

As you edit a BlackBox in Prefab Mode, you will notice some extra options under the Options foldout:

<figure><img src="/files/GLPvCe2TIDBTEfDn7wGF" alt="" width="563"><figcaption><p>The Options foldout expanded</p></figcaption></figure>

These options allow you to customise how the Prefab behaves.

<table><thead><tr><th width="179.59375" valign="top">Property</th><th valign="top">Function</th></tr></thead><tbody><tr><td valign="top"><strong>Hide Transform</strong></td><td valign="top">When the Prefab is locked, the Transform (or RectTransform) component is hidden too. In addition, the Prefab cannot be moved, scaled or rotated in the scene view.</td></tr><tr><td valign="top"><strong>Keep Unlocked</strong></td><td valign="top">Note: Having both of these options off is the default scenario, where the Prefab behaves as locked regardless of where it's used.</td></tr><tr><td valign="top">    <strong>When Nested</strong></td><td valign="top">When the Prefab is nested under another Prefab, it is shown as unlocked even if its <strong>Locked</strong> property is set to true.</td></tr><tr><td valign="top">    <strong>If Variant Root</strong></td><td valign="top">When a Variant is created out of this Prefab and the Variant is being edited, the Prefab root shows as unlocked even if the original Prefab was set to be locked.</td></tr><tr><td valign="top"><strong>Selection Type</strong></td><td valign="top">The substitute selection mesh to allow selecting children made invisible by BlackBox. (<a href="/pages/RAbdmFyU9MOIa495hW8e">more details</a>)</td></tr></tbody></table>


# Reveal

Sometimes you have a Prefab that you want to [lock](/black-box/main-features/locking-prefabs), but for which it would still make sense to expose parts of it. BlackBox provides the ability to reveal several aspects of a Prefab, to keep the important parts while all the rest is hidden.

You can reveal:

* [Properties](/black-box/main-features/reveal/properties)
* [Methods](/black-box/main-features/reveal/methods) or [UnityEvents](/black-box/main-features/reveal/properties/unityevents-as-buttons) as buttons
* [Child GameObjects](/black-box/main-features/reveal/child-gameobjects) in the Hierarchy
* [Object references](/black-box/main-features/reveal/object-references)
* Or even [entire Components](/black-box/main-features/reveal/entire-components)

Check each page for more specific information on all these items.

<figure><img src="/files/RdrgKIhv7kMWeGWOYmja" alt="" width="375"><figcaption><p>A BlackBox component revealing an AudioClip property,<br>some debug audio methods as buttons, and the volume of an AudioSource component</p></figcaption></figure>

{% hint style="success" %}
**Tip:** You don't need to [lock a Prefab](/black-box/main-features/locking-prefabs) to be able to reveal items on it.

You can use this pattern to highlight some properties that you need often, by surfacing them in the BlackBox component on the root.
{% endhint %}


# Properties

Revealed properties are like **shortcuts** that show up in the BlackBox Inspector that link to properties on child objects. Even though it might look like it belongs to the BlackBox component, modifying one of these properties means modifying the original property.

As an example, let's imagine a Prefab that has a MeshRenderer component on one of its children, and we decide to reveal the **Materials** property of this component. Once we swap Material by assigning a new one, the familiar override blue line shows that we have created an override on the **Materials** property.

<figure><img src="/files/wyqcT1rRWrAq6WviYsDO" alt="" width="563"><figcaption><p>The Material property has an override</p></figcaption></figure>

Opening the Overrides dropdown clearly shows that the override is sitting on the correct object (the MeshRenderer component, in the image below), and not on the BlackBox component.

This means that if we were to Apply these changes, they would be applied to the correct sub-object.

<figure><img src="/files/UschnJund2MybIerwChn" alt=""><figcaption><p>The override is displayed on the object it belongs to, and not on the BlackBox component</p></figcaption></figure>

## Revealing properties

There are two ways to reveal a property:

### On the BlackBox component

To get started, press the **Show Available Properties and Methods** button in the BlackBox component:

<figure><img src="/files/tit0NYJAsdliKv10sX4L" alt="" width="546"><figcaption></figcaption></figure>

Under the button, a list of the GameObjects contained in the Prefab will show as foldouts. By opening them, you will see the components belonging to those GameObjects. Opening them again displays the properties, which will show a preview of the current value.

Properties are preceded by a small **\[P]** letter, like the **Mesh** property on the MeshFilter here:

<figure><img src="/files/txo22jnpMnjavLhfCpwk" alt="" width="563"><figcaption><p>Inspecting the properties and methods that are available<br>to reveal from the Platform_4x4_Empty child object</p></figcaption></figure>

{% hint style="success" %}
**More than just properties**

You probably noticed in the screenshot above how – in addition to individual properties - [public methods](/black-box/main-features/reveal/methods) **\[M]** and [entire components](/black-box/main-features/reveal/entire-components) **\[C]** can also be revealed.
{% endhint %}

Press the **\[+]** button on each property you want to reveal. The property will be added to a list at the top, and once added, you will be able to provide a name for it. This name will show up instead of the actual property name.

<figure><img src="/files/hqyynSZhsIrhIwtbeXLp" alt="" width="563"><figcaption><p>A position property has been added to the reveal list,<br>and renamed to appear as Door position</p></figcaption></figure>

Revealed properties can be removed again by clicking on the **\[-]** button.

Once we inspect the Prefab in the scene, any revealed property will show up in the Inspector of the BlackBox component using the custom name we have specified during their configuration, and will be editable now:

<figure><img src="/files/bno9fZYMxci4SQcdU9us" alt="" width="563"><figcaption><p>The Door position property as it appears on the locked Prefab</p></figcaption></figure>

{% hint style="success" %}
**Do your scripts have tons of properties?**

When you expand a dropdown, immediately under the Entire Component line, you'll see a line called **All properties individually**. By clicking this button, all of the component's properties will be revealed individually. This means that later on you can refine the list and just remove a few, if you need to.

Revealing properties in bulk like this can really speed up Prefab setup in case of complex scripts.
{% endhint %}

### Via the context menu

In addition to the above, there is a quick and handy way to reveal a property. Just navigate to the Component that contains that property, right-click on it. Under the menu **BlackBox**, you can choose [which list](/black-box/main-features/reveal/reveal-lists) to reveal the property in:

<figure><img src="/files/Ue6WIMfCSqeipEGkJSCU" alt="" width="563"><figcaption></figcaption></figure>

Done!

{% hint style="info" %}
Not all properties can be revealed this way. If you right-click on one and you don't see the option, you have to reveal it using the method described in the previous section.
{% endhint %}

### All properties individually via the context menu

Just like individual properties, it's possible to reveal all properties of a component at once by right-clicking on the component's header, and choosing **BlackBox > All Properties > Reveal in...**, choosing then which [Reveal list](/black-box/main-features/reveal/reveal-lists) you want to add the properties to.

<figure><img src="/files/xwuPaq10lXdXIC3D3M2n" alt="" width="563"><figcaption><p>Right-click on a component header to reveal all properties</p></figcaption></figure>

{% hint style="info" %}
**First List, Second List... what are they?**

Unfortunately, a Unity limitation means we can't display the custom names that you might have assigned to [Reveal lists](/black-box/main-features/reveal/reveal-lists), and that's why they are displayed as First List, Second List, etc. up to 5 lists.

To add properties to a higher number list, you can move the list in one of the first 5 positions, add the properties, and move it back (using the reorder buttons in [Edit mode](/black-box/main-features/reveal/reveal-lists#edit-lists)).
{% endhint %}


# UnityEvents as buttons

While you can reveal `UnityEvent` type properties just [like any other](/black-box/main-features/reveal), you can also decide to reveal them as a button, very much like you can do [with methods](/black-box/main-features/reveal/methods).

However, revealing a `UnityEvent` as a button allows you to specify one argument for each method invoked, and to invoke multiple methods at once (which is exactly what `UnityEvent` supports), making it a much more powerful tool.

## Revealing a UnityEvent as a button

If a `UnityEvent` property is revealed, by default it will just show with its regular UI:

<figure><img src="/files/I1CukWJYzI2KFUZsMO3n" alt="" width="563"><figcaption><p>A revealed UnityEvent</p></figcaption></figure>

To display it as a button, the property needs to be decorated with a `[RevealEventAsButton]` attribute, like this:

```csharp
[RevealEventAsAttribute] public UnityEvent _certainConditionEvent;
```

Once the code compiles, the `UnityEvent` will now show up as a button:

<figure><img src="/files/ig5ocs3GTWeHjdTxXcrs" alt="" width="563"><figcaption><p>The same UnityEvent now displayed as a button</p></figcaption></figure>

{% hint style="info" %}
If the `UnityEvent` has no callbacks setup, the button will show up as disabled.
{% endhint %}


# Entire components

In addition to revealing [individual properties](/black-box/main-features/reveal#what-is-a-revealed-property), sometimes it's more handy to reveal entire components at once. This can be very useful to speed up the process of adding several properties.

In addition, it can be a way to get the UI of a property that was drawn in a very specific way in the original component it belongs to, where adding the single property wouldn't give the same result.

<figure><img src="/files/X0kd66jORnFva1HD3pKt" alt="" width="563"><figcaption><p>An entire RectTransform component (from child Canvas)<br>has been revealed on the BlackBox</p></figcaption></figure>

## Revealing entire components

To reveal a component, you can do it in two ways:

### On the BlackBox component

This is done exactly [as it's done for properties](/black-box/main-features/reveal#on-the-blackbox-component).

Click on the **Show available properties and methods** button on the BlackBox, and expand the foldouts until you arrive to the component you're interested in.

Components are preceded by a small **\[C]** letter:

<figure><img src="/files/qZhAnmFRezUe8xxO8iz0" alt="" width="506"><figcaption><p>The letter C denotes an entire component</p></figcaption></figure>

Press the **\[+]** button to add the component to the reveal list. The component will be visualised as a collapsed foldout in Prefab Mode, in order not to take too much space:

<figure><img src="/files/rSPwU16PDFziGZQAxnEU" alt="" width="506"><figcaption><p>The RectTransform shows up as one of the revealed aspects</p></figcaption></figure>

When seeing the object in the scene though, the component is shown with all its properties, and all the eventual custom property drawers:

<figure><img src="/files/X0kd66jORnFva1HD3pKt" alt="" width="563"><figcaption></figcaption></figure>

{% hint style="info" %}
When a component is revealed in its entirety, BlackBox hides the property that identifies the script used (the SerializedProperty `m_Script`), for the sake of brevity.
{% endhint %}

### Via the context menu

Just like for properties, components can also be revealed in context. While you have the right GameObject selected, right-click the component's title bar and choose **BlackBox > Entire Component > Reveal in...**, like so:

<figure><img src="/files/SV59ntyN0flASbKjWAwq" alt="" width="563"><figcaption><p>Right-click to reveal an entire component in one of the Reveal lists</p></figcaption></figure>

{% hint style="info" %}
**First List, Second List... what are they?**

Unfortunately, a Unity limitation means we can't display the custom names that you might have assigned to [Reveal lists](/black-box/main-features/reveal/reveal-lists), and that's why they are displayed as First List, Second List, etc. up to 5 lists.

To add components to a higher number list, you can move the list in one of the first 5 positions, add the component, and move it back (using the reorder buttons in [Edit mode](/black-box/main-features/reveal/reveal-lists#edit-lists)).
{% endhint %}


# Child GameObjects

While you normally want a locked Prefab to be shown as one object, it is possible to reveal important children GameObjects that – for some reason – need to stay visible and editable.

When revealed, they appear in the Hierarchy as they normally would:

<figure><img src="/files/QQPItbnAFbMj5oRDaxEW" alt=""><figcaption><p>A locked Prefab, with a level 1 child revealed</p></figcaption></figure>

If the revealed child is not a direct child of the root, its direct parent and other ancestors will also appear, but they will be shown as disabled (unless they are also intentionally set to be revealed):

<figure><img src="/files/gSrejSs3PmwTd0uRtm6u" alt=""><figcaption><p>A locked Prefab that had a level 3 child revealed. Its ancestors also appear, but disabled.</p></figcaption></figure>

## Revealing child GameObjects

To reveal a child GameObject, you can do it in two ways:

### On the BlackBox component

Click on the **Show Revealable Items** button on the BlackBox, and expand the foldouts until you arrive to the GameObject or component you're interested in.

Child GameObjects are preceded by a small **\[GO]** icon:

<figure><img src="/files/626I1MtagXxTNJJeepq8" alt=""><figcaption></figcaption></figure>

Press the **\[+]** button to add the GameObject to the reveal list.

### Via the context menu

Child GameObjects can also be revealed in context.

In the Hierarchy, select a child, right-click and choose **BlackBox > Child GameObject > Reveal in the xxx list**. Revealing a child GO this way will reveal it using its Transform.

Alternatively, you can right-click any component in the Inspector and choose **BlackBox > Child GameObject > Reveal using this component in the xxx list**. Revealing it this way will use the component that was right-click (see below).

## Which components are displayed?

When revealing GameObjects, you can choose which component(s) to reveal the child with. Revealed components are visible and editable, but the other components aren't.

For instance, a child GameObject revealed with its Transform will only show the Transform when inspected. If that object is revealed using its BoxCollider, then it will only show that and not the Transform.

{% hint style="info" %}
It is possible to reveal the same GameObject multiple times using each time a different component. This makes it so that the GameObject will display all of the revealed components.

For instance, in the example above, one could reveal that GameObject via its Transform and its BoxCollider.
{% endhint %}

<figure><img src="/files/z8pFrAHBFBuKiKBeT7C6" alt=""><figcaption><p>A child revealed multiple times using 2 of its components. These components are going to be both visible in the Inspector when that child is selected.</p></figcaption></figure>


# Object references

It's a common pattern in Unity to reference objects and components from one Prefab to another. A simple example is Cinemachine: to target an object with a camera, you normally assign that object's Transform to the **Tracking Target** property of a CinemachineCamera.

<figure><img src="/files/sr3QLjjitcF2ESP87sYn" alt="" width="563"><figcaption><p>A CinemachineCamera needing to reference a Transform as a target</p></figcaption></figure>

But how to do it when the object you want to assign **simply isn't visible**, because it's a child of a locked Prefab?

This is why you might want to expose an object reference on the BlackBox. When you do so, the reference will be visualised as an ObjectField without the little circular "picker icon":

<figure><img src="/files/xPnPpUNFka9zJeP3WDx0" alt="" width="563"><figcaption><p>The object reference as seen on the BlackBox component, in the scene</p></figcaption></figure>

From here, you can right-click on the field and choose **Copy**, and then paste where you need this reference.

{% hint style="success" %}
You will notice that trying to change the reference or nulling it shouldn't work, so you can't break the reference involuntarily with an override while you work on the Prefab.
{% endhint %}

## Revealing object references

To reveal a reference, you can do it in two ways:

### On the BlackBox component

Click on the **Show Available Properties and Methods** button on the BlackBox, and expand the foldouts until you arrive to the gameObject or component you're interested in.

Object References are preceded by a small **\[R]** letter:

<figure><img src="/files/fWA8jOjEKzdHZc3y88U0" alt="" width="563"><figcaption></figcaption></figure>

Press the **\[+]** button to add the component or gameObject to the reveal list.

### Via the context menu

References to components can also be revealed in context. While you have the right GameObject selected, right-click the component's title bar and choose **BlackBox > Reference to Component > Reveal in...**, like so:

<figure><img src="/files/H6YQhN6Hx9dWr93IeWqa" alt="" width="563"><figcaption></figcaption></figure>

{% hint style="info" %}
**First List, Second List... what are they?**

Unfortunately, a Unity limitation means we can't display the custom names that you might have assigned to [Reveal lists](/black-box/main-features/reveal/reveal-lists), and that's why they are displayed as First List, Second List, etc. up to 5 lists.

To add components to a higher number list, you can move the list in one of the first 5 positions, add the component, and move it back (using the reorder buttons in [Edit mode](/black-box/main-features/reveal/reveal-lists#edit-lists)).
{% endhint %}


# Methods

In addition to revealing [properties](/black-box/main-features/reveal) and [entire components](/black-box/main-features/reveal/entire-components), you can visualise buttons on a BlackBox to invoke public, parameter-less methods of any component:

<figure><img src="/files/RdrgKIhv7kMWeGWOYmja" alt="" width="563"><figcaption><p>This Prefab exposes three methods as buttons</p></figcaption></figure>

This can be useful to invoke editor-time functionality directly from a Prefab's root, like baking a Navmesh, randomising the position of children objects programmatically, etc.

## Revealing methods on the BlackBox

Like for properties, exposing methods can be done from the `BlackBox` component by entering Prefab Mode, and clicking on the **Show available properties** button:

<figure><img src="/files/cnO93OxpHa7rDEQwPPhi" alt="" width="506"><figcaption></figcaption></figure>

This exposes the list of children and all of their components. Open a component to visualise another foldout called **Public methods**. Open this one to display all available public methods, which are preceded by a tiny **\[M]**:

<figure><img src="/files/6RlJAbVzUYVibLTxAIJL" alt="" width="563"><figcaption><p>Methods available are denoted by an M icon</p></figcaption></figure>

{% hint style="warning" %}
Note that only methods with no parameters will show up in the list. To invoke a method with parameters, consider [revealing UnityEvents](/black-box/main-features/reveal/properties/unityevents-as-buttons) as a button instead.
{% endhint %}

Press on the **\[+]** button to add the method to the reveal list:

<figure><img src="/files/RzXkZdtlY7v8yvqB1K7J" alt="" width="563"><figcaption><p>Two methods have been revealed</p></figcaption></figure>

Here you can customise the button's label, just like it's done for properties, and remove them again with the **\[-]** button.

Now, by exiting Prefab Mode, you will be able to see the buttons on the Prefab, and click them both in Edit and Play mode.


# Reveal lists

When revealing aspects of a Prefab each property, method or component is revealed as part of a "reveal list".

**Reveal lists** can be used to customise how a locked Prefab looks to different members on the team, or even to the same person, while they are performing different tasks.

<figure><img src="/files/fQlapqP3pZ5snebQPBZh" alt="" width="563"><figcaption><p>The same BlackBox Prefab can look very different depending on the list selected</p></figcaption></figure>

For example:

* On a "Game Manager" Prefab, programmers can create a reveal list that exposes almost everything on the GameManager component, while everyone else on the team sees the Prefab as a complete black box.
* On a player Prefab, you can have a list that exposes **Speed** and **JumpHeight** properties on a character controller script to tweak its movements, and one that exposes only **Health** and **AttackPower** for when you are working on combat.

Each BlackBox component can contain up to 10 lists of revealed items.

### Switch the active list

To move between lists, simply click on the buttons that show up in the BlackBox Inspector.

<figure><img src="/files/UD7opAtqjftGJhGl34mD" alt="" width="563"><figcaption><p>Three lists are visible, and the first is currently selected</p></figcaption></figure>

{% hint style="info" %}
You will not see any button if there is only one visible list.
{% endhint %}

### Add and remove items

Adding items to lists is done by clicking the **Show Available Properties and Methods** button in the Inspector of the BlackBox component, or by performing one of the actions described in the [Properties](/black-box/main-features/reveal/properties), [Methods](/black-box/main-features/reveal/methods) or [Components](/black-box/main-features/reveal/entire-components) pages.

Removing items is simply done by clicking the **- (minus)** button next to a list item, while in Prefab mode.

### Edit lists

In addition to the elements they contain, lists have different properties.

To edit the properties of a list (including its name), open the BlackBox Prefab and click on the **Edit Lists** button. This enters edit mode.

<figure><img src="/files/N6voEqUzfJTjv9GwNzdB" alt="" width="563"><figcaption><p>Lists edit mode</p></figcaption></figure>

While in edit mode, you can edit:

<table><thead><tr><th width="230.19140625" valign="top">Property / Button</th><th valign="top">Function</th></tr></thead><tbody><tr><td valign="top"><strong>Name</strong></td><td valign="top">This is the name that displays on the list buttons.</td></tr><tr><td valign="top"><strong>Visible</strong></td><td valign="top">Controls the list's visibility. If set to off, a button will not be displayed for this list, and the list will not be selectable once out of edit mode.</td></tr><tr><td valign="top"><strong>Group by GameObject</strong></td><td valign="top">If this option is enabled, when the list is laid out it will group its elements by the GameObject they belong to.</td></tr><tr><td valign="top"><strong>Reorder list elements</strong></td><td valign="top">Allows to reorder the elements of a Reveal list. Simply drag them up and down to change the order in which they will appear.</td></tr><tr><td valign="top"><strong>Empty list</strong></td><td valign="top">Clears all the revealed items in a list, without deleting the list itself.</td></tr><tr><td valign="top"><strong>Delete list</strong></td><td valign="top">Removes the list entirely.</td></tr><tr><td valign="top"><strong>Arrow buttons</strong></td><td valign="top">These buttons allow to reorder the lists themselves.</td></tr></tbody></table>

{% hint style="info" %}
**Reordering, and Group by GameObject**

When a list is set to group revealed items by GameObject, it might seem to you that the pure order of the elements is not respected. This is because elements are listed by GameObjects first, and then in the order specified.

So for instance, the last element in the list might not show up as last, if another element from the same GameObject is further up in the list.

To achieve exactly the order you want, you need to turn **Group by GameObject** of&#x66;**.**
{% endhint %}


# Disable Apply

When revealing properties, you might be opening a new "vulnerability" in the workflow: by default in Unity any property that is overridden can be Applied back to the original asset, potentially creating problems for everyone else using that Prefab.

For this, BlackBox offers the possibility to **disable Apply**, preventing the Prefab user from Applying overrides to the asset.

<figure><img src="/files/t5ltLtY5HLW2pHRiaO80" alt="" width="479"><figcaption><p>Right-clicking on an overridden property, it is possible to Revert but not to Apply</p></figcaption></figure>

{% hint style="success" %}
**Tip:** You don't need to [lock a Prefab](/black-box/main-features/locking-prefabs) for Disable Apply to work, though often the two workflows go hand in hand.
{% endhint %}

## How to disable Apply

Disabling Apply is simply done by opening a Prefab with the BlackBox script in Prefab Mode, and checking the box **Disable Apply**:

<figure><img src="/files/xoOdzNEMC23tswOAFR8q" alt="" width="563"><figcaption></figcaption></figure>

When you go back to the scene, you will notice that right-clicking on an overridden revealed property brings up the dropdown menu as usual, but **Apply is not available**.

The user can still choose at any time to Revert the property to the original asset's value.

{% hint style="info" %}
Note that when disabling Apply, the whole Overrides dropdown is also disabled. This is in order to prevent operations like Apply all or Applying entire components. To Revert All, you have to Revert properties by right-clicking on them one by one, or turn **Disable Apply** off temporarily, Revert, and then turn it back on.
{% endhint %}


# Odin Inspector

BlackBox integrates with [Odin Inspector](https://odininspector.com/), and can display most of its attributes correctly for properties that [have been revealed](/black-box/main-features/reveal) in the BlackBox component.

{% hint style="warning" %}
Please note that when Odin is installed in your project, you will **lose the ability** to [right-click > "Reveal on BlackBox"](/black-box/main-features/reveal#via-the-context-menu) in all Inspectors drawn by Odin. You can still reveal properties [from the BlackBox component](/black-box/main-features/reveal#on-the-blackbox-component).
{% endhint %}

## How to enable Odin integration

First, obviously, you need to have Odin Inspector in your project. This should automatically add some scripting define symbols to your project. If you're in doubt, go to **Project Settings > Player > Other settings > Scripting Define Symbols**, and ensure that the symbol `ODIN_INSPECTOR` is there:

<figure><img src="/files/mAovBuBBki3eOQGbQgZ4" alt=""><figcaption></figcaption></figure>

## Revealing a property with Odin

By default, if you reveal a property that uses one of Odin's attributes, it will just display with its original, Unity-official property drawer. Let's assume for instance a property decorated with `[RangeSlider]`:

```csharp
[MinMaxSlider("DynamicRange", true)]
public Vector2 DynamicMinMax = new Vector2(25, 50);
public Vector2 DynamicRange = new Vector2(0, 50);
```

By default, once revealed, this property would just show as a Vector2:

<figure><img src="/files/kttBSHUPTBE4zX34Bd8A" alt="" width="563"><figcaption></figcaption></figure>

To ensure it displays correctly, you need to add the `[RevealWithOdin]` attribute:

{% code fullWidth="false" %}

```csharp
[MinMaxSlider("DynamicRange", true), RevealWithOdin]
public Vector2 DynamicMinMax = new Vector2(25, 50);
public Vector2 DynamicRange = new Vector2(0, 50);
```

{% endcode %}

With it, it will automatically display as expected:

<figure><img src="/files/guHlsBu2eZIYplhaCQCz" alt="" width="563"><figcaption></figcaption></figure>

## Caveats

When revealing a property that is decorated with an Odin attribute, there are some things to keep in mind:

* Not all attributes are supported. Especially the ones heavily modifying the layout (like `[Box]` or `[FoldoutGroup]`) will not work.
* You won't be able to reveal Odin properties by [right-clicking the original property](/black-box/main-features/reveal#revealing-properties-via-context-menu) and choosing "Reveal with Blackbox". You need to find the property on the BlackBox component, by clicking the "Show Available Properties" button (as described [here](/black-box/main-features/reveal#on-the-blackbox-component)).
* Even if you [disable Apply](/black-box/main-features/disable-apply) for a particular prefab, the user will always be able to Apply on Odin-decorated properties. This is unfortunately something we cannot override.
* Odin-decorated properties don't play well with the Prefab system, and don't support nested Prefabs. This is a general Odin limitation, and something we don't have control on.

If a property is misbehaving or doesn't look correct, just remove the `[RevealWithOdin]` from it to draw it again using its default Unity-provided Property Drawer.


# Hats - Workspaces and Teams

BlackBox integrates with [Hats - Workspaces and Teams](https://assetstore.unity.com/packages/tools/utilities/hats-workspaces-and-teams-283644).

When you have both tools installed, you can make it so some Prefabs can only be edited by certain Hats teams. This reinforces areas of ownership, and can prevent edits on key Prefabs.

<figure><img src="/files/mYXVhX4lHP8nCJZhDw4Q" alt="" width="563"><figcaption><p>A Prefab that can be edited by Artists and Programmers, but not Producers</p></figcaption></figure>

{% hint style="info" %}
As a general rule of thumb, we suggest only locking a few key Prefabs out, and leaving most of them editable by the whole team/studio.
{% endhint %}

## How to specify teams

To use this feature, you first need to setup different teams in Hats. This is described in Hats' [Teams documentation](https://tools.continis.io/hats/teams/teams).

Once you have one or more teams, simply open a Prefab that has a BlackBox in Prefab mode. A property called **Allow Editing From** should be visible just before the Reveal Lists (see screenshot above).

Using this dropdown, specify the teams that can edit the Prefab.

{% hint style="warning" %}
If you are part of a team and you deselect it from this dropdown, you will lock yourself out of the Prefab. To be able to edit the Prefab again, either revert the Prefab using version control, or change team temporarily and edit the Prefab again.
{% endhint %}


# Selection type

When a Prefab is locked and child objects are hidden in a scene view, a side effect is that Unity will not allow you to click on them to select the object. This leads to the very undesirable effect of being able to select the Prefab only by clicking on its root object.

To deal with this, BlackBox creates **a selection mesh** out of all the meshes contained in the Prefab, that is used to select the object on click. The creation of this mesh is done only in the editor, when you open a scene.

{% hint style="success" %}
Most of the time you can just ignore this setting and leave it on its default value.
{% endhint %}

If the Prefab has many sub-objects and they are very complex geometry, the mesh generation could be expensive. For this reason, BlackBox offers the ability to choose from various methods of generating it.

The available options are:

* **Use Bounding Boxes** (the default): the resulting mesh is a combination of individual Bounding Boxes (see [Bounds](https://docs.unity3d.com/ScriptReference/Bounds.html) in Unity's docs). This is less precise, but cheaper. This should be perfect for most Prefabs.
* **Use 3D Meshes**: the resulting mesh is a combination of the actual 3D meshes inside the Prefab. This gives you perfect selections, but it can impact the editor performance more. We suggest to enable it only if the meshes have a lot of holes or concave shapes.
* **Use Skinned Mesh Renderers:** the same as Use 3D Meshes, but this is intended to be used for animated characters.
* **Use Sprite Renderers:** intended to be used for Prefabs that contain Sprite Renderers. It creates a mesh out of the shape of all Sprites rendered by child objects.
* **Use Root Object**: no mesh is created, and only the root object will be considered to create a selection. However if there is no MeshFilter on the root object, a 1x1x1 cube mesh is created. This is good for particle systems, helper objects, and other Prefabs that have no 3D meshes.

<figure><img src="/files/wZIA3hhq11M7b1i4akaH" alt=""><figcaption><p>A comparison of Use 3D Meshes vs. Use Bounding Boxes selection types</p></figcaption></figure>

The setting can be modified for each `BlackBox` component individually.

{% hint style="danger" %}
**Unity 6 Preview**

If you're using Unity 6 Preview, there is an issue with selection. Read about it in our [Troubleshooting](/black-box/troubleshooting) page.
{% endhint %}


# Project Settings

Go to **Edit > Project Settings > BlackBox** to customise BlackBox.

<table><thead><tr><th width="255.9765625" valign="top">Setting</th><th valign="top">Function</th></tr></thead><tbody><tr><td valign="top"><strong>Auto-add BlackBox Component</strong></td><td valign="top"><p>Control whether a BlackBox component gets automatically added to newly created Prefabs.</p><p>Regardless of the setting, an added BlackBox component can be removed at any point (and it won't be automatically re-added).</p></td></tr><tr><td valign="top">To New Prefabs</td><td valign="top">Adds the component to new base Prefabs.</td></tr><tr><td valign="top">To New Prefab Variants</td><td valign="top">Adds the component to new Prefab Variants.</td></tr><tr><td valign="top"><strong>Defaults For New Black Boxes</strong></td><td valign="top">Control the default value for properties on newly-added BlackBox components.</td></tr><tr><td valign="top">Locked</td><td valign="top">Newly added BlackBox components are locked by default.</td></tr><tr><td valign="top">Disable Apply</td><td valign="top">Apply is disabled by default.</td></tr><tr><td valign="top">Hide Transform</td><td valign="top">The Transform component is hidden by default.</td></tr><tr><td valign="top">Unlock When Nested</td><td valign="top">Unlock When Nested is on by default.</td></tr><tr><td valign="top">Unlock If Variant Root</td><td valign="top">Unlock If Variant Root is on by default.</td></tr><tr><td valign="top">Selection Type</td><td valign="top">The <a href="/pages/RAbdmFyU9MOIa495hW8e">Selection type</a> that the component will have by default.</td></tr><tr><td valign="top"><strong>General</strong></td><td valign="top"></td></tr><tr><td valign="top">Enable Temp Unlocking</td><td valign="top"><p>By default, the <a href="/pages/Bg7r0DCJP2O3MGUX69Fa">Temp Unlocking</a> workflow is enabled.</p><p>However, since it can be used to create overrides, it might be in some teams' interest to disable it. By unchecking this option you can disable it for the whole team.</p></td></tr><tr><td valign="top"><strong>User-specific Preferences</strong></td><td valign="top">The preferences in this section are per-user, and won't be shared with other users on the project.</td></tr><tr><td valign="top">Unlock All Prefabs</td><td valign="top">At any time, you can <strong>disable</strong> the functionality of BlackBox without having to remove the component from individual Prefabs. You can use this to temporarily disable all functionality in case BlackBox is interfering with a workflow.<br>You can also turn this option on/off from the menu <strong>Tools > BlackBox > Unlock All Prefabs</strong>, or by hitting <strong>Shift + Ctrl + U</strong> on PC, or <strong>Shift + Cmd + U</strong> on Mac. This shortcut can be modified from Unity's <a href="https://docs.unity3d.com/Manual/ShortcutsManager.html">Shortcut Manager</a>.</td></tr></tbody></table>


# Intro

🔗 Available on the [**Unity Asset Store**](https://bit.ly/subassettoolbox_as)

Sub-assets have been a feature in Unity since the very early days. But outside of some default types (Animation Clips, Meshes, Materials) generated as a result of an import, it is rare to see developers use them in their games. Because of so many **missing workflows**, they can only be used when a programmer takes the time to create their own tooling around them.

**SubAssets Toolbox** provides native and intuitive workflows to work with sub-assets, for programmers as well as the rest of the team.

<figure><img src="/files/X0rUMGiuwuzGRx1aoIIV" alt=""><figcaption><p>A ScriptableObject containing several sub-assets of different types</p></figcaption></figure>

Get started by learning the [editor workflows](/subassets-toolbox/editor-workflows/adding-sub-assets), or explore the [included API](/subassets-toolbox/api/isubassetaware) that you can leverage in your project.


# Changelog

## 1.1.0 - Patch References and Addressable Assets

* When creating or removing a sub-asset, SubAssets Toolbox can now [patch references](/subassets-toolbox/editor-workflows/patch-references) to it for you. All references to the "disappearing" asset will be patched to point to the newly created one. This prevents broken references when moving assets around.
  * This behaviour is optional, and can be controlled in Project Settings.
  * You can control the list of file formats that gets scanned and patched in Project Settings.
* Sub-assets can now be renamed, either via right-clicking or by pressing the shortcut for renaming files (F2 or Enter, depending on the platform).
* SubAssets Toolbox is compatible with Addressable Assets. When relocating sub-assets, the tool will create or remove entries from the AA Groups to account for the new or removed assets.
* Fixed a warning due to an obsolete API in Unity 6.3.
* Raised minimum supported version to Unity 2022.3.

### 1.0.5

(08/09/25)

* Hotfix: Corrected a misspell in a compilation directive that was meant to target Unity 6 and newer.

### 1.0.4

(07/09/25)

* When un-parenting a sub-asset by drag and drop, SubAssets Toolbox now attempts to assign the correct extension to the newly created file (versus before, where all assets would end up with .asset). If it can't guess the extension from the type, it warns the user in the Console.
* Fixed an issue that would happen when right-click > creating a Material while a Shader was selected. The Material is now correctly created outside the Shader file, and will use the selected Shader as its shader (default behaviour).

### 1.0.3

(26/05/25)

* Fixed an issue where an error was printed to the console when creating Prefabs or Prefab Variants.

### 1.0.2

(15/03/25)

* Added checks to prevent adding Sub-Asset of illegal types (.cs, .prefab, .meta).
* Added check to prevent adding a Sub-Asset to a script.
* Improved error messages.

### 1.0.1

(18/07/24)

* Fixed issue with GUIDs clashing
* Fixed Welcome window not appearing

## 1.0.0 - First release

(10/07/24)

* Drag assets on top of others to make them sub-assets.
* Remove sub-assets by dragging them away, to turn them into independent assets.
* Drag and drop supports multi-selection (also of a mix of assets and sub-assets).
* Ctrl+Delete shortcut to delete a sub-asset.
* Right-click > Delete Sub-Asset(s) on a selection of sub-assets to delete them.
* Right-click > Create menu while an asset is selected, the newly-created asset is immediately added as a sub-asset.
* ISubAssetAware interface
* SubAssetAwareSO sample class, with custom inspector
* Welcome window


# Adding Sub-Assets

## Drag and drop

To add one or more Sub Assets to an existing asset, simply select the ones you want to add and drag them on top of another asset.

<figure><img src="/files/H63Cy6s5C5SVkO6cfy0v" alt="" width="375"><figcaption><p>Dragging SecondaryMission_1 on top of MainObjective</p></figcaption></figure>

You will be presented with a popup:

<figure><img src="/files/7LfqAr77IbR5QKxaYkUq" alt="" width="375"><figcaption></figcaption></figure>

**Add**

By choosing to just Add, the dragged asset will be added as a sub-asset to the destination and disappear from its original location.

<figure><img src="/files/VEJS54ZdRbDvjmJhm2rA" alt="" width="316"><figcaption><p>SecondaryMission_1 is now a sub-asset</p></figcaption></figure>

**Add and Keep Original**

By choosing this the original asset will stay in its place, and a new copy will be added to the destination. In this case, all references to the original asset will be preserved.

<figure><img src="/files/5truXrQf1qf7CcSCnJew" alt="" width="296"><figcaption><p>SecondaryMission_1 is now a sub-asset,<br>but the original is also preserved</p></figcaption></figure>

{% hint style="warning" %}
It's not possible to add sub-assets to assets that already feature sub-assets as a result of the import process.

For instance, adding sub-assets to an **.fbx model** will result in nothing, because as soon as the asset saves, the import process will reset the sub-assets to the default ones.

See a list of the types that can't be added as sub-assets on the [Exceptions page](/subassets-toolbox/changelog).
{% endhint %}

## Create a new sub-asset

It is possible to create a new asset directly as a sub-asset. Simply right click on the destination main asset, and use the Create menu:

<figure><img src="/files/aGdLFQieO4bUOdI63hTl" alt="" width="563"><figcaption><p>Using the Create menu while an asset is selected, to create a new Material</p></figcaption></figure>

Once you select the asset type, the new asset is created and you can give it a name, like usual:

<figure><img src="/files/5SXUCBZO1fK7c9WFILKP" alt="" width="294"><figcaption><p>Renaming the new asset</p></figcaption></figure>

Once the rename is confirmed, the new asset will be added as a sub-asset to the previous selection.

<figure><img src="/files/JpJ0tvLIRTV1akjkNwFs" alt="" width="259"><figcaption><p>The new Material is now a sub-asset</p></figcaption></figure>

{% hint style="success" %}
**Preserving References**

When adding a sub-asset using drag and drop, normally the references to the original asset will break. SubAssets Toolbox has a way to prevent this, and you can find more about it in [Patch References](/subassets-toolbox/editor-workflows/patch-references).
{% endhint %}

## Renaming sub-assets

To rename a sub-asset, select it and use **right-click > Rename Sub-Asset**. You can also select it and hit Enter (on Mac) or F2 (on Windows).


# Removing Sub-Assets

## Drag and drop

To remove one or more sub-assets from an asset, simply select all the assets you want to remove, and drag them into an empty space in the Project window (or directly to another folder).

<figure><img src="/files/randPOBwTqbxSVorTLrv" alt="" width="337"><figcaption><p>Dragging two sub-assets out of their main asset</p></figcaption></figure>

Just like that, the sub-assets will be extracted and become individual main assets.

<figure><img src="/files/CjjuiI2uyZjSVYiVv5C4" alt="" width="269"><figcaption><p>SecondaryMission_1 and _2 are now independent assets</p></figcaption></figure>

Extracting a sub-asset like this is immediate, and doesn't present a confirmation window.

{% hint style="success" %}
**Preserving References**

When adding a sub-asset using drag and drop, normally the references to the original asset will break. SubAssets Toolbox has a way to prevent this, and you can find more about it in [Patch References](/subassets-toolbox/editor-workflows/patch-references).
{% endhint %}

## Deleting sub-assets

If you want to delete a sub-asset and not just unparent it, you can also select it and use **right-click > Delete SubAsset(s)**.

<figure><img src="/files/2oUGqy0lcuJfDYLTfqMj" alt="" width="375"><figcaption><p>Confirmation for deleting a sub-asset</p></figcaption></figure>

Alternatively, you can hit Ctrl+Backspace (Windows) or Cmd+Backspace (Mac) as a shorcut.

{% hint style="info" %}
When deleting a sub-asset this way, Unity will present this warning in the console:

> The operation "Delete" cannot be executed because the selection is a root folder.

You can safely ignore it.
{% endhint %}


# Patch References

When creating or relocating a sub-asset, SubAssets Toolbox can patch references to it in the entire project.

{% hint style="warning" %}
Because patching references is an operation that involves non-Unity-supported API, it is recommended to have the project under source control before using it.
{% endhint %}

## Context

Why is patching references even needed?

* When a sub-asset is created, and added to another asset, it loses its GUID and from now on, is identified using its parents GUID + an assigned FileID.
* When a sub-asset is removed from its host asset and made a main asset, this new one loses its parent's GUID and the FileID, and receives a new GUID.

For these reasons, creating or relocating a sub-asset will **invalidate** **all references** to the asset involved. Sometimes this is not an issue, but other times it can lead to a lot of work trying to track down the dependencies and fixing them.

## Patching references

SubAssets Toolbox has a feature to "patch references" by looking into all files that could hold a reference to the moved asset, to swap the GUID + FileID with the new ones.

When you relocated a file, you will be prompted if you want SubAssets Toolbox to do so for you:

<figure><img src="/files/fLUDjWbapA0rStQs1Yn0" alt="" width="372"><figcaption></figcaption></figure>

Since this feature scans all applicable files, it can be taxing in big projects. You can set the behaviour in Project Settings, where you can decide whether to always auto-confirm patching, get asked each time, or disable it completely.


# Exceptions

This page details asset types and special cases that affect the behaviour of SubAsset Toolbox.

## Illegal asset pairs

Not all asset types can *have* sub-assets, and not all asset types can *be* sub-assets. As you parent/unparent an asset, you might see error messages in one of these cases.

Types that cannot become sub-assets:

* C-Sharp files (.cs)
* Prefabs and Prefab variants (.prefab)
* Scenes (.unity)
* Meta files (.meta)

Types that can't have sub-assets:

* C-Sharp files (.cs)
* Audio Mixers (.mixer)
* Shader files (.shader and .shadergraph)
* Scenes (.unity)
* Meta files (.meta)
* Folders

## Special create asset behaviours

Sometimes, when you right-click > Create an asset while another asset is focused, Unity does something special based on the created/selected asset types. In these cases, SubAssets Toolbox will not add the created file as a sub-asset, but instead respect the default behaviour.

These pairs are:

* When a Prefab is selected, and you right-click > create a Prefab Variant, the newly created Prefab will be a variant of the selected base.
* When a 3D model is selected, and you right-click > create a Prefab Variant, the newly created Prefab will be a variant of the selected 3D model.
* When a shader is selected, and you right-click > create a Material, the newly created Material will use the selected Shader file as its shader.


# ISubAssetAware

Implement this interface in your ScriptableObjects, to make them compatible with the editor workflows of SubAssets Toolbox. By implementing these methods every time a sub-asset is added or removed in any way, the object can react and save a reference to it (or perform any other setup action).

For an example implementation, import the [SubAsset Aware Scriptable Object](/subassets-toolbox/samples/subassetawareso) sample, and take a look at the `SubAssetAwareSO` class.

***

### AddSubAsset

```csharp
public void AddSubAsset(Object newSubAsset);
```

An object has been added as a sub-asset.

In your implementation, you should insert the new object into any List, array, Dictionary, or any data structure that allows you to retrieve the sub-asset at a later stage.

### RemoveSubAsset

```csharp
public void RemoveSubAsset(Object removedSubAsset);
```

A sub-asset will be removed.

In your implementation, you should ensure that the reference to the destroyed object is removed from whatever data structure was referencing it.

When this method is invoked as part of the API included in SubAssets Toolbox the sub-asset hasn't been destroyed yet, so you can inspect it if needed.


# SubAssetAwareSO

`SubAssetAwareSO` is an example of a ScriptableObject that is "aware" of its sub-assets, in that it uses a `List` to keep references to them so that their reference can be always retrieved at runtime.

In this sample, the list is displayed in the asset's Inspector using a **custom editor**, so the user is informed of which sub-assets are present even when the main asset is not expanded in the Project window.

<figure><img src="/files/2ryp01EKsmQkWjqNmhkJ" alt=""><figcaption><p>The MainObjective SO contains 3 sub-assets,<br>which are visualised at the end of its Inspector</p></figcaption></figure>

The sub-assets can be reordered in the list, though this is purely for tidying up in case they were added in an odd order, as it doesn't modify any functionality.

At runtime, the methods of `SubAssetAwareSO` can be used to access its sub-assets by name, or by class.

You can use this class as a starting point, and implement your own powerful "sub-asset aware" ScriptableObjects.

***

### GetSubAssetByName

```csharp
public virtual Object GetSubAssetByName(string subAssetName);
```

Returns the first sub-asset that has the specified name (Null if no sub-asset with this name is present).

### GetAllSubAssetsByName

```csharp
public virtual List<Object> GetAllSubAssetsByName(string subAssetName);
```

Returns all sub-assets that have the specified name (or an empty List if no sub-assets were found).

### GetSubAssetByType

```csharp
public virtual Object GetSubAssetByType<T>();
```

Returns the first sub-asset of the specified type (Null if no sub-asset of that type is present).

### GetAllSubAssetsByType

```csharp
public virtual List<Object> GetAllSubAssetsByType<T>();
```

Returns all sub-assets of the specified type (or an empty List if no sub-assets were found).


# Intro

:link: Available on the [**Unity Asset Store**](https://bit.ly/scenenotes_as)

Scene Notes is a tool to visualise and edit tasks, issues, docs or notes; directly from Unity's Scene View. This allows for easy communication within the team, without leaving the scene.

See what it is about in this quick trailer:

{% embed url="<https://www.youtube.com/watch?v=DwQ8JgIKr-M>" %}


# Changelog

## 1.6.0 - UX improvements

(31/05/26)

* Improvements to screenshots:
  * Screenshots are now saved into a dedicated sub-folder, keeping the project tidier.
  * A new Project Setting lets you choose whether screenshots are saved as sub-assets of the note, rather than as separate files.
  * Screenshots can now also be attached to individual comments, not just to the note itself.
* Category filtering:
  * The Scene Note Categories overlay now acts as a filter, letting you show or hide notes by category directly from the scene view.
* Note titles in scene view are now correctly occluded by objects in the scene when gizmos are set to 3D.
* Note management:
  * Notes can now be deleted by deleting their linked GameObject (with a confirmation prompt).
  * Added a button to zero out a note's offset from its linked GameObject.
* Fixes and improvements
  * Much better Undo support across user actions on notes.
  * Removed warnings for obsolete API in Unity 6.4.

### 1.5.1

(22/04/26)

* It is now possible to take screenshots and include gizmos in them.
* Screenshots attached to a note now show as a big thumbnail, which makes it easier to see what's pictured in them.
* Added the ability to decide whether a newly-created note is automatically linked to the selected GameObject. Also added menu items to perform the creation of both linked and non-linked notes.
* Scene Notes now has a presence in both Project Settings and Preferences. Settings are split between the two as it makes sense.
* Fixes and improvements
  * Fixed an issue with notes that broke the Ctrl+Shift snapping functionality.
  * Improved error handling for when a note is missing its linked object.
  * Redesigned comment UI on notes.
  * Removed warnings of obsolete code.

## 1.5.0 - Category icons

(15/06/25)

* Category icons:
  * Notes can now display an icon that displays the category they belong to.
  * This icon can be assigned on the NoteCategories ScriptableObject, and can be customised to be any image.
  * A new option in Project Settings, Icon Displays, allows to choose whether to display state or category via the note's icon.
  * A new toolbar, Scene Notes Categories, can be opened to act as a legend for category icons.
* Improvements to note titles in scene:
  * You can now customise the colour and transparency of titles, and give them a background for improved readability.
  * You can trim long titles, to cater for excessively long ones creating too much noise.
  * Titles in scene view now fade away in the distance when too small.
* The note state "Started" has been renamed to "In Progress".

## 1.4.0 - Link to GameObject

(02/06/25)

* Notes can be now linked to a GameObject.
  * When linked, notes follow the GameObject when it's moved, rotated or scaled.
  * When linked, a note can have an offset from the GameObject's pivot so it can be positioned on a specific point with respect to the GameObject.
* Multi-selection editing:
  * It's now possible to multi-select notes and edit most of their properties in bulk (title, contents, category, scene).
* Fixed an issue when duplicating a note ScriptableObject, when the duplicated note keeps the same title. Now the new note automatically gets assigned a new 4-digit suffix.

## 1.3.0 - Focus mode

(13/05/2025)

* New and changed toolbar items:
  * New Focus button in the toolbar to hide other icons and gizmos, to focus on Scene Notes.
  * New Filter by State button in the toolbar, to filter notes by state (Done, Started, Not Started).
  * New icons for category button.
* Text in the note editor now wraps on long lines.
* Log messages now display package's name.
* Overlay menu now shows Scene Notes icon instead of letters SN.
* Improved query string in NotesBrowser.
* Fixes:
  * Preventing Notes Browser error when deleting a note.
  * Fixed new notes not receiving an icon, on creation.
  * Fixed issues where scene names with spaces would break the search query in the Notes Browser.
  * Fixed error when trying to open the toolbar in an unsaved scene.
  * Fixed note snapping back into position when Completed or Started.
  * Removed warning due to obsolete class in Unity 6 and up.

### 1.2.2

(01/04/25)

* Fixed a bug that prevented the icons of the Overlay from loading, when first installing the package.
* Improved reactivity of the Browser window when changing a note's state.

### 1.2.1

(31/03/25)

* When editing note categories and the Notes Browser is open, they will update in the Notes Browser window too.
* Fixed a layout issue in the Notes Browser happening with long category names.
* Fixed various small bugs.

## 1.2.0 - Browser window and Screenshots

(29/12/24)

* New Notes Browser window! It's not possible to browse notes in list mode, and search for them by state, name, author, and category. It's also possible to filter by open scenes.
* Now it's possible to attach a screenshot to notes. The screenshot can be taken directly in the scene view and automatically attached, by clicking a button in the note's Inspector.

### 1.1.2

(18/07/24)

* Fixed an annoying bug with GUID clashes, happening when using other package assets.

### 1.1.1

(25/06/24)

* New welcome screen, with useful links to documentation, email support, and more.

## 1.1.0 - Comments and Authors

(28/05/24)

* Added the ability to add comments to notes, and reply to them.
* Added author, created date and last edited date (grouped under "More").

## 1.0.0 - Original release

(08/05/24)


# Visualising notes

## Bringing up the interface

Scene Notes is operated through a Scene Overlay. To open it, either hover on the Scene View and press the **\`** key (the one next to Shift, on a British keyboard), or click on the three vertical dots menu at the top-right corner of the Scene View, and select Overlays Menu:

<figure><img src="/files/NhwjKuYR4KWxU2T2zuWR" alt="" width="347"><figcaption><p>The Overlays Menu, that allows you to enable and disable overlays</p></figcaption></figure>

Once the Overlays Menu opens, click on Scene Notes to visualise the overlay. Once the overlay is enabled, you should see it appear somewhere in your Scene View:

<figure><img src="/files/j9gvMxE11yGmZKf5zsCB" alt="" width="144"><figcaption><p>The Scene Notes overlay, closed</p></figcaption></figure>

The overlay appears in its closed state. Click on it to enable it, and visualise the Scene Notes:

<figure><img src="/files/ujS1f5kFls8DgPM9Syzw" alt="" width="375"><figcaption><p>Scene Notes enabled, with a note visible in the scene</p></figcaption></figure>

{% hint style="info" %}
There will be no icons in the scene at first because on the first setup you haven't [created any note yet](/scene-notes/using-the-tool/creating-and-editing-notes#creating-a-new-note).
{% endhint %}

To hide the notes again, disable the overlay by clicking on the first button.

## Loading notes for a specific Unity scene

Once a scene is associated to a note, that note will be automatically loaded in Unity when the scene is open. Opening and closing scenes will automatically show/hide the related notes.

## Focusing on scene notes

If the Scene View is very busy with gizmos and icons, it might be hard to see scene notes. To get focus, click on the Focus button. All gizmos and icons for other components will be disabled, putting the spotlight on the notes.

<figure><img src="/files/3EAkwV46m3A8BhjxXykS" alt="" width="383"><figcaption><p>The Focus Mode button</p></figcaption></figure>

Click on the button again, or disable the overlay, to see other gizmos again.

{% hint style="info" %}
When enabling Focus mode, Scene Notes will remember which gizmos were already disabled. This way when you exit Focus mode, those gizmos won't be enabled by mistake.
{% endhint %}


# Creating and editing notes

## Creating a new note

To create a new Note, focus on the spot in the scene where you want to create it, and click the Plus button.

{% hint style="info" %}
The new Scene Note will be associated with the scene that is the currently Active scene. You can always change the scene later.
{% endhint %}

## Editing a note

You can edit the data of a Scene Note by just selecting it in the scene, and editing the data in the Inspector:

<figure><img src="/files/YlzG7bo3xCQr3lwXmxsm" alt="" width="375"><figcaption><p>The Inspector of a Scene Note</p></figcaption></figure>

Alternatively, you can edit [the ScriptableObject](/scene-notes/other/data-and-folders#data-format) directly.

## Note properties

### Note state

All notes have a state, which by default is "Not started". The state is reflected in the coloured bar at the top of the note's Inspector. You can change a note's state by just clicking the buttons under the bar.

<figure><img src="/files/KpUYRptl0bwvGhNe7cIt" alt="" width="375"><figcaption><p>An unstarted note</p></figcaption></figure>

<figure><img src="/files/3ZUi8eVgEH24UyBulilh" alt="" width="375"><figcaption><p>A completed note</p></figcaption></figure>

The possible states are:

* Not started: grey bar
* In progress: blue bar
* Done: green bar

The meaning that you give to each status is up to you and your team.

### Title

The title of the note. Changing this will rename [the associated ScriptableObject](/scene-notes/other/data-and-folders#data-format) file.

If note titles are set to display in [Project Settings](/scene-notes/other/project-settings), will be shown below the note's icon in the Scene View.

### Contents

The main text of a note.

### Category

The category the note belongs to, used for [filtering](/scene-notes/organising-notes/filtering-notes#filtering-notes-by-category) and icons. Refer to [Handling categories](/scene-notes/organising-notes/handling-categories) for more information.

### Scene

You can freely reassign a different scene to the **Scene** field.

{% hint style="info" %}
Keep in mind that reassigning a scene will move the [ScriptableObject](/scene-notes/other/data-and-folders) for the note, and might make the note disappear from the Scene View if the specific scene is not currently loaded.
{% endhint %}

### Linked GameObject

If a note is not linked to any object, it's just placed with a **World position** in the scene, and you can edit it here.

<figure><img src="/files/4GF6JsHABExMnouXoSnX" alt="" width="563"><figcaption><p>The Scene information section of a note</p></figcaption></figure>

If a GameObject is dragged into the **Linked to** field, the note becomes linked to that GameObject. When that object moves or rotates, the note moves with it. As such, while the note still has a world position, this will not be editable: what matters is the **Local offset**, which can be tweaked at the bottom of this section:

<figure><img src="/files/5cz1zM8suuIIBK2AHxdr" alt="" width="563"><figcaption><p>This note is linked to a GameObject</p></figcaption></figure>

{% hint style="info" %}
Deleting the GameObject linked doesn't delete the note, it just unlinks it.
{% endhint %}

### Screenshots

You can attach screenshots (or any image) to a note or to comments.

To take a screenshot directly in the Scene View, click the button. An overlay will appear in the Scene View:

<figure><img src="/files/Mj8lPMto85q8wGOJ48sG" alt="" width="375"><figcaption><p>Capturing a screenshot</p></figcaption></figure>

Screenshots captured this way will be saved in the 📁 `Screenshots` folder, right under the [data folder](/scene-notes/other/data-and-folders).

After taking a screenshot, you can potentially link it to another note by just manually adding it to the other note's list.

Handling these screenshots is up to you: removing a linked screenshot from a note doesn't delete the corresponding image.

{% hint style="info" %}
The data folder path can be specified in [Project Settings](/scene-notes/other/project-settings).
{% endhint %}

### More

This section contains info about the note's author, when the note was created and when it was last edited. This data is not editable.

{% hint style="info" %}
You can change the name used to sign your notes in [Project Settings](/scene-notes/other/project-settings).
{% endhint %}

### Comments

This section is a lightweight comment thread that belongs to the note. To add comments, simply use the UI to add a new one. After that, you'd need to commit the note using whatever Version Control system you use, at which point your teammates can reply.

<figure><img src="/files/BU7Hx2mpiGFE2iak0lSv" alt="" width="375"><figcaption><p>Two comments, and the reply box</p></figcaption></figure>

Comments cannot be edited, only deleted.

{% hint style="info" %}
You can change the name used to sign your comments in [Project Settings](/scene-notes/other/project-settings).
{% endhint %}

## Deleting a note

To delete a note, press the trash button on the note's toolbar:

<figure><img src="/files/p7q6nVSFMTR4ENWLGsqq" alt=""><figcaption></figcaption></figure>

The [ScriptableObject](/scene-notes/other/data-and-folders) representing the note will be immediately deleted.


# Filtering notes

While visualising notes in the scene, you can filter and display only the ones you need, according to different filters.

## Filtering notes by Category

You can hide/show notes by their category. To do so, click on the dropdown arrow on the Filter by Category button, and select the categories you want to see or hide:

<figure><img src="/files/4LRGPmQlbK4JOxJHBSma" alt="" width="331"><figcaption><p>The Filter by Category dropdown</p></figcaption></figure>

If you click on the button itself, you can turn the filter on/off, but the tool will remember the categories you selected in the dropdown.

## Filtering notes by State

You can hide/show notes by their state (Not Started, In Progress, or Done). To do so, click on the dropdown arrow on the Filter by State button, and select the states you want to see or hide.

<figure><img src="/files/wruTSM8CNHvnizXvsD3S" alt="" width="273"><figcaption><p>The Filter by State dropdown</p></figcaption></figure>

If you click on the button itself, you can turn the filter on/off, but the tool will remember the states you selected in the dropdown.


# Handling categories

Notes can be grouped into categories, which can be used to filter notes, or to give them different icons for an easier visualisation.

<figure><img src="/files/iHH2um7htU5tqmPquCqo" alt=""><figcaption><p>A scene full of notes, whose icons are set to display their category</p></figcaption></figure>

## The Note Categories index

Inside the notes folder (specified in Project Settings), a ScriptableObject of type `Note Categories` is automatically created when first launching the tool.

This SO acts as an index of the categories that notes can belong to. For each category, you can assign a name and an icon.

### Category icons

Each category icon will be displayed in the Scene View for all notes belonging to that category. You can assign any Texture2D contained in the project as an icon.

{% hint style="success" %}
There are about 20 icons provided by default in different colours, and a .psd file that can be used as a template for creating new icons in the same style.

They are found in 📁 `Packages/io.continis.scene-notes/UI/Images/NoteIcons_Category`
{% endhint %}

{% hint style="warning" %}
Icons are only used if the **Icon Displays** setting in [Project Settings](/scene-notes/other/project-settings) is set to Categories. If your setting is to display icons for State, you can ignore the icons in the index.
{% endhint %}

## The Categories Overlay

When you choose that note icons display their category, it can be easy to lose track of "which colour represents which category". For this, you can use the Categories Overlay to act as a legend.

The Categories Overlay can be opened by either hovering on the Scene View and pressing the **\`** key (the one next to Shift, on a British keyboard), or clicking on the three vertical dots menu at the top-right corner of the Scene View and selecting Overlays Menu, and then Categories Overlay.

<figure><img src="/files/Q3z0tdwx6d4jqHFnSw45" alt="" width="563"><figcaption><p>The overlay showing 6 categories</p></figcaption></figure>

When the overlay is open, click on a category to filter notes from that category out. You can click as many categories as needed to create a customised filter. This filtering is mirrored in the [Filter by Category button](/scene-notes/organising-notes/filtering-notes#filtering-notes-by-category) in the main toolbar.

The overlay also contains a button that acts as a shortcut to the [Note Categories index](#the-categories-scriptableobject), so you can quickly change them or edit their icons.


# Notes Browser window

When you have many notes in the scene, it can be handy to look at them as a list. For that, Scene Notes has the Notes Browser window:

<figure><img src="/files/Wx2bUEEzJQpqrKg2dbEK" alt="" width="563"><figcaption><p>The Notes Browser window</p></figcaption></figure>

The Notes Browser visualises the notes' author, title, a brief excerpt of the contents, the creation date, a screenshot (if present), and the state (as a vertical bar, to the left).

Click on a note to bring the camera there (if the note is currently loaded), and to ping its [corresponding ScriptableObject](/scene-notes/other/data-and-folders).

## Opening the Notes Browser

This window can be opened via the top menu under:

* **Tools > Scene Notes > Notes Browser window**, or
* **Window > Scene Notes > Notes Browser**

## Filtering notes

You can search and filter the notes visualised by using the top filters bar:

<figure><img src="/files/7EIYRVPT9x8M3AuSsslb" alt="" width="563"><figcaption><p>The notes being filtered by name, state, and category</p></figcaption></figure>

Searching using the search box will look into the note's title, contents, and author.

{% hint style="info" %}
**The Notes Browser is empty?**

If the window is empty when first opening it, it's because Unity might still be building the search index that the Notes Browser relies on. Look for the activity bar in the bottom right corner: is there an operation going?

If the notes still don't appear after a few seconds, you can try rebuilding the index. Go to **Window > Search > Index Manager**. In the window that open, select the first index (it should be called "Assets"), right-click, and choose Force Rebuild.

After a few seconds of wait, the notes should now appear in the Browser window.
{% endhint %}


# Data and folders

Since Scene Notes is a purely project-based tool, the data for the notes is stored in a specific folder as ScriptableObjects. The location of this folder is initially **Assets > SceneNotes**, but it can be changed in [Project Settings](/scene-notes/other/project-settings).

## Data format

Inside the main folder, alongside the NoteCategories ScriptableObject, multiple folders will be created with the guid of each scene that contains notes:

<figure><img src="/files/AtQ6ZS7nJWnRht7LF0xD" alt="" width="438"><figcaption></figcaption></figure>

As notes are moved between scenes, these folders will be automatically created and destroyed, so you don't need to manage them.

Inside these scene folders, each ScriptableObject represents a note:

<figure><img src="/files/nIybf4MXzI4XeR6bWufx" alt=""><figcaption></figcaption></figure>

The file name reflects the note's title and is automatically updated when the title changes.

When the toolbar is open, what is visualised in the scene are **invisible GameObjects** that reference these ScriptableObjects. Deleting one of these GameObjects **will not** delete the ScriptableObject.

{% hint style="info" %}
It is advisable to [delete a note](/scene-notes/using-the-tool/creating-and-editing-notes#deleting-a-note) by clicking on the trash button in the note's Inspector.
{% endhint %}

Though notes are generally meant to be managed from within the Scene View, it is totally possible to manage them directly from their ScriptableObjects: changing properties, assigning different scenes, etc.&#x20;

However, after making these changes, it's good practice to [reload the notes](/scene-notes/using-the-tool/visualising-notes#bringing-up-the-interface) from the Overlay so they show correctly in the Scene View.

### Screenshots

Screenshots taken from a note are stored in one of two ways, controlled by the **Save Screenshots as Sub-assets** option in Project Settings.

When the option is **enabled** (the default), each screenshot is saved as a sub-asset inside the note's own `.asset` file. This keeps the screenshot tightly bound to the note: it can't be referenced from anywhere else in the project, it's hidden from the Texture2D object picker, and it is automatically deleted when the note is deleted. The trade-off is that the texture is stored uncompressed inside the `.asset`, so the file grows in size and git diffs grow with it.

When the option is **disabled**, screenshots are saved as standalone PNG files on disk, under the Notes folder, in a dedicated subfolder structure:

```
<NotesFolder>/Screenshots/<sceneGuid>/<noteGuid>/Screenshot_<timestamp>.png
```

This mirrors the per-scene layout already used for notes themselves: each scene gets its own folder (named after the scene's GUID), and within it, each note gets its own folder (named after the note's GUID). Files saved this way retain PNG compression on disk, which keeps the project lighter and produces smaller git diffs, at the cost of the screenshot files being independent assets that aren't cleaned up automatically when the note is deleted.

Both modes can be mixed within the same project: changing the setting only affects screenshots taken from that point on, and existing screenshots remain wherever they were originally saved.

## Version control

As notes are meant to be shared across the team, the folder containing the Scene Notes should be versioned using the version control of your choice. This way changes to the notes can be pushed and pulled just like any other regular file.


# Project Settings

You can find these in **Project Settings > Scene Notes**. These are shared with the team.

<table><thead><tr><th width="238.10546875">Setting</th><th>Function</th></tr></thead><tbody><tr><td><strong>Project</strong></td><td></td></tr><tr><td>    Notes Folder</td><td>The name of the folder in which Scene Notes will be stored. Changing it doesn't move data, so you might have to rename the corresponding folder to match.</td></tr><tr><td>Save Screenshots as Sub-assets</td><td>When enabled, new screenshots are stored as sub-assets inside the note's file. When disabled, screenshots are saved as standalone PNG files.</td></tr><tr><td><strong>Visualisation Preferences</strong></td><td></td></tr><tr><td>    Display Title in Scene</td><td>If enabled, the title of the note will be visualised in the Scene View alongside the note's icon.</td></tr><tr><td>    Maximum Title Length</td><td>The maximum title length when visualising note titles in the Scene View. If a title is longer than this, it will be elided with "..."</td></tr><tr><td>    Title Colour</td><td>The colour of the title's text (if enabled).</td></tr><tr><td>    Title Background Colour</td><td>The colour of the title's background (if enabled).</td></tr><tr><td>    Icon Displays</td><td>Choose whether note icons in the Scene View display the note's state, or the category it belongs to.</td></tr></tbody></table>


# Preferences

You can find these in **Preferences > Scene Notes**. These are personal settings.

<table><thead><tr><th width="238.10546875">Setting</th><th>Function</th></tr></thead><tbody><tr><td>    Author Name</td><td>This is the name used to sign both new notes, and comments. You can input any name, including an email. By default this is the email of the signed-in Unity ID.</td></tr><tr><td>Include Gizmos in Screenshots</td><td>When enabled, gizmos will be visible in screenshots taken from the Scene View.</td></tr><tr><td>Default Create Note Action</td><td>The default action when clicking the Create Note button in the toolbar. 'Linked to Selected' creates a note that is right away linked to the selected GameObject. 'Linked to Selected' falls back to 'Independent Note' if no single GameObject is selected.</td></tr></tbody></table>


# Intro

<figure><picture><source srcset="/files/V8I015kAs7YikZjXEXu9" media="(prefers-color-scheme: dark)"><img src="/files/bHHSrvfdcq6mjmooxGU5" alt=""></picture><figcaption></figcaption></figure>

:link: Available on the [**Unity Asset Store**](https://bit.ly/codecksscenenotes_as)&#x20;

Codecks Scene Notes is a Unity integration of [**Codecks**](https://tools.continis.io/codecks-scene-notes/www.codecks.io), which brings added power to an already cool project management tool.

See what it is about in this quick trailer:

{% embed url="<https://youtu.be/xApCaowevM0?si=fuQOerWkQk8wa8na>" %}

### Requirements

To use Codecks Scene Notes you need to have an existing Codecks account (free tier is fine), and you need a working internet connection. You can create one at [**codecks.io**](https://tools.continis.io/codecks-scene-notes/www.codecks.io).

{% hint style="info" %}
If you are looking for a simple notes integration that is completely project-based (no server, no backend), you can consider my other asset [Scene Notes](https://tools.continis.io/scene-notes/)!
{% endhint %}

### Terminology

In Codecks, every note, bug, issue, etc. is represented by a card, and cards are grouped into decks. In this tool, once cards make it into Unity we refer to them as Scene Notes.

There is a one to one correspondence: (in Codecks) a **Card** < > a **Scene Note** (in Unity)

In essence, to create a Scene Note you take a Codecks card and you assign it a position in space, and a scene that it is associated with.

{% hint style="warning" %}
A Scene Note can't exist without having a Codecks card associated to it.
{% endhint %}


# Changelog

### 1.6.1

(12/08/25)

* Fixed an issue where the user could still edit a note even if they were not its Owner.

## 1.6.0 - Card owners, Hand cards, Focus mode

(08/08/25)

* Notes can now be linked to a GameObject.
  * When linked, notes follow the GameObject when it's moved, rotated or scaled.
  * When linked, a note can have an offset from the GameObject's pivot so it can be positioned on a specific point with respect to the GameObject.
* Multi-selection editing:
  * It's now possible to multi-select notes and edit most of their properties in bulk (title, contents, deck, scene, author).
* Improvements to note titles in scene:
  * You can now customise the colour and transparency of titles, and give them a background for improved readability.
  * You can trim long titles, to cater for excessively long ones creating too much noise.
  * Titles in scene view now fade away in the distance when too small.

## 1.5.0 - Card owners, Hand cards, Focus mode

(13/05/25)

* Notes now display their owner in the Inspector (name and avatar). The owner can then be reassigned directly from within Unity.
* New toolbar button to filter notes by their state (Done, Started, Not Started, Snoozed or Doc).
* New toolbar button to filter notes by their owner.
* New toolbar button to display only the cards currently in the user's Hand.
* New toolbar button to hide other icons and gizmos, to focus on Scene Notes.
* Filter buttons are now "toggle dropdowns" (i.e. a button + dropdown). Even after configuring a filter, you can turn it on/off and it will remember the configuration.
* Completely redesigned icons for many buttons.
* Codecks logo updated to the latest graphics.
* Log messages now display the package's name.
* Improved handling (escaping) of strings in notes' body and titles.
* Text in the note editor now wraps on long lines.
* Fixed an issue impeding the toolbar to open after a loading error.
* Overlay menu now shows Codecks icon instead of the letters "CS".

### 1.4.3

(11/04/25)

* Fixed new notes not displaying an icon on creation.

### 1.4.2

(01/04/25)

* Fixed a bug that prevented the icons of the Overlay from loading, when first installing the package.
* Fixed formatting of the Welcome window.

### 1.4.1

(18/07/24)

* Fixed an annoying bug with GUIDs, happening when using Codecks Scene Notes in tandem with other assets.
* Changed IDs for UI elements, so Codecks Scene Notes can be used together with Scene Notes in the same project.
* Moved default folder to CodecksSceneNotes, so it doesn't clash with the default folder in regular Scene Notes (you can still rename them, like before).

## 1.4.0 - Filter by project

(26/06/24)

* Notes can now display their title in the scene (this can be turned on/off using a setting in Project Settings).
* It is now possible to specify Codecks projects to filter notes.
* New, reimagined Wizard window, to setup projects and default deck more easily.
* Added a welcome window with useful links.

### 1.3.1

(02/05/24)

* Improved legibility for people who use the Light UI for Unity, including new dark icons for the toolbar.

## 1.3.0

(07/03/24)

* Fixed an issue with the Setup Wizard where the window sometimes didn't show the Save button. The window now displays a scrollbar when too small (thanks to user "cjaks" for pointing this out).
* Renamed package to be io.continis.codecks-scene-notes

## 1.2.0

(20/02/24)

* Added the ability to search a card in Unity starting from its ID in Codecks, by pasting it in the search box in the toolbar.
* Added support and specific icons for Doc cards and for Snoozed cards.
* Add a button to scene notes to visualise their corresponding card on the Codecks website.
* Improved a lot detection of setup errors, and added more descriptive error messages.
* If a card is being edited, upon quitting the editor you will be asked to confirm. This prevents unwanted loss of data.

## 1.0.0 - Original release

(19/01/24)

<br>


# Visualising notes

## First setup

To get started with Codecks Scene Notes, you can use the Setup Wizard included. Go to **Tools > Codecks Scene Notes > Setup Wizard**.

Fill in all the fields, login, and confirm. All of the information is saved into [Project Settings](/codecks-scene-notes/other/project-settings). You can always use the Wizard again to override the values, or edit them manually from within Project Settings.

## Bringing up the overlay

Codecks Scene Notes is operated through a Scene Overlay toolbar. To open it, either hover on the Scene View and press the **\`** key (the one next to Shift, on a British keyboard), or click on the three vertical dots menu at the top-right corner of the Scene View, and select Overlay Menu:

<figure><img src="/files/AFyd1abFWytRtRLfKgTQ" alt="" width="563"><figcaption><p>Opening the Overlays Menu via the top-right dropdown</p></figcaption></figure>

Once the Overlay Menu opens, click on Codecks Scene Notes to enable the overlay. Once the Codecks Scene Notes overlay is enabled, you should see it appear somewhere in your Scene View:

<figure><img src="/files/cF62MW34CKDNWuIqaFd7" alt=""><figcaption><p>The Codecks Scene Notes overlay, closed</p></figcaption></figure>

The overlay appears in its closed state. Click on it to enable it, and load Scene Notes.

## Pulling card data

The first time the tool is enabled, it pulls card data from the server.

<figure><img src="/files/HY3ZdwJig8LblUXwJP5o" alt="" width="563"><figcaption><p>Codecks Scene Notes enabled, with a few notes visible in the scene</p></figcaption></figure>

Once it’s done, you can always force a refresh of the data by clicking the Reload button.

{% hint style="danger" %}
Reloading data will discard any unsaved changes you might have, so make sure to save any edited Note before you Reload!
{% endhint %}

## Loading notes for a specific Unity scene

Once a scene is associated to a note, that note will be automatically loaded in Unity when the scene is open. Opening and closing scenes will automatically show/hide the related notes.

## Focusing on Scene Notes

If the Scene View is very busy with gizmos and icons, it might be hard to see scene notes. To get focus, click on the Focus button. All gizmos and icons for other components will be disabled, putting the spotlight on the notes.

<figure><img src="/files/3EAkwV46m3A8BhjxXykS" alt="" width="383"><figcaption><p>The Focus Mode button</p></figcaption></figure>

Click on the button again, or disable the overlay, to see other gizmos again.

{% hint style="info" %}
When enabling Focus mode, Codecks Scene Notes will remember which gizmos were already disabled. This way when you exit Focus mode, those gizmos won't be enabled by mistake.
{% endhint %}


# Creating and editing notes

## Creating a new note from Unity

To create a new Note, focus on the spot in the scene where you want to create it, and click the Plus button. The newly created card will be immediately sent to the Codecks server, and you can keep editing its properties in the Inspector.

<figure><img src="/files/R6zW3CQv1yIpTaRPcu1m" alt="" width="563"><figcaption><p>Click the Plus button to create a new note</p></figcaption></figure>

{% hint style="info" %}
The new Scene Note will go in the default Deck specified during setup, and will be associated with the scene that is the currently Active scene. You can always change these later.
{% endhint %}

## Editing a note

You can edit the data of a Scene Note by just clicking on its icon, and editing the data in the Inspector.

However, when you are done, you need to **press the Save button** at the bottom to upload the changes to the Codecks server.

<figure><img src="/files/jyqzaz7V4G2meYeplYLg" alt="" width="375"><figcaption><p>A Scene Note being edited, displaying the Save button at the bottom</p></figcaption></figure>

{% hint style="danger" %}
Any unsaved change will be lost next time Codecks Scene Notes loads data, so make sure you save as soon as you're done editing.
{% endhint %}

## Note properties

### Note state

All notes have a state, which by default is "Not started". The state is reflected in the coloured bar at the top of the note's Inspector. You can change a note's state by just clicking the buttons under the bar.

<figure><img src="/files/KpUYRptl0bwvGhNe7cIt" alt="" width="375"><figcaption><p>An unstarted note</p></figcaption></figure>

<figure><img src="/files/3ZUi8eVgEH24UyBulilh" alt="" width="375"><figcaption><p>A completed note</p></figcaption></figure>

The possible states are:

* Not started: grey bar
* Started: blue bar
* Done: green bar

The meaning that you give to each status is up to you and your team.

{% hint style="info" %}
If a note is a **Doc** note in Codecks, the bar will be yellow and some properties will not be available.
{% endhint %}

### Title

The title of the note.

### Contents

The main text of a note.

### Deck

The deck that contains the note in Codecks. Can be used for [filtering](/codecks-scene-notes/organising-notes/filtering-notes#filtering-notes-by-deck).

### Scene

You can freely reassign a different scene to the **Scene** field.

{% hint style="info" %}
Keep in mind that reassigning a scene might make the note disappear from the Scene View if the specific scene is not currently loaded.
{% endhint %}

### Linked GameObject

If a note is not linked to any object, it's just placed with a **World position** in the scene, and you can edit it here.

<figure><img src="/files/4GF6JsHABExMnouXoSnX" alt="" width="563"><figcaption><p>The Scene information section of a note</p></figcaption></figure>

If a GameObject is dragged into the **Linked to** field, the note becomes linked to that GameObject. When that object moves or rotates, the note moves with it. As such, while the note still has a world position, this will not be editable: what matters is the **Local offset**, which can be tweaked at the bottom of this section:

<figure><img src="/files/5cz1zM8suuIIBK2AHxdr" alt="" width="563"><figcaption><p>This note is linked to a GameObject</p></figcaption></figure>

{% hint style="info" %}
Deleting the GameObject linked doesn't delete the note, it just unlinks it.
{% endhint %}

### Priority

The priority of the card in Codecks.

### Effort

The priority of the card in Codecks.

### Owner

The owner of the card in Codecks. This can be used for [filtering](/codecks-scene-notes/organising-notes/filtering-notes#filtering-notes-by-owner) too.

You can also enforce more safety by disallowing users from editing notes that are not assigned to them. See the setting **Lock Notes You Don't Own** in [Project Settings](/codecks-scene-notes/other/project-settings).

## Deleting a note

Like in Codecks, we don’t allow full deletion of a Scene Note. To remove a Note, you need to archive it.

Click on the Archive button in the note’s Inspector, and it will immediately be archived on the Codecks website as well (no need to save).

<figure><img src="/files/2DZWFLbThzWw2hvEnCDL" alt="" width="317"><figcaption><p>Click on the Archive button to archive the note</p></figcaption></figure>

You can bring it back, by unarchiving it on the Codecks site (this requires reloading data in Unity).

{% hint style="warning" %}
If you just delete the GameObject that displays a note (by hitting Ctrl + Delete, for instance), the corresponding note is not deleted on the Codecks server. You need to archive it.
{% endhint %}


# Filtering notes

While visualising notes in the scene, you can filter and display only the ones you need, according to different filters.

## Display Hand

You can visualise only the notes that are in your user's Hand in Codecks. Click the Display Hand button to toggle this mode on/off.

<figure><img src="/files/GlLvQ6OdG9gDRqC5ZojA" alt=""><figcaption><p>The Display Hand button</p></figcaption></figure>

Keep in mind that when displaying the Hand, other filters are removed.

## Filtering notes by Deck

You can hide/show notes by their Codecks deck. To do so, click on the dropdown arrow on the Filter by Decks button, and select the decks you want to see or hide:

<figure><img src="/files/yFXkK0ggpgNt4AFNI3E7" alt="" width="302"><figcaption><p>Use the filter dropdown to select the categories to show or hide</p></figcaption></figure>

If you click on the button itself, you can turn the filter on/off, but the tool will remember the decks you selected in the dropdown.

## Filtering notes by State

You can hide/show notes by their state (Not Started, In Progress, or Done). To do so, click on the dropdown arrow on the Filter by State button, and select the states you want to see or hide.

<figure><img src="/files/wruTSM8CNHvnizXvsD3S" alt="" width="273"><figcaption><p>The Filter by State dropdown</p></figcaption></figure>

If you click on the button itself, you can turn the filter on/off, but the tool will remember the states you selected in the dropdown.

## Filtering notes by Owner

You can hide/show notes by their owner. To do so, click on the dropdown arrow on the Filter by Owner button, and select the owners you want to see or hide.

<figure><img src="/files/Qzqvf57sLbWa28RJM8i6" alt="" width="283"><figcaption><p>The Filter by Owner dropdown</p></figcaption></figure>

If you click on the button itself, you can turn the filter on/off, but the tool will remember the owners you selected in the dropdown.

{% hint style="success" %}
Showing/hiding the Hand or filtering doesn’t destroy the notes or reloads data. If you have unsaved data, it will not be lost.
{% endhint %}


# Searching for notes

If there is a note in Codecks you cannot find, you can simply look for it by its card ID.

First, go to the Codecks website and Ctrl-click on the note's ID, in the bottom left corner. A card's ID always starts with the "$" sign.

<figure><img src="/files/AXhArGlKYwNP5Nj1sWoi" alt="" width="285"><figcaption><p>Copying a card's ID</p></figcaption></figure>

<figure><img src="/files/l0uPw5c7Xe2498maNULi" alt="" width="309"><figcaption><p>Paste a card's ID in the input field to look for it</p></figcaption></figure>

Then go into Unity, paste that ID in the text input box in the Scene Notes toolbar, and hit enter. If the card is loaded as part of the open scenes, it will be selected and the scene camera will go to it.


# Understanding the data

## Temporary ScriptableObjects

When Codecks Scene Notes pulls data from the Codecks servers, it creates some **temporary** ScriptableObjects in a folder of your choice (the path can be choses in [Project Settings](/codecks-scene-notes/other/project-settings)). It is important to understand that these ScriptableObjects are meant to be just a throwaway data container.

When editing them in the Inspector, to save edits the data needs to be uploaded back to the Codecks servers. Next time Unity is opened and the tool is activated, the ScriptableObjects are overwritten, and any change not uploaded is lost.

If you use Git, SVN, Plastic or other version control systems, we suggest to add the folder in which the SOs are created to your **ignore list**, in order to not push this temporary data to other teammates.

## Card metadata

When Codecks Scene Notes pulls cards from Codecks, it looks for this metadata written at the bottom of a card.

An example:

```
{
  "scene":"Grasslands",
  "sceneguid":"2c9d71b156bef6846b6ba8d4b2f01fc2",
  "position":{"x":94.1,"y":12.76,"z":-179.0883}
}
```

This metadata is what turns a regular Codecks card into a Codecks Scene Note, that can be visualised into Unity.

If you know what you're doing, you can manually edit that metadata. This for instance can be useful to fix a card that was referencing a scene whose guid changed.

{% hint style="warning" %}
After you make changes this way, remember to reload Scene Notes data in Unity using the Reload button in the overlay. Changes are not pushed to Unity live!
{% endhint %}

### Turning an existing Codecks card into a Scene Note

To turn an existing card in a Codecks project to a Scene Note, you can simply add some metadata that links the card with the specific Unity scene.

Since this metadata can be complex to guess, to obtain it you can click the Copy Metadata button in the overlay. You can then paste it at the end of the card’s contents, in Codecks.

<figure><img src="/files/VWkp4PFFBOxzKphFHfAd" alt=""><figcaption><p>Copy the metadata to add to your card in Codecks</p></figcaption></figure>

Save the card, and reload Codecks Scene Notes data in Unity via the Reload button in the overlay.


# Project Settings

You can find these in **Project Settings > Codecks Scene Notes**. Some settings are shared with the whole team, others are personal.

<table><thead><tr><th width="236.47265625" valign="top">Setting</th><th valign="top">Function</th></tr></thead><tbody><tr><td valign="top"><strong>Codecks Project</strong></td><td valign="top"></td></tr><tr><td valign="top">    Org Name</td><td valign="top">The organisation to pull card data from. The org name is the one that makes up your domain URL. For instance, if your org is on example.codecks.org, the org name will be example.</td></tr><tr><td valign="top">     Default Deck ID</td><td valign="top">The ID of the default deck in which cards will end up when you create a Scene Note from Unity (they can be moved to another deck later).</td></tr><tr><td valign="top">    Specific Project IDs</td><td valign="top">The IDs of the projects (in Codecks) that notes will be taken from. It's preferable to choose these by running through the <a href="/pages/ueIvbyBgDQetXvAZtEC0#first-setup">configuration Wizard</a>, but you can also edit them by hand here.</td></tr><tr><td valign="top"><strong>Codecks User</strong></td><td valign="top"></td></tr><tr><td valign="top">    Last Used Email</td><td valign="top">The last email used to login in the Setup Wizard. This is just stored for convenience, so you don’t have to type it in case you need to login again.</td></tr><tr><td valign="top"><strong>Personal Preferences</strong></td><td valign="top"></td></tr><tr><td valign="top">    Display Title In Scene</td><td valign="top">If enabled, the title of the note will be visualised in the Scene View alongside the note's icon.</td></tr><tr><td valign="top">    Title Colour</td><td valign="top">The colour of the title's text (if enabled).</td></tr><tr><td valign="top">    Title Background Colour</td><td valign="top">The colour of the title's background (if enabled).</td></tr><tr><td valign="top">    Maximum Title Length</td><td valign="top">The maximum title length when visualising note titles in the Scene View. If a title is longer than this, it will be elided with "..."</td></tr><tr><td valign="top">   Lock Notes You Don't Own </td><td valign="top">When visualising a note, it will lock it from edits if the currently logged user doesn't match the note's Owner. This is useful to prevent editing other people's notes by mistake. Notes with no Owner will not be locked.</td></tr><tr><td valign="top"><strong>Unity Project</strong></td><td valign="top"></td></tr><tr><td valign="top">    Notes Folder</td><td valign="top">The folder in the project that Notes ScriptableObjects get created in.</td></tr></tbody></table>


# Troubleshooting

Common problems and their solutions

### The console is showing errors about not being able to load Decks, data, …

Please ensure that you are logged in correctly, and that your org’s name is entered as it is in Codecks. You can use the [Setup Wizard](/codecks-scene-notes/using-the-tool/visualising-notes#configuration) to login again.

Also make sure that your internet connection is working correctly.

### I enabled the tool and I see no errors, but no cards appear in the Scene View

By default, Codecks cards don’t have any data about their position or associated scene. If you haven’t added it, your cards won’t automatically show up in Unity, so **it's normal to see no notes** the first time you pull data.

Check out the sections on how to [create a new Note](/codecks-scene-notes/using-the-tool/visualising-notes#creating-a-new-note-from-unity), or how to [turn an existing card into a Note](/codecks-scene-notes/using-the-tool/visualising-notes#turning-an-existing-card-into-a-scene-note).

### I have some other issue I can’t resolve!

You can always get in touch with us via the email <buoybase@gmail.com>. We’ll be happy to help you resolve the issue. Or if we can’t solve it, issue a refund.


# Special thanks

Thanks to the Codecks team at [Maschinen Mensch](https://maschinen-mensch.com/) for making an awesome tool.

The asset pack used to showcase the integration on the Asset Store is the pack “[RPG Poly Pack - Lite](https://assetstore.unity.com/packages/3d/environments/landscapes/rpg-poly-pack-lite-148410)” by Gigel. The assets are not included in the tool release.

Thanks to Elli K. for the great feedback during the tool’s development.

<br>


# Intro

<div align="left" data-full-width="false"><figure><picture><source srcset="/files/0xVSldRVb8Gr6pLOnkOf" media="(prefers-color-scheme: dark)"><img src="/files/G3CgD3VT7Qusij7cEyuL" alt=""></picture><figcaption></figcaption></figure></div>

:link: Available on the [**Unity Asset Store**](https://bit.ly/sotools_as)

ScriptableObject Tools is a collection of tools to structure gameplay using the power of ScriptableObjects. By using ScriptableObjects as the glue between different parts of the game, you can:

* Solve cross-scene communication.
* Create gameplay that is possible to test in isolation, improving iteration time.
* Allow designers to tweak gameplay in the editor, even at runtime.

All of this using consolidated Unity workflows - which means they will work on all platforms, and with future Unity versions.

## Main components

ScriptableObject Tools is made of different components. You can find the documentation for each one of them in individual pages below.

[Shared Values](/scriptable-object-tools/components/sharedvalues)

They hold one value, and can be used to describe a primitive value (int, float, bool, etc.) that is shared among different objects.

[Runtime Anchors](/scriptable-object-tools/components/runtimeanchors)

They hold a reference to a Unity component that is only available at runtime. Once the game enters Play Mode, scripts can write and read from the value.

[Events](/scriptable-object-tools/components/events)

Events with zero or more arguments, that can be used as channels of communication between objects.

## Utilities

These are base classes that you can derive from.

[ManagedScriptableObject](/scriptable-object-tools/utilities/managedscriptableobject)

A base type to create a ScriptableObject that can reset itself when exiting Play Mode, thus making it compatible with Unity's Enter Play Mode Options (and specifically with "No domain reload").

[DescriptiveScriptableObject](/scriptable-object-tools/utilities/descriptivescriptableobject)

A ScriptableObject with an editor-only description to let developers clarify its use.


# Changelog

## 2.0.0 - Events refactoring

(09/06/26)

* AddListener/RemoveListener methods instead of operators += -=.
* Added Vector2Reference.
* Assets created via the Create menu now get a default file name matching their type.
* RuntimeAnchorSetBase events now include parameter of the element added/removed.
* RuntimeAnchorSetBase GetRandomElement is now deterministic and correct.
* All PropertyDrawers are now UIToolkit.
* Fixed compilation of Editor only API.

### 1.5.1

(29/09/25)

* Tooltip clarification of \_allowIndirectEditing property.
* Values in Runtime Sets are now completely (and correctly) read-only. This prevents users from being able to add/remove values from the Inspector, something which should only be done via APIs at runtime.
* Fix: Removed debug class included by mistake.

## 1.5.0 - Event improvements

(31/10/24)

* Improved simplicity of creating custom SO Events
* SO Events can now be created with 1, 2 or 3 arguments just by inheriting from a class. Events with more arguments can be also created, just by mirroring the functionality of the included 3 classes.
* Improved Sample scenes

## 1.0.0

(03/01/24)

* Initial release


# Shared Values

Shared Values are individual variables wrapped in a ScriptableObject. They can be used to represent one value shared between several GameObjects or other ScriptableObjects.

The project already includes Shared Values of different types, like **int**, **float**, **Boolean**, **Vector3**, **Vector2**, **Quaternion**, **string**, and **Color**; but you can create custom types by extending the base class (see below).

### Sample usages 💡

If you have a lot of prefabs that draw debug gizmos in the scene, a Shared Value can be used in place of a boolean to centralise that debug setting. Instead of having to turn individual Prefab's values on/off, you can now do it from a centralised place.

Another example can be to express some stats related to a character with Shared Values: both the player character and the UI can reference the player's health. When the character gets damage or heals itself, the UI immediately reacts to that.

***

## Using Shared Values

### Creating a new Shared Value

To create a Shared Value, simply position your mouse in the Project View and right click, then **Create > ScriptableObject Tools > Shared Values**, and then choose the type you want to create.

### Referencing a Shared Value in scripts

To reference the Shared Value SO, simply declare a variable of its type, like usual:

```csharp
public SharedInt playerHealth;
// Or also
[SerializeField] private SharedInt _playerHealth;
```

If visualised in the inspector, you should see the field appear and display its value.

### Accessing/writing the value

To use the value contained in a Shared Value SO, all you need to do is reference it and access its `.Value` property, like so:

```csharp
int health = _playerHealth.Value;
```

Alternatively, you can use the SO reference directly to access its value, which will be cast to its inside type:

```csharp
int health = _playerHealth; // Implicit cast to int
bool isAlive = _playerIsAlive; // Implicit cast to Boolean
```

However, assignment and other operators like `+`, `+=`, `-`, `-=` etc. can't be used on the SO directly, but need to be used on its `.Value` property:

```csharp
_playerHealth.Value += 2; // This works
_playerHealth += 2; // This doesn't work
```

To manipulate the data in it, you just add, assign, subtract etc. to its `.Value` property:

```csharp
_playerHealth.Value = _playerHealth.Value + (damage * 3f);
```

### The 'AllowIndirectEditing' property

When a Shared Value SO is referenced in a script, it shows its contained property in the Inspector of the script that is referencing it. Using `AllowIndirectEditing` one can decide whether this value is editable from these Inspectors, or whether to protect it from unwanted edits.

It is off by default, to suggest a workflow where the user of a Shared Value SO has to intentionally go to the SO and edit the value there, reinforcing the idea that they are editing an external value that might be used by other scripts too.

It has no effect at runtime.

***

## Extending Shared Values

### Adding a new Shared Value type

To create a new Shared Value class holding a different type, all you need to do is to create a new C-sharp file, and in it, subclass `SharedValueBase<T>` like this (we'll use `Vector4` as an example):

```csharp
[CreateAssetMenu]
public class SharedVector4 : SharedValueBase<Vector4> { }
```

Don't forget to include the `[CreateAssetMenu]` attribute at the top, so you can create a new ScriptableObject using the right-click menu.

### Giving it a custom PropertyDrawer

With this, the value is ready to use, however, it won't display using a custom PropertyDrawer like all the others. Using a custom PropertyDrawer is absolutely not needed, but it's a nice thing that can improve usability.

To create one: create a new script in an `Editor` folder, and put something like this in it:

```csharp
[CustomPropertyDrawer(typeof(SharedVector4))]
public class SharedVector4Drawer : SharedValueDrawerBase
{
    protected override float GetFieldMaxWidth() => 200f;
}
```

The important thing is that you specify which class you are providing a PropertyDrawer for (in this case, `SharedVector4`), and in the `GetFieldMaxWidth()` method, provide the space you want the property to take when visualised inside a referencing MonoBehaviour or ScriptableObject. This will really depend on the type you are embedding.

**Note:** This pre-made PropertyDrawer will only work for one-value types. For other types like structs and complex classes, you might have to write a PropertyDrawer from scratch.

For more information on this, refer to the Unity API Reference for [PropertyDrawers](https://docs.unity3d.com/ScriptReference/PropertyDrawer.html).


# Runtime Anchors

Runtime Anchors, very similarly to [Shared Values](/scriptable-object-tools/components/sharedvalues), in the sense that they are a value that is encased in a ScriptableObject. The difference with Shared Values is that, while Values are intended to hold a quantity or some identifier set at edit or runtime, Anchors hold a reference to a GameObject or Component that will only be provided in Play Mode.

A Runtime Anchor is always null when the game starts, and some object needs to write its reference into it to make it usable.

Accessing a Runtime Anchor and finding it's null means the object is not present or has been destroyed. By implementing simple null checks, you can create decoupled systems that can rely on objects from other scenes, and are independent from them if they haven't been instantiated.

You can think of Runtime Anchors like a "promise". The object referencing it already has the reference but not the value, but it can rely on the fact that at runtime the value will be provided by some other object.

Runtime Anchors come in two flavours: **individual**, and **sets**. A Runtime Anchor Set is simply a list of Anchors, all contained in one ScriptableObject. See below for usage of both cases.

### Sample usages 💡

A typical use for them is a Runtime Anchor with a reference to a Transform (or another component) that represents the player's character. This allows scripts from other scenes to find the player without having to perform stuff like `FindObjectOfType<>` which only works effectively with components existing in one copy, and is an expensive call anyways.

***

## Individual Runtime Anchors

Individual Runtime Anchors, as opposed to Runtime Anchor Sets, are meant to store only one value.

### Creating a new Runtime Anchor

To create a Runtime Anchor, simply position your mouse in the Project View and right click, then **Create > ScriptableObject Tools > Runtime Anchors**, and then choose the type you want to create.

### Referencing a Runtime Anchor in scripts

To reference the Runtime Anchor SO, simply declare a variable of its type, like usual:

```csharp
public TransformAnchor playerTransform;
```

and assign it using the Inspector.

### Providing a value to a Runtime Anchor

When referencing a Runtime Anchor, providing a value is as simple as calling the `Provide()` method and passing a correct type as an argument:

```csharp
private void Start()
{
    myTransform.Provide(transform);
}
```

This will also notify whoever is watching the Anchor and is listening to the event `OnAnchorProvided`.

### Reading an Anchor's value

To access the value of an Anchor, use its `Value` property, like this:

```csharp
public void Update()
{
    transform.LookAt(playerTransform.Value);
}
```

You can also (and it's good practice) check if the Anchor is null. Instead of doing a null check, you can use its `IsSet` boolean property, which is faster:

```csharp
if(playerTransform.IsSet) transform.LookAt(playerTransform.Value);
```

### Unsetting an Anchor

To correctly remove a value from an Anchor, call its `Unset()` method:

```csharp
myTransform.Unset();
```

There is no protection that prevents other objects to unset an Anchor, because Anchors have no concept of "owner".

Calling `Unset()` also invokes the `OnAnchorUnset` event, so that objects hooked into that can be notified of the change.

### Listening to an Anchor's changes in value

Anchors provide two events to listen to the changes to their value.

* `OnAnchorProvided` is called every time the value of an Anchor changes - but not to a null value.
* `OnAnchorUnset` is called when someone sets the Anchor to null.

***

## Runtime Sets

Runtime Sets are very similar to individual Runtime Anchors, and only differ in that they have additional tools to manage the list of values that is contained within the set. The list can be accessed using `.Values` but is not directly writable, but needs to be manipulated using the set's public methods:

* `AddToSet()`
* `RemoveFromSet()`
* `GetRandomElement()`
* `GetRandomElement(T elementToExclude)`

### Listening to changes in the set's values

Runtime Sets provide three events that objects can listen to:

* `OnElementAdded` is called when an element is added.
* `OnElementRemoved` is called when an element is removed, including if it's the last element.
* `OnSetEmptied` is called only when a set is purposely emptied by calling the method `EmptySet()`.

Note that `OnSetEmptied` is not called when the last element is removed via `OnElementRemoved`, to avoid objects firing both events accidentally.

An object that wants to fire `OnSetEmptied` when the last element is removed can, upon reacting to `OnElementRemoved`, check that the `IsEmpty` property is true, and invoke the code manually.

### When is the list reset

Because ideally many objects might want to add elements to a set, there might be no object in charge of emptying the set when exiting Play Mode. For this reason, `RuntimeAnchorSetBase` inherits from the `ManagedScriptableObject` class. Upon exiting Play Mode, the set will be emptied by the `Reset()` method.

See the [Managed Scriptable Object](/scriptable-object-tools/utilities/managedscriptableobject) page for more info.

***

## Extending Runtime Anchors

### Adding a new individual Runtime Anchor type

To create a new Runtime Anchor class holding a different type, all you need to do is to create a new C-sharp file, and in it, subclass `RuntimeAnchorBase<T>` like this (we'll use `Rigidbody` as an example):

```csharp
[CreateAssetMenu]
public class TransformAnchor : RuntimeAnchorBase<Rigidbody> { }
```

Nothing else is needed.

### Adding a new Runtime Set type

Similarly to individual Anchors, a new set can be added by just declaring a new class inheriting from `RuntimeAnchorSetBase<T>`:

```csharp
[CreateAssetMenu]
public class RigibodyAnchorSet : RuntimeAnchorSetBase<Rigidbody> { }
```


# Events

Events are ScriptableObjects which contain one event, either with one or no argument. You can think of them as channels that any object, from any scene, can tap into.

Additionally, they present a button in their Inspector that allows to fire the event on demand, for testing purposes.

### Sample usage 💡

In an action game, a player character Prefab could broadcast its death on a "OnPlayerDied" SO Event. Any object in the game that needs to react to it, all the way up to a game manager, can reference into that SO to react.

***

## Using Events

### Creating a new Event

To create a new Event, simply position your mouse in the Project View and right click, then **Create > ScriptableObject Tools > Events**, and then choose the type you want to create.

### Referencing an Event in scripts

Like usual, expose a public or serialised property of the right type:

```csharp
public VoidEvent playerDiedEvent;
// Or also
[SerializeField] private VoidEvent _playerDiedEvent;
```

### Listening to an event

The event contained in the ScriptableObject is not public, so to hook an object to an event, you can use the syntax as if the SO was the event itself.

```csharp
playerDiedEvent.AddListener(RespawnCharacter);
// and later...
playerDiedEvent.RemoveListener(RespawnCharacter);
```

### Firing an event

To fire on a SO Event, use the `Invoke()` method, passing the correct arguments:

```csharp
playerDiedEvent.Invoke();
playerHealthChanged.Invoke(-3);
```

***

## Extending Events

Extending the Event system with a new class is simple. To create a new event that carries one, two or three arguments, all you need to do is to create a new C# file and subclass one of the existing implementations.

For instance, inheriting from `EventOneArg<T>` like this (we'll use `Collider` as an example):

```csharp
[CreateAssetMenu]
public class ColliderEvent : EventOneArg<Collider> { }
```

In cases like these, nothing else is needed. The event SO will also display the Invoke button automatically.

{% hint style="info" %}
If your event's arguments are of type Struct, don't forget to add the `[Serializable]` attribute to your Struct.
{% endhint %}

### New event with four or more arguments

It's also possible to add an event with four or more arguments, but this guide doesn't cover it. You can use `EventThreeArg<T, TU, TV>` as a guide. You might also want to write a custom Inspector for it, using for instance `EventThreeArgsEditor` as a reference.


# AutoReset classes

To understand the usage of these classes, it's important to understand Unity's Enter Play Mode Options and the effect that not reloading the domain can have on ScriptableObjects.

The lifetime of a ScriptableObject, unlike a GameObject in the scene, doesn't start and finish with Play Mode. An SO can call its `OnEnable()` only once when the editor is started (or when code recompiles), so its state is not cleared when entering Play Mode (like it happens to GameObjects and their scripts).

For more information, read all about Unity's [Enter Play Mode Options](https://docs.unity3d.com/Manual/ConfigurableEnterPlayMode.html) and especially [disabling Domain Reload](https://docs.unity3d.com/Manual/DomainReloading.html) on their documentation.

To deal with these complications, ScriptableObject Tools provides three base classes `AutoResetOnEnterPlayMode` `AutoResetOnExitPlayMode` and `AutoResetOnBoth`. They expose methods that will be invoked when entering or exiting Play Mode, offering you a chance to reset the SO's state.

***

## Using these classes

To use one of the AutoReset classes, simply inherit from them and implement the abstract methods contained within: `OnEnterPlayMode()`, `OnExitPlayMode()`, or both; depending on the class.

For instance, if you wanted to make an SO that holds the score of the game, you want to make sure to reset it when the editor exits Play Mode, like this:

```csharp
[CreateAssetMenu]
public class MySmartSO : AutoResetOnExitPlayMode
{
    public int score;

    public void AddPoints(int points) => score += points;
    
    protected override void OnExitPlayMode()
    {
        score = 0;
    }
}
```

This way, even if no code resets the score, upon exiting Play Mode the `OnExitPlayMode()` will take care of that.

{% hint style="warning" icon="triangle-exclamation" %}
These classes set up their listeners in `OnEnable()` and `OnDisable()`.

If you want to use those methods you have to declare them as `override` and invoke the base ones to make sure the listeners are correctly set up:

```csharp
public class MySmartSO : AutoResetOnExitPlayMode
{
    protected override void OnEnable()
    {
        base.OnEnable();
        // This class' OnEnable code...
    }
}
```

{% endhint %}


# Descriptive Scriptable Object

The purpose of this simple class is to provide a text area at the top of a ScriptableObject for the developers to write a concise explanation of where the SO is used, what to expect from it, or any other short note.

### Sample usage 💡

For instance, a great idea when using a [Shared Value](/scriptable-object-tools/components/sharedvalues) SO is to write which objects in the game write to it. Writing who reads from it might lead to a long description that is not often up to date anyways.

When using [RuntimeAnchors](/scriptable-object-tools/components/runtimeanchors), it might make sense to write who is providing the value and in response to what event (is it in Awake, or later?).

***

## Using this class

To use this class, simply inherit from it. The inheritor will display the extra text area at the top of the Inspector.

The text value is editor-only, so it's discarded when making a build.


# Intro

<figure><img src="/files/PxPDmmTOS115KSXwVjEy" alt=""><figcaption></figcaption></figure>

SuperScenes is a framework that gives you the ability to attach components to Unity scenes. You can use them to store data, or to run code when the scene loads or unloads.

With the SuperScenes package installed, [adding components](/superscenes/using-superscenes/adding-removing-components) to a scene is as simple as doing it on a GameObject:

<figure><img src="/files/aBIPWIw6wjIadl2XJaQ7" alt="" width="375"><figcaption></figcaption></figure>

Once that is done, you can retrieve those components using some [simple API](/superscenes/using-superscenes/superscenes-api), and use their data.


# Changelog

### 1.1.2

(09/06/26)

* Null checks to guard against possible null reference exception on SuperScenes.Instance.
* Removed unused reference to Editor Coroutines.
* Reinforced checks for possible null reference errors.
* Removed wrong namespace.
* Fixed cleanup method when scene path is null.
* Fixed wrong URL in Welcome window.
* Fixed obsolete API for Unity 6.5, 6.6.

### 1.1.1

(09/02/25)

* Fixed an issue happening when Reimporting the whole project, that led to a loss of data because the SceneDataRegistry would get overwritten.

## 1.1.0 - OnGameStarted

(02/12/25)

* Introduced a new event that SceneComponents can respond to: [OnGameStarted](/superscenes/using-superscenes/superscenes-api#scenecomponent-base-class-api). This fires as soon as the game starts, both in the Editor (upon pressing Play) and in a build (when launching the game).
* Added settings to control the visibility and margin of the Scene shortcut icon in the Hierarchy.
* Fixed component names showing up with the whole namespace in the SceneComponent Property Drawer. Now they only display their class name.
* Fixed warning about UXML file's URI not being valid.
* Added Serializable attribute to SceneComponent template, to remove warning.

### 1.0.1

(08/09/25)

* Reorganised [API](/superscenes/using-superscenes/superscenes-api) so that it's easier to access scene components at runtime, even when the connected scene hasn't been loaded yet.

## 1.0.0 - First Release

(01/09/25)

* Adding components to scenes. Components are stored in SceneData SOs, indexed in a SceneDataRegistry SO.
* The SceneDataRegistry SO is automatically added to the Preloaded assets when building.
* A script template allows easy creation of new SceneComponents.
* Extension methods to the Scene struct type to access components.


# Defining new components

The first step to using SuperScenes is to create your own Scene Component types, as SuperScenes doesn't come with pre-made components out of the box.

{% hint style="info" %}
You will, however, find example components as part of the Package Samples in the Package Manager.
{% endhint %}

## Creating a new type

To create a new type, simply create a new class and implement the base abstract class `SceneComponent`. Then, add any data you need the component to hold.

For instance, a simple component that describes how enemy waves are spawn in a certain scene, could look like this:

```csharp
public class EnemyWaveData : SceneComponent
{
    public int numberOfEnemies;
    public int difficultyLevel;
}
```

Scene Components can hold any serializable type, and can hold them in `List<T>` or arrays.

You can store references to other Scenes, and to any other asset type like ScriptableObjects, Prefabs, etc. You can also store references to components present on Prefabs.

{% hint style="warning" %}
References to objects in the scene are not possible. This is a general Unity limitation.

To get a reference to an object in the scene, find it at runtime when the scene is loaded using some other method, like for instance `GameObject.Find()` or `Object.FindFirstObjectByType()`.
{% endhint %}

### SceneComponent script template

You can easily create a new Scene Component by just right-clicking in the Project view, and choosing **Create > SuperScenes > New Scene Component**.

<figure><img src="/files/pgQRn7yEiQp5cZVJ80Gx" alt="" width="233"><figcaption></figcaption></figure>

Very much like it happens for a regular MonoBehaviour with `Start` and `Update`, the script generated will contain a pre-made template for a functioning Scene Component, so you'll get a head-start.

## OnSceneLoaded / OnSceneUnloaded

Scene Components can also run logic. For instance:

```csharp
public class EnemyWaveData : SceneComponent
{
    public AudioManagerSO audioManager;
    public AudioClip backgroundMusicTrack;
    
    public void override OnSceneLoaded()
    {
        audioManager.Play(backgroundMusicTrack);
    }
}
```

In this example, we override the `OnSceneLoaded()` method from the `SceneComponent` base class. When this scene is loaded, the code will execute and the `AudioManagerSO` ScriptableObject will play the referenced `AudioClip`.

`SceneComponent` provides both `OnSceneLoaded` and `OnSceneUnloaded` methods.


# Adding/Removing components

Once you have at least one Scene Component type in your project, you can start adding components to scenes.

## Adding a component

To do so, simply select a Scene asset in the Project view, and look at its Inspector:

<figure><img src="/files/aBIPWIw6wjIadl2XJaQ7" alt="" width="375"><figcaption><p>Adding a scene component</p></figcaption></figure>

When you click the Add Scene Component button, all types available in the project will show up as a dropdown. Select the one you want to add.

Once added, Scene Component will appear just like Game Object components:

<figure><img src="/files/FeETRgCIAL53W2X2lKXE" alt="" width="375"><figcaption><p>The Inspector of a scene file, displaying 2 scene components</p></figcaption></figure>

## Removing a component

To remove a component, right-click on its header (or left-click on the three dots menu) and choose Remove Component.

<figure><img src="/files/zM7zaTgLGZygVYCFJjyM" alt="" width="359"><figcaption><p>Right-click to remove a component</p></figcaption></figure>


# SuperScenes API

## SceneComponent

This is the base abstract class that all scene components should derive from.

<details>

<summary>SceneComponent base class API</summary>

### scene

```csharp
public Scene scene;
```

The scene that the component is attached to. This is only valid at runtime, and only if the scene is currently loaded.

### OnGameStarted

```csharp
public virtual void OnGameStarted() { }
```

If implemented, this method will be executed when the game first starts, and only then. It runs both in the Editor (upon pressing Play) and in a build (when launching the game).

The method will not be invoked when the scene is loaded after the beginning of the game and thus, it will only ever run once.

{% hint style="success" %}
If you want a scene component to respond in the same way both when the game starts and when that scene is reloaded, just let one callback invoke the other, like in the following example.
{% endhint %}

{% code lineNumbers="true" %}

```csharp
[Serializable]
public class MySceneComponent : SceneComponent
{
    public override void OnGameStarted() => OnSceneLoaded();
    
    public override void OnSceneLoaded()
    {
        // Do something on both scene load and game start
    }
}
```

{% endcode %}

### OnSceneLoaded

```csharp
public virtual void OnSceneLoaded() { }
```

This method is invoked when the scene that the component is connected to has fully loaded by Unity's [Scene Manager](https://docs.unity3d.com/6000.1/Documentation/ScriptReference/SceneManagement.SceneManager.html). As such, you can inspect the scene's GameObjects in this method.

### OnSceneUnloaded

```csharp
public virtual void OnSceneLoaded() { }
```

This method is invoked when the scene that the component is connected to has been unloaded by Unity's [Scene Manager](https://docs.unity3d.com/6000.1/Documentation/ScriptReference/SceneManagement.SceneManager.html).

</details>

## SceneExtensions

At runtime, the static class `SceneExtensions` provides some extension methods for the built-in Unity struct `Scene`. This means you can just use an existing `Scene` reference, and invoke on it one of the available methods listed below:

<details>

<summary>SceneExtensions extensions class API</summary>

### GetComponent

{% code fullWidth="false" %}

```csharp
public static T GetComponent<T>(this Scene scene) where T : SceneComponent
```

{% endcode %}

Returns the first component of type `T` attached to the given `Scene` struct, if any is present. If no component of that type is present, it returns `null`.

If you are not sure if a component is present, you can use [TryGetComponent](#trygetcomponent) instead.

### TryGetComponent\<T>

{% code fullWidth="false" %}

```csharp
public static bool TryGetComponent<T>(this Scene scene, out T component)
where T : SceneComponent
```

{% endcode %}

Returns a boolean value representing whether the requested component of type `T` is present or not on the given `Scene` struct.

The output parameter `component` will contain a reference to the component or, if not present, it will contain `null`.

### GetComponents

{% code fullWidth="false" %}

```csharp
public static List<SceneComponent> GetComponents(this Scene scene)
```

{% endcode %}

Returns a list of all scene components present on the provided `Scene`. Returns an empty `List` if the scene has no components.

</details>

## SceneDataRegistry

The `SceneDataRegistry` ScriptableObject holds the index of all the `SceneDataSO` ScriptableObjects – which in turn hold the data for the components. You can use it to access components even before the related scene is loaded, but finding the component in the list is up to you.

<details>

<summary>SceneDataRegistry class API</summary>

### Instance

```csharp
public static SceneDataRegistry Instance
```

Holds a reference to the `SceneDataRegistry` ScriptableObject.

### sceneData

```csharp
public List<SceneDataSO> sceneData;
```

A list of all `SceneDataSO` objects.

### GetSceneData (string)

```csharp
public SceneDataSO GetSceneData(string scenePath)
```

Looks for a `SceneDataSO` where the path property matches the provided one. The path is intended to be project-related (i.e. starting from "Assets").

### GetSceneData (Scene)

```csharp
public SceneDataSO GetSceneData(Scene scene)
```

Looks for a `SceneDataSO` where the path property matches the path of the provided `Scene` struct.

</details>

## SceneDataSO

`SceneDataRegistrySO` ScriptableObjects hold the data for the scene components. You can reference them to access components even before the related scene is loaded.

<details>

<summary>SceneDataSO class API</summary>

### sceneAsset

```csharp
public SceneAsset sceneAsset;
```

The connected `SceneAsset`. This is only available in the editor.

### scenePath

```
public string scenePath;
```

The path of the targeted scene. Can be used at runtime to query for components even before the scene is loaded.

Note: at edit time, this is automatically provided by SuperScenes, no need to fill in manually.

### components

```csharp
[SerializeReference] public List<SceneComponent> components;
```

The list of scene components attached to the related scene.

### GetComponent\<T>

```csharp
public T GetComponent<T>() where T : SceneComponent
```

Tries to find a component in the list of the provided type. Returns `null` if not present.

### TryGetComponent\<T>

```csharp
public bool TryGetComponent<T>(out T component) where T : SceneComponent
```

Tries to find a component in the list of the provided type. The returned component will be null if not present.

</details>


# Understanding SuperScenes data

SuperScenes tries its best to work like magic and allow you to add and remove components with ease. However, if necessary, this page can give you more info on how SuperScenes data is stored, both in editor and at runtime.

## Edit-time data

### SceneDataSO

Components for a given scene are stored in a ScriptableObject of type `SceneDataSO`. Whenever you select a Scene asset to add components, a Scene Data SO is automatically created.

This ScriptableObject stores:

* A reference to the SceneAsset file (only for edit-time)
* The path to this file (for runtime)
* A list of Scene Components

The path cannot be edited, and will be inferred from the Scene asset, and refreshed both when the editor starts, and double-checked when the game builds.

### SceneDataRegistry

All Scene Data SO ScriptableObjects are referenced in another ScriptableObject, of type `SceneDataRegistry`.

This is supposed to exist only in one copy, and will be created for you when the editor starts. This one copy can be accessed using `SceneDataRegistry.Instance` (at both runtime and edit time).

### Data location

In the Unity editor, all the Scene Data SO and the Scene Data Registry ScriptableObjects are kept together in a specific folder. The path to this folder can be customised in **Project Settings > SuperScenes**.

You can customise the path to be anything you want: the data doesn't need to be inside a Resources folder.

{% hint style="warning" %}
If you modify the path and the assets already exist, ensure to move them to the new path before continuing.
{% endhint %}

## Runtime data

At runtime, the key to access the data becomes the Scene Data Registry ScriptableObject. This object is automatically added to the build's [Preloaded assets](https://docs.unity3d.com/6000.1/Documentation/ScriptReference/PlayerSettings.GetPreloadedAssets.html), so there is no action to take on your side.

When the game loads, the ScriptableObject will be loaded into memory before any scene loads. It will then be available to query at any time during the game, using the provided [SuperScenes API](/superscenes/using-superscenes/superscenes-api).


# Custom component Inspectors

To get full control over how a component draws its presence in the Inspector, you can implement a custom `PropertyDrawer` script for it.

{% hint style="info" %}
If you are unfamiliar with Property Drawers, check out [the official Unity documentation](https://docs.unity3d.com/6000.1/Documentation/ScriptReference/PropertyDrawer.html) for them.
{% endhint %}

To draw the component correctly, create a script and inherit from `SceneComponentDrawer` class. Then, override the `DrawComponent()` method, like this:

```csharp
using SuperScenes.Editor.CustomEditors;
using UnityEditor;
using UnityEngine.UIElements;

namespace SuperScenes.Editor
{
    [CustomPropertyDrawer(typeof(EnemyData))]
    public class EnemyDataPropertyDrawer : SceneComponentDrawer
    {
        protected override VisualElement DrawComponent(SerializedProperty property)
        {
            VisualElement inspector = base.DrawComponent(property);

            inspector.Add(new HelpBox("This box has been added by a custom PropertyDrawer.",
                HelpBoxMessageType.Info));

            return inspector;
        }
    }
}
```

In the method, you can create a completely new editor from scratch, or you can leverage `base.DrawComponent(property)` to still draw the original Inspector and add elements to it (like in the example above).

{% hint style="info" %}
To create a custom Property Drawer for Scene Components, you must use [UI Toolkit](https://docs.unity3d.com/6000.1/Documentation/Manual/UIElements.html).

However, you can still return an `IMGUIContainer` element from your override of `DrawComponent()` , and implement your UI in `OnGUI`. Check out Unity's own [IMGUIContainer documentation](https://docs.unity3d.com/Manual/UIE-uxml-element-IMGUIContainer.html).
{% endhint %}


# Intro

<figure><img src="/files/3WeX6cdxerFINIQia9xP" alt=""><figcaption></figcaption></figure>

Entering Play Mode is time-consuming for big and small projects. Tired of wasting time every time you need to do a tiny tweak?

Then start using [Fast Enter Play Mode](https://docs.unity3d.com/6000.3/Documentation/Manual/configurable-enter-play-mode.html) with a handy button that enables it for you, just before entering Play Mode!

* Press the **Fast Play** button to play FAST – without Domain and Scene reload
* Press the regular **Play** button to play as usual, with a full state reset


# Changelog

## 1.0.0 - First Release

(18/02/26)

* First release of the package.


# Setting up

{% hint style="info" %}
Please note: this utility is only compatible with Unity 6.3 and up.
{% endhint %}

## Enabling the button

To display the Fast Enter Play Mode button in the main Unity toolbar, click on the 3 dots in the top-right corner of the Unity editor, then choose **Fast Enter Play Mode > Fast Play Button**:

<figure><img src="/files/zgzy9LjAcm8d5PTpho3R" alt="" width="563"><figcaption></figcaption></figure>

Once the button has appeared, you can drag it to any position in the toolbar by holding Ctrl (or Cmd on Mac) and dragging with the Left Mouse button.

We recommend placing the button on the left of the Play Button, for easy access:

<figure><img src="/files/puzDmKl3aJdT7TgW85K6" alt="" width="563"><figcaption></figcaption></figure>

## Setting Enter Play Mode Settings

For the button to make sense, you want the setting in **Project Settings > Editor >** **Enter Play Mode Settings** to be set to its default value, which is *Reload Domain and Scene*.

This way, whenever you press the Fast button, you get "fast mode"; while pressing the regular Play button allows you to go into Play mode with a clean slate.


# How it works

With the button [enabled](/fast-enter-play-mode/setting-up), you now have the option to enter Play Mode in two ways:

* Press the **Fast Play** button to play without Domain and Scene reload
* Press the regular **Play** button to play as usual, with a full state reset

Read on to understand in detail how the Fast Enter Play Mode button works in conjunction with the regular Play button.

## What happens behind the scenes

When you press the Fast Play button, this plugin sets the option in **Project Settings > Editor > Enter Play Mode Settings** to *Do not reload Domain or Scene*, and then enters Play Mode, guaranteeing the maximum speed when playing the game.

Upon exiting Play Mode, the plugin sets the option back to *Reload Domain and Scene*. This means that the next time you press the regular Play mode button, Unity will reload both domain and scene, ensuring a clean slate that is guaranteed to work even with pieces of code that don't work well when the domain is not reloaded.

{% hint style="warning" %}
Because this plugin modifies the value of the **Enter Play Mode Settings** option, it might produce a change to the Project Settings asset. If you're using version control, you might want to ensure not to commit this to the rest of the team so it doesn't mess up with their setup.
{% endhint %}


