using UnityEngine;
/// <summary>
/// GAME 1303 Tier 1 — Platform that travels between waypoints and carries the player.
///
/// SETUP
/// 1. Platform GameObject: SpriteRenderer, BoxCollider2D, Rigidbody2D (Body Type = Kinematic),
/// and this script.
/// 2. Create empty child objects as waypoints, then UN-parent them (drag out to scene root)
/// so they don't move with the platform. Drag them into the Waypoints list in order.
/// 3. Loop = go A→B→C→A. Ping-Pong = A→B→C→B→A.
/// 4. The player is carried by being parented while standing on top. If your player
/// is a prefab and you get scale weirdness, make sure the platform's scale is (1,1,1).
///
/// Also usable for Cutthroat Course's Crusher (2 waypoints, fast) or drifting hazards.
/// </summary>
[RequireComponent(typeof(Rigidbody2D))]
public class MovingPlatform : MonoBehaviour
{
public enum Mode { Loop, PingPong }
public Transform[] waypoints;
public float speed = 2f;
public Mode mode = Mode.PingPong;
[Tooltip("Pause at each waypoint.")]
public float waitAtWaypoint = 0.3f;
[Tooltip("Tag of objects that should ride the platform.")]
public string riderTag = "Player";
private Rigidbody2D rb;
private int index;
private int dir = 1;
private float waitTimer;
void Awake()
{
rb = GetComponent<Rigidbody2D>();
rb.bodyType = RigidbodyType2D.Kinematic;
if (waypoints != null && waypoints.Length > 0) transform.position = waypoints[0].position;
}
void FixedUpdate()
{
if (waypoints == null || waypoints.Length < 2) return;
if (waitTimer > 0f) { waitTimer -= Time.fixedDeltaTime; return; }
Vector2 target = waypoints[index].position;
Vector2 next = Vector2.MoveTowards(rb.position, target, speed * Time.fixedDeltaTime);
rb.MovePosition(next);
if (Vector2.Distance(next, target) < 0.01f)
{
waitTimer = waitAtWaypoint;
Advance();
}
}
void Advance()
{
if (mode == Mode.Loop)
{
index = (index + 1) % waypoints.Length;
}
else
{
if (index + dir >= waypoints.Length || index + dir < 0) dir = -dir;
index += dir;
}
}
// Carry the rider: parent them while they stand on us
void OnCollisionEnter2D(Collision2D col)
{
if (!col.collider.CompareTag(riderTag)) return;
// Only if they're on top (contact normal points down onto us)
foreach (var contact in col.contacts)
if (contact.normal.y < -0.5f) { col.transform.SetParent(transform); break; }
}
void OnCollisionExit2D(Collision2D col)
{
if (col.collider.CompareTag(riderTag) && col.transform.parent == transform)
col.transform.SetParent(null);
}
void OnDrawGizmos()
{
if (waypoints == null) return;
Gizmos.color = Color.cyan;
for (int i = 0; i < waypoints.Length; i++)
{
if (waypoints[i] == null) continue;
Gizmos.DrawSphere(waypoints[i].position, 0.1f);
if (i + 1 < waypoints.Length && waypoints[i + 1] != null)
Gizmos.DrawLine(waypoints[i].position, waypoints[i + 1].position);
}
}
}