EerieVillage/Assets/Scripts/Mechanics/PlatformDropThrough.cs

76 lines
2.8 KiB
C#

using UnityEngine;
namespace Platformer.Mechanics
{
/// <summary>
/// BT5-Dev #27 — PD 제안 Layer + Raycast 동적 충돌.
/// Layer 8(JumpThrough) 발판은 기본 통과(IgnoreLayerCollision). Player 하강 + 발 Raycast 시점만 IgnoreCollision(false)로 충돌 활성 → 착지.
/// 점프(상승) 시 IgnoreCollision(true) 복구 → 다시 통과.
/// PlayerController.Awake에서 자동 부착.
/// </summary>
[RequireComponent(typeof(Collider2D))]
public class PlatformDropThrough : MonoBehaviour
{
const int JUMP_THROUGH_LAYER = 8;
[Tooltip("발 raycast 거리. 0.05~0.15 권장.")]
public float footRayDistance = 0.1f;
Collider2D _self;
KinematicObject _ko;
Collider2D _activePlatform;
int _jumpThroughMask;
void Awake()
{
_self = GetComponent<Collider2D>();
_ko = GetComponent<KinematicObject>();
_jumpThroughMask = 1 << JUMP_THROUGH_LAYER;
}
void Update()
{
if (_self == null || _ko == null) return;
// Player 발 위치 (collider 하단 중심)
Vector2 footPos = new Vector2(_self.bounds.center.x, _self.bounds.min.y + 0.02f);
// Layer 8 발판 raycast (footRayDistance 영역만 검사)
RaycastHit2D hit = Physics2D.Raycast(footPos, Vector2.down, footRayDistance, _jumpThroughMask);
bool falling = _ko.velocity.y <= 0.01f; // 하강 또는 정지
bool rising = _ko.velocity.y > 0.5f; // 점프 상승
if (rising)
{
// 점프 → 활성 발판 통과 복구
if (_activePlatform != null)
{
Physics2D.IgnoreCollision(_self, _activePlatform, true);
_activePlatform = null;
}
}
else if (falling && hit.collider != null && hit.collider != _activePlatform)
{
// 하강 + 발판 raycast hit → 충돌 활성 (착지)
Physics2D.IgnoreCollision(_self, hit.collider, false);
_activePlatform = hit.collider;
}
else if (falling && hit.collider == null && _activePlatform != null)
{
// 발판 떠남 (낙하) → 활성 해제
Physics2D.IgnoreCollision(_self, _activePlatform, true);
_activePlatform = null;
}
}
void OnDrawGizmosSelected()
{
if (_self == null) return;
Vector2 footPos = new Vector2(_self.bounds.center.x, _self.bounds.min.y + 0.02f);
Gizmos.color = Color.cyan;
Gizmos.DrawLine(footPos, footPos + Vector2.down * footRayDistance);
}
}
}