2026-04-22 15:58:44 +00:00
|
|
|
|
using System.Collections;
|
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
|
using Platformer.Gameplay;
|
|
|
|
|
|
using UnityEngine;
|
|
|
|
|
|
using static Platformer.Core.Simulation;
|
|
|
|
|
|
|
|
|
|
|
|
namespace Platformer.Mechanics
|
|
|
|
|
|
{
|
|
|
|
|
|
/// <summary>
|
2026-05-07 06:29:34 +00:00
|
|
|
|
/// 낙사 영역 — PD 지시 2026-05-07: 즉사 폐기 → HP 감소 + 위치 복귀 + 1초 무적.
|
|
|
|
|
|
/// 추가 (#3): 캐릭터가 카메라 영역 밖으로 완전히 사라진 후 위치 복귀 (낙하 자연스러움).
|
2026-04-22 15:58:44 +00:00
|
|
|
|
/// </summary>
|
|
|
|
|
|
public class DeathZone : MonoBehaviour
|
|
|
|
|
|
{
|
2026-05-07 06:29:34 +00:00
|
|
|
|
public int fallDamage = 1;
|
|
|
|
|
|
public float fallInvulnerability = 1f;
|
|
|
|
|
|
/// <summary>카메라 영역 외 대기 timeout(초). 안전망 — 카메라 영역 영역 외로 안 사라지는 경우 강제 진행.</summary>
|
|
|
|
|
|
public float fallTimeout = 3f;
|
|
|
|
|
|
|
|
|
|
|
|
readonly HashSet<PlayerController> falling = new HashSet<PlayerController>();
|
|
|
|
|
|
|
2026-04-22 15:58:44 +00:00
|
|
|
|
void OnTriggerEnter2D(Collider2D collider)
|
|
|
|
|
|
{
|
|
|
|
|
|
var p = collider.gameObject.GetComponent<PlayerController>();
|
2026-05-07 06:29:34 +00:00
|
|
|
|
if (p == null || p.health == null) return;
|
|
|
|
|
|
if (falling.Contains(p)) return; // 이미 처리 중이면 중복 방지
|
|
|
|
|
|
|
|
|
|
|
|
falling.Add(p);
|
|
|
|
|
|
StartCoroutine(FallSequence(p));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
IEnumerator FallSequence(PlayerController p)
|
|
|
|
|
|
{
|
|
|
|
|
|
// 입력 차단 (낙하 중에는 조작 불가)
|
|
|
|
|
|
p.controlEnabled = false;
|
|
|
|
|
|
|
|
|
|
|
|
// 카메라 영역 외 (viewport y < 0)까지 대기 — PD 지시 2026-05-07 #3
|
|
|
|
|
|
Camera cam = Camera.main;
|
|
|
|
|
|
float deadline = Time.time + fallTimeout;
|
|
|
|
|
|
while (Time.time < deadline)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (cam != null)
|
|
|
|
|
|
{
|
|
|
|
|
|
Vector3 viewport = cam.WorldToViewportPoint(p.transform.position);
|
|
|
|
|
|
if (viewport.y < -0.1f) break;
|
|
|
|
|
|
}
|
|
|
|
|
|
yield return null;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-05-07 06:50:17 +00:00
|
|
|
|
// 위치 복귀 + HP 감소 + 1초 무적 (PD 지시 2026-05-07 — 낙사 복귀 시 hit 모션 X → DecrementSilent)
|
2026-05-07 06:29:34 +00:00
|
|
|
|
p.transform.position = p.LastGroundedPosition;
|
|
|
|
|
|
p.velocity = Vector2.zero;
|
2026-05-07 06:50:17 +00:00
|
|
|
|
p.health.DecrementSilent(fallDamage);
|
2026-05-07 06:29:34 +00:00
|
|
|
|
|
|
|
|
|
|
if (p.health.IsAlive)
|
2026-04-22 15:58:44 +00:00
|
|
|
|
{
|
2026-05-07 06:29:34 +00:00
|
|
|
|
p.health.GrantInvulnerability(fallInvulnerability);
|
|
|
|
|
|
p.controlEnabled = true;
|
2026-04-22 15:58:44 +00:00
|
|
|
|
}
|
2026-05-07 06:29:34 +00:00
|
|
|
|
// IsAlive == false면 ResurrectPromptUI가 OnDeathEvent로 자동 처리 (controlEnabled false 유지)
|
|
|
|
|
|
|
|
|
|
|
|
falling.Remove(p);
|
2026-04-22 15:58:44 +00:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|