using BaseGames.Combat; using BaseGames.Feedback; using UnityEngine; namespace BaseGames.World { /// /// 假墙(秘密通道)。外观与普通墙相同,可通过攻击/接近揭示并穿越。 /// 揭示后禁用碰撞体(不销毁),状态通过 WorldStateRegistry 持久化。 /// WorldStateRegistrySaver(ISaveable)统一负责将 Door 分类写入存档。 /// [RequireComponent(typeof(Collider2D))] public class FalseWall : MonoBehaviour, IDamageable { public enum RevealCondition { Proximity, AttackOnce, AlwaysOpen } [Header("识别")] [SerializeField] private string _wallId; [Header("揭示条件")] [SerializeField] private RevealCondition _revealCondition = RevealCondition.AttackOnce; [SerializeField] private float _proximityRadius = 2.0f; [Header("组件引用")] [SerializeField] private Collider2D _wallCollider; [SerializeField] private SpriteRenderer _renderer; [SerializeField] private SceneFeedback _revealFeedback; [Header("World State")] [Tooltip("绑定场景唯一的 WorldStateRegistry ScriptableObject,用于持久化揭示状态。")] [SerializeField] private WorldStateRegistry _registry; private bool _isRevealed; // ── IDamageable ─────────────────────────────────────────────────────── public bool IsAlive => true; public bool IsInvincible => _isRevealed; public int Defense => 0; public void TakeDamage(DamageInfo info) { if (_isRevealed || _revealCondition != RevealCondition.AttackOnce) return; Reveal(); } // ── Unity Lifecycle ─────────────────────────────────────────────────── private void Start() { if (_revealCondition == RevealCondition.AlwaysOpen) { SetPassThroughImmediate(); _isRevealed = true; return; } // 从 WorldStateRegistry 恢复揭示状态(注册表由 WorldStateRegistrySaver.OnLoad 填充) if (!string.IsNullOrEmpty(_wallId) && (_registry?.IsDoorOpened(_wallId) ?? false)) { _isRevealed = true; SetPassThroughImmediate(); } } private void OnTriggerEnter2D(Collider2D other) { if (_isRevealed || _revealCondition != RevealCondition.Proximity) return; if (!other.CompareTag("Player")) return; // Proximity 模式:仅播放 Shimmer 暗示,碰撞仍启用 _revealFeedback?.Play(); } // ── Implementation ──────────────────────────────────────────────────── private void Reveal() { _isRevealed = true; _registry?.MarkDoorOpened(_wallId); _revealFeedback?.Play(); SetPassThroughImmediate(); } private void SetPassThroughImmediate() { if (_wallCollider != null) _wallCollider.enabled = false; // 切换 Sprite 到透明/揭示帧(由子类或动画处理) } #if UNITY_EDITOR private void OnDrawGizmosSelected() { Gizmos.color = new Color(0.6f, 0.2f, 1f, 0.8f); var col = GetComponent(); if (col != null) Gizmos.DrawWireCube(transform.position, col.bounds.size); if (_revealCondition == RevealCondition.Proximity) { Gizmos.color = new Color(0.6f, 0.2f, 1f, 0.2f); Gizmos.DrawWireSphere(transform.position, _proximityRadius); } } #endif } }