BT5-Dev #96: transform+body 동시 push (가장자리 밀림 차단)
PD 보고 (2026-05-08): "몬스터가 벽 가장자리에 닿으면 밀려나는 현상·방향 튼 상태로 뒤로 밀려남" 진단: - BT95 velocity.x = -moveDir * maxSpeed = 1 frame만 적용 (KinematicObject FixedUpdate 영역에서 velocity.x = targetVelocity.x로 덮어씀) - transform.position 영역 ↔ body.position 영역 비동기 = KinematicObject 영역 부정합 → 미세 영역 잔존 정정 (BT96): 1. _body Rigidbody2D 영역 캐싱 (Awake) 2. TriggerReverse(moveDir, pushDistance) 함수 신규: - phase+2 + SetNextPatrolTarget - transform.position + body.position 동시 push (반대 방향 0.2~0.3m) - velocity.x = -moveDir * maxSpeed + move.x = -moveDir - cooldown 1.0초 활성 3. 절벽 검출 시 TriggerReverse(moveDir, 0.3f) 4. 벽 정지 (stuckTimer) 시 TriggerReverse(moveDir, 0.2f) 효과: - transform + body 동시 set = KinematicObject body 영역 정합 = 비동기 영역 부정합 차단 - 즉시 반대 방향 0.2~0.3m push = 가장자리 영역에서 즉시 멀어짐 - velocity.x 큰 속도 = 다음 frame 안정 이동 - 1초 cooldown = 충분 영역 멀어진 후 재검출
This commit is contained in:
parent
32012aa450
commit
53e6a5935f
|
|
@ -50,6 +50,7 @@ namespace Platformer.Mechanics
|
|||
internal Collider2D _collider;
|
||||
internal AudioSource _audio;
|
||||
SpriteRenderer spriteRenderer;
|
||||
Rigidbody2D _body; // BT96: KinematicObject body 영역 직접 set 위해 캐싱
|
||||
|
||||
public Bounds Bounds => _collider.bounds;
|
||||
|
||||
|
|
@ -68,6 +69,7 @@ namespace Platformer.Mechanics
|
|||
_collider = GetComponent<Collider2D>();
|
||||
_audio = GetComponent<AudioSource>();
|
||||
spriteRenderer = GetComponent<SpriteRenderer>();
|
||||
_body = GetComponent<Rigidbody2D>();
|
||||
|
||||
// BT5-Dev #21 — Awake 시점 fallback 추가 (Player tag 영역 미설정 영역 대비)
|
||||
var playerObj = GameObject.FindGameObjectWithTag("Player");
|
||||
|
|
@ -100,7 +102,29 @@ namespace Platformer.Mechanics
|
|||
SetNextPatrolTarget();
|
||||
}
|
||||
|
||||
// BT94 — 시작 위치에서 좌·우 walk 영역 절벽 검출까지 거리 측정 (안전 margin 1.5m 차감)
|
||||
// BT96 — 절벽·벽 검출 시 즉시 반대 방향 이동 (transform + body 동시 push·KinematicObject 정합)
|
||||
void TriggerReverse(float moveDir, float pushDistance)
|
||||
{
|
||||
_patrolPhase = (_patrolPhase + 2) % 4;
|
||||
SetNextPatrolTarget();
|
||||
|
||||
// transform + body 동시 push (KinematicObject body.position 영역 동기화)
|
||||
Vector3 newPos = transform.position + new Vector3(-moveDir * pushDistance, 0f, 0f);
|
||||
transform.position = newPos;
|
||||
if (_body != null) _body.position = newPos;
|
||||
|
||||
// velocity.x 즉시 반대 방향 + move.x 반대 (다음 frame 안정 이동)
|
||||
if (control != null)
|
||||
{
|
||||
control.velocity = new Vector2(-moveDir * control.maxSpeed, control.velocity.y);
|
||||
control.move.x = -moveDir;
|
||||
}
|
||||
|
||||
_stuckTimer = 0f;
|
||||
_phaseCooldown = PHASE_COOLDOWN;
|
||||
_lastX = transform.position.x;
|
||||
}
|
||||
|
||||
float MeasureSafeWalkDistance(float dir)
|
||||
{
|
||||
float groundY = transform.position.y - 0.34f; // 발 영역 위 0.05m (Capsule offset 영역 기반 추정)
|
||||
|
|
@ -171,7 +195,7 @@ namespace Platformer.Mechanics
|
|||
// BT94 — 절벽·벽 검출은 phase cooldown 영역 끝난 후 활성 (좌우 반복 차단)
|
||||
if (_phaseCooldown <= 0f)
|
||||
{
|
||||
// BT95 — 절벽 검출: velocity.x 즉시 반대 방향 큰 속도 (가장자리에서 빠르게 멀어짐)
|
||||
// BT96 — 절벽·벽 검출: transform + body 동시 push (가장자리에서 안전 영역으로 즉시 이동)
|
||||
if (_collider != null)
|
||||
{
|
||||
Vector2 footAhead = new Vector2(
|
||||
|
|
@ -181,36 +205,17 @@ namespace Platformer.Mechanics
|
|||
RaycastHit2D groundHit = Physics2D.Raycast(footAhead, Vector2.down, cliffCheckDepth, groundLayerMask);
|
||||
if (groundHit.collider == null)
|
||||
{
|
||||
_patrolPhase = (_patrolPhase + 2) % 4;
|
||||
SetNextPatrolTarget();
|
||||
if (control != null)
|
||||
{
|
||||
control.velocity = new Vector2(-moveDir * control.maxSpeed, control.velocity.y);
|
||||
control.move.x = -moveDir;
|
||||
}
|
||||
_stuckTimer = 0f;
|
||||
_phaseCooldown = PHASE_COOLDOWN;
|
||||
_lastX = transform.position.x;
|
||||
TriggerReverse(moveDir, 0.3f);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// BT95 — 벽 정지 (stuckTimer): velocity.x 즉시 반대 방향 큰 속도
|
||||
if (Mathf.Abs(transform.position.x - _lastX) < stuckMoveThreshold)
|
||||
{
|
||||
_stuckTimer += Time.deltaTime;
|
||||
if (_stuckTimer > stuckThresholdTime)
|
||||
{
|
||||
_patrolPhase = (_patrolPhase + 2) % 4;
|
||||
SetNextPatrolTarget();
|
||||
if (control != null)
|
||||
{
|
||||
control.velocity = new Vector2(-moveDir * control.maxSpeed, control.velocity.y);
|
||||
control.move.x = -moveDir;
|
||||
}
|
||||
_stuckTimer = 0f;
|
||||
_phaseCooldown = PHASE_COOLDOWN;
|
||||
_lastX = transform.position.x;
|
||||
TriggerReverse(moveDir, 0.2f);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue