using System.Collections; using System.Collections.Generic; using BaseGames.Core.Events; using UnityEngine; namespace BaseGames.World { /// /// 移动平台。Kinematic Rigidbody2D,支持三种移动模式。 /// 乘客跟随:OnTriggerEnter2D 时 SetParent,离开时还原并附加速度。 /// [RequireComponent(typeof(Rigidbody2D))] public class MovingPlatform : MonoBehaviour { public enum MoveType { LinearAB, WayPoints, TriggeredLinear } [Header("移动配置")] [SerializeField] private MoveType _moveType = MoveType.LinearAB; [SerializeField] private Transform[] _wayPoints; [SerializeField] private float _speed = 3f; [SerializeField] private float _waitAtEndpoint = 0.5f; [Header("TriggeredLinear 模式")] [SerializeField] private VoidEventChannelSO _activationChannel; [Header("乘客检测")] [SerializeField] private BoxCollider2D _passengerSensor; // IsTrigger,用于乘客 SetParent private Rigidbody2D _rb; private List _passengers = new(); private int _waypointIndex; private bool _movingForward = true; private bool _triggered; private bool _waiting; private readonly CompositeDisposable _subs = new(); private void Awake() { _rb = GetComponent(); _rb.bodyType = RigidbodyType2D.Kinematic; _rb.interpolation = RigidbodyInterpolation2D.Interpolate; } private void OnEnable() { _activationChannel?.Subscribe(OnTriggered).AddTo(_subs); } private void OnDisable() { _subs.Clear(); } private void FixedUpdate() { if (_wayPoints == null || _wayPoints.Length == 0) return; if (_moveType == MoveType.TriggeredLinear && !_triggered) return; if (_waiting) return; MoveTowardsNextWaypoint(); } private void MoveTowardsNextWaypoint() { var target = (Vector2)_wayPoints[_waypointIndex].position; var next = Vector2.MoveTowards(_rb.position, target, _speed * Time.fixedDeltaTime); _rb.MovePosition(next); if (Vector2.Distance(_rb.position, target) < 0.02f) StartCoroutine(WaitAndAdvance()); } private IEnumerator WaitAndAdvance() { _waiting = true; yield return new WaitForSeconds(_waitAtEndpoint); AdvanceWaypoint(); _waiting = false; } private void AdvanceWaypoint() { if (_moveType == MoveType.TriggeredLinear) { _waypointIndex = Mathf.Min(_waypointIndex + 1, _wayPoints.Length - 1); if (_waypointIndex == _wayPoints.Length - 1) _triggered = false; return; } if (_moveType == MoveType.LinearAB) { _movingForward = !_movingForward; _waypointIndex = _movingForward ? 1 : 0; } else // WayPoints { _waypointIndex = (_waypointIndex + 1) % _wayPoints.Length; } } private void OnTriggered() => _triggered = true; // ── Passenger Pattern ───────────────────────────────────────────────── private void OnTriggerEnter2D(Collider2D other) { if (!IsPassenger(other.gameObject)) return; other.transform.SetParent(transform); _passengers.Add(other.transform); } private void OnTriggerExit2D(Collider2D other) { if (!_passengers.Contains(other.transform)) return; other.transform.SetParent(null); _passengers.Remove(other.transform); // 离开时附加平台速度,避免卡顿 var passengerRb = other.GetComponentInParent(); if (passengerRb != null) passengerRb.AddForce(_rb.velocity, ForceMode2D.Impulse); } private static bool IsPassenger(GameObject go) { return go.CompareTag("Player") || go.CompareTag("Enemy"); } #if UNITY_EDITOR private void OnDrawGizmos() { if (_wayPoints == null || _wayPoints.Length < 2) return; Gizmos.color = new Color(1f, 0.8f, 0f, 0.8f); for (int i = 0; i < _wayPoints.Length - 1; i++) { if (_wayPoints[i] != null && _wayPoints[i + 1] != null) Gizmos.DrawLine(_wayPoints[i].position, _wayPoints[i + 1].position); } } #endif } }