A high-performance automatic door system using Unity ECS (Entities) with pooled audio and colliders. Supports rotating and sliding doors, single and double configurations. Features distance-based culling, object pooling for AudioSources and BoxColliders
npm install fr.jeanf.automaticdoorsystemA high-performance automatic door system using Unity ECS (Entities) with pooled audio and colliders for optimal performance with hundreds of doors.
---
1. System Overview
2. Prerequisites
3. Part 1: Creating Door Configurations
4. Part 2: Setting Up Door Prefabs
5. Part 3: Adding Doors to Subscenes
6. Part 4: Main Scene Setup
7. Part 5: Setting Up Door Identifiers
8. Part 6: Player Setup
9. Part 7: Audio Configuration (Optional)
10. Troubleshooting
---
This door system uses:
- Unity ECS for efficient door state management and animation
- Subscenes for doors (better loading performance)
- Object pooling for audio sources and colliders (handles hundreds of doors)
- Distance-based culling to only activate nearby doors
```
SUBSCENE (ECS World) MAIN SCENE (MonoBehaviour World)
+---------------------------+ +----------------------------------+
| Door Prefab | | DoorManagement |
| - DoorAuthoring | | - BoxColliderPoolManager |
| - DoorConfig (SO) | <----> | - AudioSourcePoolManager |
| - Door Meshes + Colliders | | - DoorDataBridge |
| - TriggerVolume | | - DoorAudioBridge |
+---------------------------+ +----------------------------------+
|
v
+----------------------------------+
| DoorIdentifier (per door) |
| - Links doorNumber to ECS door |
| - Audio configuration reference |
+----------------------------------+
---
- Unity 2022.3 LTS or newer
- Entities package installed
- Basic understanding of Unity's Subscene system
---
Door configurations are ScriptableObjects that define how a door behaves. Multiple doors can share the same configuration.
1. In the Project window, right-click in your desired folder
2. Select Create > AutomaticDoorSystem > DoorConfig
3. Name it descriptively (e.g., DoorConfig_DoubleRotating_90deg)
!Screenshot: 01_create_doorconfig.png
Right-click > Create > AutomaticDoorSystem > DoorConfig
Select your new DoorConfig and configure it in the Inspector:
| Setting | Description | Recommended Values |
|---------|-------------|-------------------|
| Door Movement | Rotating or Sliding | Choose based on door type |Single
| Door Count | or Double | Single = 1 panel, Double = 2 panels |Forward
| Opening Style | How double doors open | (both away from player) |90
| Open Forward Angle | Rotation when opening forward | |-90
| Open Backward Angle | Rotation when opening backward | |(1.5, 0, 0)
| Slide Open Offset | Distance to slide (sliding doors) | |1.0
| Animation Duration | How fast the door opens/closes | - 1.5 seconds |3.0
| Auto Close Delay | Time before auto-closing | seconds |Player
| Can Open Layer Mask | Which layers can trigger doors | Select layer |false
| Start Locked | Should door start locked? | Usually |
!Screenshot: 02_doorconfig_inspector.png
DoorConfig Inspector with all settings visible
---
Create a new prefab with this exact hierarchy structure:
``
Door_DoubleRotating <- Root GameObject (DoorAuthoring goes here)
├── LeftDoorMesh <- Left door panel (mesh + BoxCollider)
├── RightDoorMesh <- Right door panel (mesh + BoxCollider)
└── TriggerVolume <- Detection zone (DoorTriggerVolumeAuthoring)
For single doors, use this structure instead:
``
Door_SingleRotating <- Root GameObject (DoorAuthoring goes here)
├── DoorMesh <- Door panel (mesh + BoxCollider)
└── TriggerVolume <- Detection zone
!Screenshot: 03_door_hierarchy.png
Door prefab hierarchy in the Hierarchy window
1. Select the root GameObject (e.g., Door_DoubleRotating)
2. Click Add Component and add DoorAuthoring
3. Configure the DoorAuthoring component:
| Field | What to Assign |
|-------|---------------|
| Door Id | Unique number for this door (e.g., 1, 2, 3...) |
| Door Mesh | (Single doors only) Drag your DoorMesh here |
| Left Door Mesh | (Double doors) Drag LeftDoorMesh here |
| Right Door Mesh | (Double doors) Drag RightDoorMesh here |
| Trigger Volume Object | Drag TriggerVolume GameObject here |
| Door Config | Drag your DoorConfig asset here |
| Enable Debug | Check for gizmo visualization |
!Screenshot: 04_doorauthoring_inspector.png
DoorAuthoring component configured for a double door
Important: BoxColliders on door meshes are essential for player collision!
1. Select each door mesh (e.g., LeftDoorMesh)
2. Click Add Component > BoxCollider
3. Adjust the collider to match your door's visual size:
- Click Edit Collider button in the Inspector
- Drag the green handles to fit the door mesh
- Or manually set Size and Center values
Typical values for a standard door:
- Size: (1.0, 2.2, 0.08) (width, height, thickness)(0.5, 1.1, 0)
- Center: (offset from pivot)
!Screenshot: 05_door_collider_setup.png
BoxCollider on LeftDoorMesh with Edit Collider mode active
!Screenshot: 06_collider_gizmo_scene.png
Scene view showing the green BoxCollider outline on door meshes
> Note: These colliders won't work directly in subscenes for physics. The system extracts their size/center during baking and applies them to pooled colliders at runtime.
1. Select the TriggerVolume child GameObject
2. Add the DoorTriggerVolumeAuthoring component
3. Configure the detection zone:
| Field | Description | Recommended Value |
|-------|-------------|-------------------|
| Volume Size | Size of the trigger box | (3.5, 3.0, 3.5) |(0, 1.5, 0)
| Volume Center | Center offset | |
!Screenshot: 07_triggervolume_inspector.png
DoorTriggerVolumeAuthoring component settings
The trigger volume appears as a green wireframe box when selected in the Scene view.
!Screenshot: 08_triggervolume_gizmo.png
Scene view showing the trigger volume gizmo
1. Drag the root GameObject from Hierarchy to your Project window
2. Save it in a folder like Assets/Prefabs/Doors/Door_DoubleRotating.prefab
3. Name it clearly (e.g., )
---
1. In your scene, select GameObject > New Sub Scene > Empty Sub Scene
2. Name it (e.g., Subscene_Building1_Doors)
3. The subscene appears in the Hierarchy with a special icon
!Screenshot: 09_create_subscene.png
Creating a new subscene
1. Double-click the subscene to open it for editing (or right-click > Open)
2. Drag your door prefab from the Project window into the subscene
3. Position the door in your scene
4. Important: Set a unique Door Id for each door instance
!Screenshot: 10_door_in_subscene.png
Door prefab placed inside an open subscene
Each door must have a unique Door ID. This ID links the ECS door to its MonoBehaviour DoorIdentifier.
1. Select the door in the subscene
2. In the DoorAuthoring component, set Door Id to a unique number
3. Write down or remember this number - you'll need it for the DoorIdentifier later
| Door | Door ID |
|------|---------|
| Entrance Door | 1 |
| Office Door | 2 |
| Storage Door | 3 |
| ... | ... |
!Screenshot: 11_unique_door_ids.png
Multiple doors with unique Door IDs
1. Right-click the subscene in Hierarchy
2. Select Close
3. The subscene will bake and convert to ECS entities
---
The Main Scene contains the DoorManagement system that handles pooled resources.
1. In your Main Scene (not a subscene), create an empty GameObject
2. Name it DoorManagement(0, 0, 0)
3. Position it at - position doesn't matter, but keep it organized
!Screenshot: 12_doormanagement_create.png
DoorManagement GameObject in the Main Scene hierarchy
Add these four components to the DoorManagement GameObject:
#### Component 1: BoxColliderPoolManager
Purpose: Creates pooled BoxColliders that follow door panels for physics collision.
| Setting | Description | Recommended Value |
|---------|-------------|-------------------|
| Max Pool Size | Maximum active colliders | 25 |25
| Culling Distance | Range to activate colliders | meters |0.5
| Distance Check Interval | How often to update | seconds |0.5
| Minimum Spacing | Prevent duplicate colliders | meters |1.3
| Reassignment Threshold | Hysteresis for stability | |true
| Keep Out Of Range Assignments | Reduce reassignments | |
!Screenshot: 13_boxcolliderpoolmanager.png
BoxColliderPoolManager component settings
#### Component 2: AudioSourcePoolManager
Purpose: Creates pooled AudioSources for door sounds (open, close, lock, unlock).
| Setting | Description | Recommended Value |
|---------|-------------|-------------------|
| Audio Source Prefab | Optional custom prefab | Leave empty for default |
| Max Pool Size | Maximum active audio sources | 25 |25
| Culling Distance | Range to activate audio | meters |0.5
| Distance Check Interval | How often to update | seconds |0.5
| Minimum Source Spacing | Prevent overlapping sounds | meters |1.3
| Reassignment Threshold | Hysteresis for stability | |true
| Keep Out Of Range Assignments | Reduce reassignments | |0.1
| Fade Duration | Volume fade time | seconds |
!Screenshot: 14_audiosourcepoolmanager.png
AudioSourcePoolManager component settings
#### Component 3: DoorDataBridge
Purpose: Bridges data between ECS doors and MonoBehaviour world. Caches door positions and states.
This component has no visible settings - just add it.
!Screenshot: 15_doordatabridge.png
DoorDataBridge component (no settings)
#### Component 4: DoorAudioBridge
Purpose: Routes audio events from ECS to the pooled AudioSources.
This component has no visible settings - just add it.
!Screenshot: 16_dooraudiobridge.png
DoorAudioBridge component (no settings)
Your DoorManagement GameObject should now have all 4 components:
!Screenshot: 17_doormanagement_complete.png
Complete DoorManagement setup with all 4 components
---
DoorIdentifier components live in the Main Scene and link each door's audio configuration to its Door ID.
For each door in your subscenes, create a corresponding DoorIdentifier in the Main Scene:
1. Create an empty GameObject in the Main Scene
2. Name it DoorIdentifier_[DoorID] (e.g., DoorIdentifier_001)
3. Position it at the same location as the subscene door (approximate is fine)
!Screenshot: 18_dooridentifier_create.png
DoorIdentifier GameObject created in Main Scene
1. Add the DoorIdentifier component
2. Configure these settings:
| Field | Description | Value |
|-------|-------------|-------|
| Door Number | Must match the Door ID in DoorAuthoring | Same as subscene door |
| Audio Configuration | Optional audio settings asset | Assign if using custom audio |
!Screenshot: 19_dooridentifier_inspector.png
DoorIdentifier component showing Door Number field
Create a parent GameObject to keep things organized:
``
DoorIdentifiers <- Parent (empty GameObject)
├── DoorIdentifier_001
├── DoorIdentifier_002
├── DoorIdentifier_003
└── ...
!Screenshot: 20_dooridentifiers_organized.png
Organized DoorIdentifiers under a parent
> Tip: You can batch-create DoorIdentifiers for many doors at once using a simple editor script.
---
The player needs to be able to trigger doors.
1. Select your Player GameObject (the one with the CharacterController or Rigidbody)
2. Add the DoorTriggerableAuthoring component
3. Set the Player's Layer to match the door's Can Open Layer Mask
!Screenshot: 21_player_triggerable.png
Player with DoorTriggerableAuthoring component
1. Check your Player's layer (top-right of Inspector)
2. Ensure your DoorConfig's Can Open Layer Mask includes this layer
!Screenshot: 22_player_layer_check.png
Checking player layer matches DoorConfig layer mask
The pooling system uses Camera.main for distance calculations.
1. Ensure your main camera has the MainCamera tag
2. Or ensure it's the first enabled camera in the scene
---
1. Right-click in Project > Create > Automatic Door System > Door Audio Configuration
2. Name it (e.g., DoorAudio_Wood)
!Screenshot: 23_create_audioconfig.png
Creating a Door Audio Configuration
| Setting | Description |
|---------|-------------|
| Volume | Master volume (0-1) |
| Spatial Blend | 0 = 2D, 1 = 3D |
| Min/Max Distance | 3D audio rolloff range |
| Open Sound Clips | Array of sounds for opening |
| Close Sound Clips | Array of sounds for closing |
| Lock/Unlock Sound Clips | Sounds for lock events |
!Screenshot: 24_audioconfig_inspector.png
Door Audio Configuration with sound clips assigned
1. Select your DoorIdentifier
2. Drag the Audio Configuration asset to the Audio Configuration field
!Screenshot: 25_assign_audioconfig.png
Assigning audio configuration to DoorIdentifier
---
1. Check Player has DoorTriggerableAuthoring component
2. Check Player layer matches DoorConfig's Can Open Layer Mask
3. Check TriggerVolume size is large enough
4. Check subscene is closed (baked to ECS)
1. Check BoxColliders exist on door meshes in prefab
2. Check BoxColliderPoolManager exists in Main Scene
3. Check Culling Distance is large enough
1. Check AudioSourcePoolManager exists in Main Scene
2. Check DoorIdentifier has matching Door Number
3. Check Audio Configuration has sound clips assigned
4. Check Camera.main exists (tagged MainCamera)
- Ensure DoorAuthoring.doorId matches DoorIdentifier.doorNumber exactly
---
Save screenshots with these exact names in an images/ folder next to this README:
| Filename | What to Capture |
|----------|-----------------|
| 01_create_doorconfig.png | Right-click menu showing Create > AutomaticDoorSystem > DoorConfig |02_doorconfig_inspector.png
| | DoorConfig asset selected, showing all Inspector settings |03_door_hierarchy.png
| | Door prefab hierarchy (Root > DoorMeshes > TriggerVolume) |04_doorauthoring_inspector.png
| | DoorAuthoring component with all fields configured |05_door_collider_setup.png
| | BoxCollider on door mesh in Inspector with Edit Collider active |06_collider_gizmo_scene.png
| | Scene view showing green BoxCollider wireframes on doors |07_triggervolume_inspector.png
| | DoorTriggerVolumeAuthoring component settings |08_triggervolume_gizmo.png
| | Scene view showing green trigger volume wireframe |09_create_subscene.png
| | GameObject menu showing New Sub Scene option |10_door_in_subscene.png
| | Door prefab inside open subscene in Hierarchy |11_unique_door_ids.png
| | Multiple doors selected showing different Door IDs |12_doormanagement_create.png
| | DoorManagement empty GameObject in Main Scene |13_boxcolliderpoolmanager.png
| | BoxColliderPoolManager component with all settings |14_audiosourcepoolmanager.png
| | AudioSourcePoolManager component with all settings |15_doordatabridge.png
| | DoorDataBridge component (simple, no settings) |16_dooraudiobridge.png
| | DoorAudioBridge component (simple, no settings) |17_doormanagement_complete.png
| | DoorManagement with all 4 components visible |18_dooridentifier_create.png
| | DoorIdentifier empty GameObject in Main Scene |19_dooridentifier_inspector.png
| | DoorIdentifier component showing Door Number field |20_dooridentifiers_organized.png
| | Multiple DoorIdentifiers organized under parent |21_player_triggerable.png
| | Player with DoorTriggerableAuthoring component |22_player_layer_check.png
| | Player Inspector showing layer, DoorConfig showing mask |23_create_audioconfig.png
| | Right-click menu showing Create audio config option |24_audioconfig_inspector.png
| | DoorAudioConfiguration with clips assigned |25_assign_audioconfig.png` | DoorIdentifier with audio config assigned |
|
---