using BaseGames.Combat; using BaseGames.Core; using BaseGames.Core.Save; using MoreMountains.Feedbacks; using UnityEngine; namespace BaseGames.World { /// /// 假墙(秘密通道)。外观与普通墙相同,可通过攻击/接近揭示并穿越。 /// 揭示后禁用碰撞体(不销毁),状态持久化到 WorldSaveData。 /// [RequireComponent(typeof(Collider2D))] public class FalseWall : MonoBehaviour, IDamageable, ISaveable { 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 MMF_Player _revealFeedback; private bool _isRevealed; // ── IDamageable ─────────────────────────────────────────────────────── public bool IsInvincible => _isRevealed; public int Defense => 0; public void TakeDamage(DamageInfo info) { if (_isRevealed || _revealCondition != RevealCondition.AttackOnce) return; Reveal(); } // ── Unity Lifecycle ─────────────────────────────────────────────────── private void Awake() { ServiceLocator.GetOrDefault()?.Register(this); } private void OnDestroy() { ServiceLocator.GetOrDefault()?.Unregister(this); } private void Start() { if (_revealCondition == RevealCondition.AlwaysOpen) { SetPassThroughImmediate(); _isRevealed = true; return; } } // ── ISaveable ───────────────────────────────────────────────────────── public void OnSave(SaveData data) { if (_isRevealed && !string.IsNullOrEmpty(_wallId) && !data.World.OpenedDoors.Contains(_wallId)) data.World.OpenedDoors.Add(_wallId); } public void OnLoad(SaveData data) { if (string.IsNullOrEmpty(_wallId)) return; _isRevealed = data.World.OpenedDoors.Contains(_wallId); if (_isRevealed) SetPassThroughImmediate(); } private void OnTriggerEnter2D(Collider2D other) { if (_isRevealed || _revealCondition != RevealCondition.Proximity) return; if (!other.CompareTag("Player")) return; // Proximity 模式:仅播放 Shimmer 暗示,碰撞仍启用 _revealFeedback?.PlayFeedbacks(); } // ── Implementation ──────────────────────────────────────────────────── private void Reveal() { _isRevealed = true; _revealFeedback?.PlayFeedbacks(); 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 } }