PlayerMovement:新增 _facingLocked 字段 + LockFacing(bool) 方法;UpdateFacing() 锁定时直接返回 WallSlideState:OnStateEnter 调用 LockFacing(true) + FlipFacing(_wallDir);OnStateExit 调用 LockFacing(false) 解锁 WallJumpState:OnStateEnter 保险性再调一次 LockFacing(false);WallJumpAway/Toward 同步写入 _inputVelocityX,确保解锁后 UpdateFacing 朝向正确(背墙跳 = 离墙方向,对墙跳 = 朝墙方向)
92 lines
3.4 KiB
C#
92 lines
3.4 KiB
C#
using System.Collections;
|
||
using UnityEngine;
|
||
using BaseGames.Feedback;
|
||
|
||
namespace BaseGames.World
|
||
{
|
||
/// <summary>
|
||
/// 碎裂平台。玩家踩上后经历 Warning → Crumbling → Gone → (Recovering) 四态。
|
||
/// _isOneShot = true 时碎裂后永久消失;_respawnDelay > 0 则在延迟后恢复。
|
||
/// </summary>
|
||
[RequireComponent(typeof(BoxCollider2D))]
|
||
public class CrumblePlatform : MonoBehaviour
|
||
{
|
||
[SerializeField] private float _warningDuration = 0.6f;
|
||
[SerializeField] private float _crumbleDuration = 0.3f;
|
||
[SerializeField] private float _respawnDelay = 3.0f; // 0 = 永久消失
|
||
[SerializeField] private bool _isOneShot = false;
|
||
[SerializeField] private SceneFeedback _crumbleFeedback; // 预警震动 + 碎裂粒子 + 音效
|
||
[SerializeField] private BoxCollider2D _passengerSensor; // IsTrigger,检测玩家踩踏
|
||
|
||
[Header("持久化(_isOneShot = true 时生效)")]
|
||
[Tooltip("平台唯一 ID。_isOneShot=true 时碎裂状态写入 WorldStateRegistry,重载场景后不复原。留空则不持久化。")]
|
||
[SerializeField] private string _platformId;
|
||
[SerializeField] private WorldStateRegistry _worldState;
|
||
|
||
private BoxCollider2D _col;
|
||
private SpriteRenderer _sr;
|
||
private bool _isCrumbling;
|
||
|
||
private void Awake()
|
||
{
|
||
_col = GetComponent<BoxCollider2D>();
|
||
_sr = GetComponent<SpriteRenderer>();
|
||
}
|
||
|
||
private void Start()
|
||
{
|
||
// 读档恢复:_isOneShot 平台已碎裂则直接禁用,无需等待触发
|
||
if (!_isOneShot || string.IsNullOrEmpty(_platformId) || _worldState == null) return;
|
||
if (!_worldState.HasFlag("crumble_" + _platformId)) return;
|
||
|
||
_isCrumbling = true;
|
||
_col.enabled = false;
|
||
_sr.enabled = false;
|
||
if (_passengerSensor != null) _passengerSensor.enabled = false;
|
||
}
|
||
|
||
private void OnTriggerEnter2D(Collider2D other)
|
||
{
|
||
if (_isCrumbling) return;
|
||
if (!other.CompareTag("Player")) return;
|
||
StartCoroutine(CrumbleSequence());
|
||
}
|
||
|
||
private IEnumerator CrumbleSequence()
|
||
{
|
||
_isCrumbling = true;
|
||
|
||
// 1. Warning(抖动)
|
||
_crumbleFeedback?.Play();
|
||
yield return new WaitForSeconds(_warningDuration);
|
||
|
||
// 2. Crumbling 动画等待
|
||
yield return new WaitForSeconds(_crumbleDuration);
|
||
|
||
// 3. Gone:禁用碰撞体 + 隐藏 Sprite
|
||
_col.enabled = false;
|
||
_sr.enabled = false;
|
||
if (_passengerSensor != null)
|
||
_passengerSensor.enabled = false;
|
||
|
||
if (_isOneShot || _respawnDelay <= 0f)
|
||
{
|
||
// 持久化一次性碎裂状态,场景重载后不复原
|
||
if (_isOneShot && !string.IsNullOrEmpty(_platformId))
|
||
_worldState?.SetFlag("crumble_" + _platformId);
|
||
yield break;
|
||
}
|
||
|
||
// 4. Respawn
|
||
yield return new WaitForSeconds(_respawnDelay);
|
||
|
||
_col.enabled = true;
|
||
_sr.enabled = true;
|
||
if (_passengerSensor != null)
|
||
_passengerSensor.enabled = true;
|
||
|
||
_isCrumbling = false;
|
||
}
|
||
}
|
||
}
|