using UnityEngine; namespace Minigames.Airplane.Interactive { /// /// Gravity well that pulls airplanes toward its center. /// Creates challenging "danger zones" that players must avoid or escape from. /// [RequireComponent(typeof(Collider2D))] public class AirplaneGravityWell : MonoBehaviour { [Header("Gravity Configuration")] [SerializeField] private float pullStrength = 5f; [SerializeField] private bool useInverseSquare = false; [SerializeField] private float minPullDistance = 0.5f; [Header("Optional Modifiers")] [SerializeField] private float maxPullForce = 15f; [SerializeField] private AnimationCurve pullFalloff = AnimationCurve.Linear(0, 1, 1, 0); [Header("Visual Feedback (Optional)")] [SerializeField] private ParticleSystem gravityParticles; [SerializeField] private SpriteRenderer centerSprite; [SerializeField] private float rotationSpeed = 90f; [Header("Debug")] [SerializeField] private bool showDebugLogs; [SerializeField] private bool drawDebugLines = true; private Vector2 centerPosition; private void Awake() { // Ensure collider is trigger var collider = GetComponent(); if (collider != null) { collider.isTrigger = true; } centerPosition = transform.position; } private void Update() { // Rotate center visual if present if (centerSprite != null) { centerSprite.transform.Rotate(0, 0, rotationSpeed * Time.deltaTime); } } private void OnTriggerStay2D(Collider2D other) { // Check if it's an airplane var airplane = other.GetComponent(); if (airplane == null || !airplane.IsFlying) return; var rb = other.GetComponent(); if (rb == null) return; // Calculate direction and distance to center Vector2 airplanePos = rb.position; Vector2 toCenter = centerPosition - airplanePos; float distance = toCenter.magnitude; // Prevent division by zero if (distance < minPullDistance) { distance = minPullDistance; } // Calculate pull force float forceMagnitude; if (useInverseSquare) { // Realistic gravity-like force (inverse square law) forceMagnitude = pullStrength / (distance * distance); } else { // Linear falloff based on distance var collider = GetComponent(); float maxDistance = collider != null ? collider.bounds.extents.magnitude : 5f; float normalizedDistance = Mathf.Clamp01(distance / maxDistance); float falloff = pullFalloff.Evaluate(1f - normalizedDistance); forceMagnitude = pullStrength * falloff; } // Clamp force forceMagnitude = Mathf.Min(forceMagnitude, maxPullForce); // Apply force toward center Vector2 pullForce = toCenter.normalized * forceMagnitude; rb.AddForce(pullForce, ForceMode2D.Force); if (showDebugLogs && Time.frameCount % 30 == 0) // Log every 30 frames { Debug.Log($"[AirplaneGravityWell] Pulling {other.name}: force={forceMagnitude:F2}, distance={distance:F2}"); } } private void OnDrawGizmos() { // Visualize gravity well in editor Gizmos.color = new Color(1f, 0f, 1f, 0.3f); // Magenta transparent var collider = GetComponent(); if (collider != null) { // Draw zone bounds Gizmos.DrawWireSphere(collider.bounds.center, collider.bounds.extents.magnitude); // Draw center point Gizmos.color = Color.magenta; Gizmos.DrawWireSphere(transform.position, 0.5f); // Draw pull strength indicator Gizmos.DrawRay(transform.position, Vector3.up * pullStrength * 0.2f); } } private void OnDrawGizmosSelected() { if (!drawDebugLines) return; // Draw pull force visualization at multiple points var collider = GetComponent(); if (collider == null) return; float radius = collider.bounds.extents.magnitude; int samples = 8; for (int i = 0; i < samples; i++) { float angle = (i / (float)samples) * 360f * Mathf.Deg2Rad; Vector2 offset = new Vector2(Mathf.Cos(angle), Mathf.Sin(angle)) * radius; Vector3 samplePoint = transform.position + (Vector3)offset; Vector3 direction = (transform.position - samplePoint).normalized; Gizmos.color = Color.yellow; Gizmos.DrawLine(samplePoint, samplePoint + direction * 2f); } } } }