多轮审查和修复
This commit is contained in:
144
Assets/Scripts/World/MovingPlatform.cs
Normal file
144
Assets/Scripts/World/MovingPlatform.cs
Normal file
@@ -0,0 +1,144 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using BaseGames.Core.Events;
|
||||
using UnityEngine;
|
||||
|
||||
namespace BaseGames.World
|
||||
{
|
||||
/// <summary>
|
||||
/// 移动平台。Kinematic Rigidbody2D,支持三种移动模式。
|
||||
/// 乘客跟随:OnTriggerEnter2D 时 SetParent,离开时还原并附加速度。
|
||||
/// </summary>
|
||||
[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<Transform> _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<Rigidbody2D>();
|
||||
_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<Rigidbody2D>();
|
||||
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
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user