# 5. Arena Hazards During Phases Part of [[Boss Battles with Phases]]. Prev: [[4. Timeline Intros and Phase Transitions]]. Next: [[6. Worked Example Three-Phase Boss]]. A hazard that is always on is furniture. A hazard that *arrives with a phase* is a rule change, which is what a phase is for ([[1. Boss Design and the Arena]]). The trap logic itself lives in [[Hazards, Traps and Key-Door Puzzles]] (telegraph, then damage, then cooldown). This part is only the **director** that turns those traps on and off from `PhaseDefinition` data. ## 5.1 Id-based hazards Give each trap a stable string id (`floor-ring`, `west-jets`, `collapsed-ledge`). The phase asset lists which ids to enable and disable. The director does not know what a jet is. ```csharp using System.Collections.Generic; using UnityEngine; public interface IArenaHazard { string Id { get; } void SetHazardActive(bool active); } /// <summary> /// Finds scene hazards and applies phase enable/disable lists. /// NOT compiled in Unity. /// </summary> public sealed class ArenaHazardDirector : MonoBehaviour { readonly Dictionary<string, IArenaHazard> _hazards = new(); void Awake() { var found = GetComponentsInChildren<MonoBehaviour>(true); for (int i = 0; i < found.Length; i++) { if (found[i] is IArenaHazard h && !string.IsNullOrEmpty(h.Id)) _hazards[h.Id] = h; } } public void SetActiveHazards(string[] enableIds, string[] disableIds) { if (disableIds != null) { for (int i = 0; i < disableIds.Length; i++) if (_hazards.TryGetValue(disableIds[i], out var h)) h.SetHazardActive(false); } if (enableIds != null) { for (int i = 0; i < enableIds.Length; i++) if (_hazards.TryGetValue(enableIds[i], out var h)) h.SetHazardActive(true); } } } ``` A thin adapter around whatever trap component the hazards series ships: ```csharp using UnityEngine; public sealed class ArenaHazardProxy : MonoBehaviour, IArenaHazard { [SerializeField] string id = "floor-ring"; [SerializeField] Behaviour trap; // a TimedTrap, or any enabled/disabled behaviour public string Id => id; public void SetHazardActive(bool active) { if (trap != null) trap.enabled = active; else gameObject.SetActive(active); if (!active) { // Optional: if the trap exposes a ForceSafe() / Deactivate, call it so a // mid-telegraph jet does not fire after the phase has moved on. } } } ``` When you write `TimedTrap` in the hazards series, add a `ForceSafe()` and call it from here. Until then, disabling the behaviour mid-telegraph is a known pitfall (part 7): the trap should also disable its hitbox in `OnDisable`. ## 5.2 What to change per phase | Phase | Hazard idea | Why it is a rule change | |---|---|---| | 1 | None, or a slow perimeter fire | Teach the boss moves in a clean floor | | 2 | Floor ring or water that matches a slam | The tell now has a second consequence | | 3 | Collapsed edges, smaller safe island | Space itself gets tighter | Do not turn on every trap at Phase 2 "for difficulty." The player should be able to name what changed. Hazards still telegraph. A phase enter is not permission to drop a rock. If a new trap appears, give it a show (a rumble, a Timeline sting, a rising glow) *before* it can damage. ## 5.3 Exercise List three hazard ids on paper, assign them to phases, and confirm a student can explain the Phase 2 rule in one sentence. If they cannot, the hazard is noise. ## Sources - [[Hazards, Traps and Key-Door Puzzles]] - [[Level Up! (Review)]] Levels 11-12