// MIT License - Copyright (c) 2025 wallstop // Full license text: https://github.com/wallstop/unity-helpers/blob/main/LICENSE namespace WallstopStudios.UnityHelpers.Tags { using System; using System.Collections.Generic; using Core.Attributes; using UnityEngine; /// /// Monitors the TagHandler for a specific tag that disables/enables colliders on this GameObject. /// When the "CollisionDisabledTag" is applied, all enabled colliders are disabled and tracked. /// When the tag is removed, the colliders are re-enabled. /// /// /// /// This component provides a tag-based way to temporarily disable collision detection, /// useful for effects like invulnerability, phasing, or ghost mode. /// /// /// Example usage: /// /// // Apply an effect with the CollisionDisabledTag /// AttributeEffect ghostMode = ...; /// ghostMode.effectTags.Add(CollisionSenses.CollisionDisabledTag); /// gameObject.ApplyEffect(ghostMode); /// /// // Colliders are now disabled /// // When the effect expires, colliders are automatically re-enabled /// /// /// [DisallowMultipleComponent] [RequireComponent(typeof(TagHandler))] public sealed class CollisionSenses : MonoBehaviour { /// /// The tag name that triggers collision disable/enable behavior. /// public const string CollisionDisabledTag = nameof(CollisionDisabledTag); [SiblingComponent] #pragma warning disable CS0649 // Field is never assigned to, and will always have its default value private TagHandler _tagHandler; #pragma warning restore CS0649 // Field is never assigned to, and will always have its default value private readonly List _managedColliders = new(); private void Awake() { this.AssignRelationalComponents(); } private void OnEnable() { if (_tagHandler.HasTag(CollisionDisabledTag)) { StartManagingColliders(); } _tagHandler.OnTagAdded += CheckForTagAddition; _tagHandler.OnTagRemoved += CheckForTagRemoval; } private void OnDisable() { _tagHandler.OnTagAdded -= CheckForTagAddition; _tagHandler.OnTagRemoved -= CheckForTagRemoval; StopManagingColliders(); } private void CheckForTagAddition(string addedTag) { if (!isActiveAndEnabled) { return; } if (string.Equals(addedTag, CollisionDisabledTag, StringComparison.Ordinal)) { StartManagingColliders(); } } private void CheckForTagRemoval(string removedTag) { if (!isActiveAndEnabled) { return; } if (string.Equals(removedTag, CollisionDisabledTag, StringComparison.Ordinal)) { StopManagingColliders(); } } private void StopManagingColliders() { foreach (Collider2D managedCollider in _managedColliders) { if (managedCollider != null) { managedCollider.enabled = true; } } _managedColliders.Clear(); } private void StartManagingColliders() { GetComponentsInChildren(_managedColliders); _managedColliders.RemoveAll(managed => !managed.enabled); foreach (Collider2D managedCollider in _managedColliders) { managedCollider.enabled = false; } } } }