Room System Overview - AlexisBliesener/Bewitched GitHub Wiki

Overview

A room controller system locks the door automatically when the player enters the room. Enemies will remain despawned/inactive until the room is entered. If the last enemy is defeated, the doors unlock automatically.

image

Designer Guide

Setting Up a Room System

  1. Add Room System:

    • Add the RoomSystem prefab into the scene
      • RoomSystem prefab can be found in /Assets/Prefabs/RoomSystem/RoomSystem.prefab
    • This acts as a container and manager for all rooms in the scene
    • The RoomSystem is a singleton - only one should exist per scene
  2. Create Rooms:

    • Use the "Add New Room" button in the RoomSystem inspector
    • Each room is automatically created as a child object with a RoomController component
    • Rooms are automatically named (Room_01, Room_02, etc.) [This is changeable!]

Managing Rooms in the Inspector

  • Room List: Shows all rooms with their current status (the status shows only in runtime !) :
    • Select Button: Highlight the room in the hierarchy and ping it
    • Focus Button: Select the room and frame it in the scene view
    • Delete Button: Remove the room
    • Status Display: Show the room state (Inactive/Active/Cleared), the number of enemies spawned after the room became active, and the number of enemies detected by the system.

Configuring Individual Rooms

After creating a room, select it to configure:

  1. Configure Room Bounds:

    • Set the Room Bounds to define the area where enemies will be detected and spawned
      • All enemies in the bounds will be detected and added to the room
    • Set the Entry Trigger Bounds to define when the player enters the room
      • This activates enemies and locks doors when the player enters this area
      • Once the room is active, enemies will be spawned and doors will be locked
  2. Configure Enemy Detection:

    • Set the Enemy Layer Mask to match the enemy layer
    • Set the Enemy Tag to match the enemy prefab tags (default: "Enemy")

Adding Enemies

  1. Automatic Detection (Recommended):
  • Place enemy GameObjects within the Room Bounds
  • Make sure enemies have the correct tag and layer
  • Enemies will be automatically detected and added to the room's enemy list
  1. Manual Adding:
  • Drag enemy GameObjects directly into the Room Enemies list in the inspector
  • Useful for specific enemy placement

Adding Doors

  1. Create Door GameObjects: Ensure the doors implement the IDoor interface
  2. Add to Room: Drag door GameObjects into the Doors Objects list in the inspector
  3. Door Behavior:
    • Doors will automatically lock when the player enter the room
    • Doors will unlock when all enemies are defeated

Developer Guide

RoomSystem Singleton

Access the RoomSystem from anywhere in the code:

// Get a specific room
RoomController room = RoomSystem.Instance.GetRoom("Room_01");
RoomController roomByIndex = RoomSystem.Instance.GetRoom(0);

// Can subscribe to any room and get notified when the player enters 

// Get room count
int totalRooms = RoomSystem.Instance.GetRoomCount();

Global Events

  • OnAnyRoomEntered (RoomController room): Triggered when any room is entered
  • OnAnyRoomCleared (RoomController room): Triggered when any room is cleared
  • OnAnyRoomStateChanged (RoomController room, RoomState newState): Triggered when any room's state changes

The RoomSystem broadcast events for all rooms which allow any class to listen for room activities:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class RoomTest: MonoBehaviour
{
    private void OnEnable()
    {
        // Subscribe to global room events
        RoomSystem.OnAnyRoomEntered += HandleAnyRoomEntered;
        RoomSystem.OnAnyRoomCleared += HandleAnyRoomCleared;
        RoomSystem.OnAnyRoomStateChanged += HandleAnyRoomStateChanged;
    }

    private void OnDisable()
    {
        // Unsubscribe from global room events
        RoomSystem.OnAnyRoomEntered -= HandleAnyRoomEntered;
        RoomSystem.OnAnyRoomCleared -= HandleAnyRoomCleared;
        RoomSystem.OnAnyRoomStateChanged -= HandleAnyRoomStateChanged;
    }

    private void HandleAnyRoomEntered(RoomController room)
    {
        Debug.Log($"Player entered room: {room.gameObject.name}");
    }

    private void HandleAnyRoomCleared(RoomController room)
    {
        Debug.Log($"Room cleared: {room.gameObject.name}");
    }

    private void HandleAnyRoomStateChanged(RoomController room, RoomState newState)
    {
        Debug.Log($"Room {room.gameObject.name} changed to state: {newState}");
    }
}

Individual Room Events

You can still subscribe to individual room events if needed!

Door Interface Implementation

To create custom doors, implement the IDoor interface:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class SampleDoor : MonoBehaviour, IDoor
{
    // <summary>
    // This is a sample code to lock the door
    // it can be use later like for animation or other things
    // </summary>
    public void Lock()
    {
        gameObject.SetActive(true);
    }
    // <summary>
    // This is a sample code to unlock the door
    // it can be use later like for animation or other things
    // </summary>
    public void Unlock()
    {
        gameObject.SetActive(false);
    }
}

Questions to be considered:

Q: I have an area that is not rectangular, how do I use the stupid Automatic Detection box since it's not a rectangle?

image

A: You can create a rectangle like this and add the two enemies that are out of the rectangle to the list and it will work!

image image

The system isn't that smart (yet), so we have to help it out a little. Just make the Room Bounds big enough to catch most of the enemies, then manually drag the enemies that are out of the room bounds into the Room Enemies list.

⚠️ **GitHub.com Fallback** ⚠️