Files
zeling_v2/Assets/_Game/Scripts/World/FalseWall.cs

108 lines
4.0 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using BaseGames.Combat;
using BaseGames.Feedback;
using UnityEngine;
namespace BaseGames.World
{
/// <summary>
/// 假墙(秘密通道)。外观与普通墙相同,可通过攻击/接近揭示并穿越。
/// 揭示后禁用碰撞体(不销毁),状态通过 WorldStateRegistry 持久化。
/// WorldStateRegistrySaverISaveable统一负责将 Door 分类写入存档。
/// </summary>
[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<Collider2D>();
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
}
}