258 lines
20 KiB
C#
258 lines
20 KiB
C#
|
|
using UnityEngine;
|
|||
|
|
|
|||
|
|
// ============================================================
|
|||
|
|
// NorcielBoss.PatternSelection.cs — 패턴 선택 AI 로직 (partial class)
|
|||
|
|
//
|
|||
|
|
// [역할]
|
|||
|
|
// 거리/상황 기반 가중치 패턴 선택 시스템
|
|||
|
|
// - closeFactor, farFactor, midFactor 계산
|
|||
|
|
// - 플레이어 행동 감지 기반 가중치 보정
|
|||
|
|
// - 카운터 시스템 히스토리 감쇠 적용
|
|||
|
|
// - 가중치 룰렛으로 최종 패턴 결정
|
|||
|
|
// ============================================================
|
|||
|
|
|
|||
|
|
public partial class NorcielBoss : MonsterClass
|
|||
|
|
{
|
|||
|
|
private void SelectAndFire(float dist) // 함수를 선언할거에요 -> 가중치 기반 적응형 패턴을 선택하고 시작하는
|
|||
|
|
{
|
|||
|
|
// ══════════════════════════════════════════════════════
|
|||
|
|
// 가중치(Weight) 기반 패턴 선택 시스템
|
|||
|
|
//
|
|||
|
|
// 모든 패턴에 기본 가중치를 부여하고, 상황에 따라 가중치를 조정해요.
|
|||
|
|
// - 거리 조건에 안 맞는 패턴은 가중치 0 (선택 불가)
|
|||
|
|
// - 직전에 쓴 패턴은 가중치 대폭 감소 (연속 방지)
|
|||
|
|
// - 플레이어 행동에 따라 특정 패턴 가중치 증가 (적응형)
|
|||
|
|
// - 최종 가중치 기반 확률 룰렛으로 패턴 결정
|
|||
|
|
// ══════════════════════════════════════════════════════
|
|||
|
|
|
|||
|
|
// ── 쇠공 상태 확인 ───────────────────────────────
|
|||
|
|
bool ballIsHeld = ironBall != null && ironBall.State == BossIronBall.BallState.Held; // 확인할거에요 -> 쇠공 들고 있는지를
|
|||
|
|
|
|||
|
|
// ── 각 패턴별 기본 가중치 설정 ──────────────────
|
|||
|
|
float wThrow = 0f; // 초기화할거에요 -> Throw 가중치를
|
|||
|
|
float wSmash = 0f; // 초기화할거에요 -> Smash 가중치를
|
|||
|
|
float wSweep = 0f; // 초기화할거에요 -> Sweep 가중치를
|
|||
|
|
float wDash = 0f; // 초기화할거에요 -> Dash 가중치를
|
|||
|
|
float wDashSmash = 0f; // 초기화할거에요 -> DashSmash 가중치를
|
|||
|
|
|
|||
|
|
bool isKiting = _kitingTimer >= kitingDetectTime; // 판단할거에요 -> 카이팅 여부를 (kitingDetectTime초 이상 거리 유지 + 피격)
|
|||
|
|
|
|||
|
|
// ══════════════════════════════════════════════════════
|
|||
|
|
// [개선 v2] 거리 기반 부드러운 가중치 시스템
|
|||
|
|
//
|
|||
|
|
// 핵심 원리:
|
|||
|
|
// - closeFactor, farFactor, midFactor 세 가지 비율로 패턴 가중치를 보간
|
|||
|
|
// - "AI 판단 거리"는 meleeRange 기준 (smashRadius는 데미지 판정 범위이지 AI 판단 기준이 아님)
|
|||
|
|
// - 어느 거리에서든 모든 패턴이 확률적으로 섞이되, 거리에 따라 비중이 달라짐
|
|||
|
|
//
|
|||
|
|
// [v2 수정] smashRadius가 아무리 커도 패턴 선택에 영향 안 줌
|
|||
|
|
// → effectiveMeleeMax를 meleeRange + 슬라이드 접근 거리로 계산
|
|||
|
|
// → smashRadius는 "맞는 범위"일 뿐, "패턴을 고르는 거리"가 아님
|
|||
|
|
// ══════════════════════════════════════════════════════
|
|||
|
|
|
|||
|
|
// ══════════════════════════════════════════════════════════
|
|||
|
|
// [v3 수정] 실제 타격 범위 기반 가중치 시스템
|
|||
|
|
//
|
|||
|
|
// 핵심 변경: effectiveMeleeMax를 "실제 Smash가 닿는 거리"로 수정
|
|||
|
|
// 기존 문제: slideApproachDist(3m) 때문에 8m까지 Smash 가중치가 남아있었음
|
|||
|
|
// → 6~8m에서 Smash를 골라놓고 실제로는 안 닿는 "데드존" 발생
|
|||
|
|
// 수정: Smash 실제 타격 범위(smashForwardOffset + smashRadius) + 여유 1m로 제한
|
|||
|
|
// ══════════════════════════════════════════════════════════
|
|||
|
|
|
|||
|
|
// Smash가 실제로 닿는 최대 거리 (판정 중심 오프셋 + 판정 반경 + 약간의 이동 여유)
|
|||
|
|
float actualSmashRange = smashForwardOffset + smashRadius + 1f; // 계산할거에요 -> Smash 실제 타격 최대 거리를 (1.5+3+1=5.5m)
|
|||
|
|
|
|||
|
|
// AI가 "근접"이라고 판단하는 최대 거리
|
|||
|
|
// ⚠️ 기존 slideApproachDist(3m) 제거 → Smash가 안 닿는 거리에서 선택되는 버그 방지
|
|||
|
|
float effectiveMeleeMax = actualSmashRange; // 설정할거에요 -> AI 근접 판단 최대 거리를 (실제 타격 범위 기준)
|
|||
|
|
|
|||
|
|
// closeFactor: 0(먼 거리) ~ 1(근접) — actualSmashRange 이내에서만 높음
|
|||
|
|
float closeFactor = Mathf.Clamp01(1f - (dist / effectiveMeleeMax)); // 계산할거에요 -> 근접 비율을 (가까울수록 1, 5.5m 밖이면 0)
|
|||
|
|
|
|||
|
|
// farFactor: 0(근접) ~ 1(먼 거리) — meleeRange부터 throwRange까지 선형 증가
|
|||
|
|
float farFactor = Mathf.Clamp01((dist - meleeRange) / Mathf.Max(throwRange - meleeRange, 1f)); // 계산할거에요 -> 원거리 비율을 (멀수록 1)
|
|||
|
|
|
|||
|
|
// midFactor: 중간 거리(meleeRange~throwRange 사이)에서 가장 높음 — 삼각형 분포
|
|||
|
|
float midPoint = (meleeRange + throwRange) * 0.5f; // 계산할거에요 -> 중간 거리를 (예: 6.75m)
|
|||
|
|
float midHalfWidth = (throwRange - meleeRange) * 0.5f; // 계산할거에요 -> 삼각형 분포 반폭을
|
|||
|
|
float midFactor = 1f - Mathf.Abs(dist - midPoint) / Mathf.Max(midHalfWidth, 1f); // 계산할거에요 -> 중간 거리 비율을 (중간일수록 1)
|
|||
|
|
midFactor = Mathf.Clamp01(midFactor); // 보장할거에요 -> 0~1 범위를
|
|||
|
|
|
|||
|
|
// ── Smash: 실제 타격 범위 안에서만 가중치 부여 ──────────
|
|||
|
|
// [v3] actualSmashRange(5.5m) 밖이면 완전 차단 → 빗나갈 Smash 원천 차단
|
|||
|
|
wSmash = 25f * closeFactor; // 계산할거에요 -> 거리 보간된 Smash 가중치를 (가까우면 25, 멀면 0에 수렴)
|
|||
|
|
if (dist > actualSmashRange) wSmash = 0f; // 차단할거에요 -> Smash가 실제로 닿을 수 없으면 (5.5m 초과)
|
|||
|
|
|
|||
|
|
// ── Sweep: 근접 전용, Smash보다 좁은 범위 ─────────
|
|||
|
|
wSweep = sweepSelectChance * 50f * closeFactor; // 계산할거에요 -> 거리 보간된 Sweep 가중치를
|
|||
|
|
if (dist > sweepRadius + 2f) wSweep = 0f; // 차단할거에요 -> 스윕 범위 밖이면
|
|||
|
|
|
|||
|
|
// ── Throw: 중~원거리에서 주력, 근접에서도 서프라이즈 ──
|
|||
|
|
if (ballIsHeld) // 조건이 맞으면 실행할거에요 -> 쇠공 들고 있으면
|
|||
|
|
{
|
|||
|
|
float throwBase = isKiting ? 30f : 40f; // 설정할거에요 -> Throw 기본치를 (카이팅 시 약간 줄임)
|
|||
|
|
// 가까울 때도 최소 20% 확보 → 근접에서 가끔 던지기 = 의외성
|
|||
|
|
wThrow = throwBase * (farFactor * 0.4f + midFactor * 0.4f + 0.2f); // 계산할거에요 -> 거리 보간된 Throw 가중치를
|
|||
|
|
}
|
|||
|
|
else // 쇠공 없을 때
|
|||
|
|
{
|
|||
|
|
wThrow = 0f; // 설정할거에요 -> 쇠공 없으면 Throw 불가
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// ── Dash: 중~원거리 갭클로저, 근접에서는 낮음 ──
|
|||
|
|
// [v5 수정] 기존 문제: 바닥 40% + 쇠공 없음 ×2.0 → 돌진 편향
|
|||
|
|
// 수정: 바닥 20%로 낮추고, 쇠공 없음 보정도 완화
|
|||
|
|
float dashBase = isKiting ? 15f : 10f; // 설정할거에요 -> Dash 기본치를 (v5: 18/12 → 15/10 하향)
|
|||
|
|
wDash = dashBase * (farFactor * 0.8f + 0.2f); // 계산할거에요 -> 거리 보간된 Dash 가중치를 (v5: 바닥 20%, 멀면 높고 가까우면 매우 낮음)
|
|||
|
|
if (!ballIsHeld && dist > meleeRange) wDash *= 1.5f; // 올릴거에요 -> 쇠공 없이 원거리면 갭클로저 보정 (v5: 2.0 → 1.5 완화)
|
|||
|
|
|
|||
|
|
// ── DashSmash: 중~원거리 갭클로저 콤보, 근접에선 가중치 낮음 ──
|
|||
|
|
// [v5 수정] 기존 문제: 바닥 배율 0.5(50%) → 근접에서도 항상 높은 가중치 → DashSmash 편향
|
|||
|
|
// 수정: 바닥 배율 0.15(15%)로 낮추고, 기본값도 Phase별 하향 → 근접 패턴과 균형
|
|||
|
|
float dsmashPhaseBase = _isPhase3 ? 15f : _isPhase2 ? 12f : 6f; // 설정할거에요 -> Phase별 DashSmash 기본치를 (v5: 25/18/10 → 15/12/6 하향)
|
|||
|
|
wDashSmash = dsmashPhaseBase * (farFactor * 0.85f + 0.15f); // 계산할거에요 -> 거리 보간된 DashSmash 가중치를 (v5: 바닥 15%로 하향, 먼 거리에서만 높음)
|
|||
|
|
if (isKiting) wDashSmash *= 1.5f; // 올릴거에요 -> 카이팅 시 콤보 대시 보정 (v5: 2.0 → 1.5 완화)
|
|||
|
|
if (!ballIsHeld && dist > throwRange) wDashSmash *= 1.3f; // 올릴거에요 -> 쇠공 없이 멀면 돌진 보정 (v5: 1.8 → 1.3 완화)
|
|||
|
|
|
|||
|
|
// ── 카운터 시스템 패턴 보정 ─────────────────────
|
|||
|
|
if (counterSystem != null) // 조건이 맞으면 실행할거에요 -> 카운터 시스템 있으면
|
|||
|
|
{
|
|||
|
|
string counterResult = counterSystem.SelectBossPattern(); // 가져올거에요 -> 카운터 결과를
|
|||
|
|
if (!string.IsNullOrEmpty(counterResult) && counterResult != "default" && counterResult != "Normal") // 조건이 맞으면 실행할거에요 -> 특정 패턴 지정이면
|
|||
|
|
{
|
|||
|
|
// 카운터가 특정 패턴을 권장하면 해당 가중치를 1.5배 보정 (강제가 아닌 유도)
|
|||
|
|
if (counterResult.Contains("Smash")) wSmash *= 1.5f; // 올릴거에요 -> Smash 보정을
|
|||
|
|
else if (counterResult.Contains("Throw")) wThrow *= 1.5f; // 올릴거에요 -> Throw 보정을
|
|||
|
|
else if (counterResult.Contains("Dash")) wDash *= 1.5f; // 올릴거에요 -> Dash 보정을
|
|||
|
|
else if (counterResult.Contains("Sweep")) wSweep *= 1.5f; // 올릴거에요 -> Sweep 보정을
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// ── [적응형 AI] 플레이어 행동에 따른 가중치 보정 ──
|
|||
|
|
//
|
|||
|
|
// 1) 플레이어가 정지해 있으면 → 갭클로저(Dash/DashSmash) 가중치 상승
|
|||
|
|
// "서서 힐 쓰거나 가만히 있으면 벌 준다"
|
|||
|
|
if (_playerStillTimer >= stillPunishTime) // 조건이 맞으면 실행할거에요 -> 오래 멈춰있으면
|
|||
|
|
{
|
|||
|
|
wDash *= 2.0f; // 올릴거에요 -> 대시 가중치를 (가만히 있으면 돌진)
|
|||
|
|
wDashSmash *= 2.5f; // 올릴거에요 -> 콤보 대시를 (강력한 징벌)
|
|||
|
|
wThrow *= 0.3f; // 낮출거에요 -> 던지기를 (멀리서 던질 이유 없음)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 2) 플레이어가 접근 중이면 → Smash/Sweep 가중치 상승
|
|||
|
|
// "다가오는 플레이어를 근접기로 맞이한다"
|
|||
|
|
if (_playerApproachTimer >= approachReactTime) // 조건이 맞으면 실행할거에요 -> 접근 감지되면
|
|||
|
|
{
|
|||
|
|
wSmash *= 1.8f; // 올릴거에요 -> 스매시를 (다가오는 걸 내려찍기)
|
|||
|
|
wSweep *= 1.5f; // 올릴거에요 -> 스윕을 (범위 공격으로 견제)
|
|||
|
|
wDash *= 0.3f; // 낮출거에요 -> 대시를 (다가오는데 돌진할 이유 없음)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 3) 플레이어가 도주 중이면 → 갭클로저 가중치 상승 (과하지 않게)
|
|||
|
|
// "도망가면 쫓아가서 잡는다"
|
|||
|
|
// [v5 수정] 누적 곱셈 폭발 방지 → 배율 완화
|
|||
|
|
if (_playerFleeTimer >= 1.0f) // 조건이 맞으면 실행할거에요 -> 도주 감지되면
|
|||
|
|
{
|
|||
|
|
wDash *= 1.8f; // 올릴거에요 -> 대시를 (추격, v5: 2.5 → 1.8)
|
|||
|
|
wDashSmash *= 2.0f; // 올릴거에요 -> 콤보 대시를 (v5: 3.0 → 2.0)
|
|||
|
|
wSmash *= 0.3f; // 낮출거에요 -> 근접기를 (닿지도 못하니)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 4) 카이팅 감지 (활 쏘면서 거리 유지) → 갭클로저 우선 (과하지 않게)
|
|||
|
|
// "원거리 공격하면서 도망다니면 쫓아간다"
|
|||
|
|
// [v5 수정] 기존 문제: ×3.0, ×4.0 곱셈 → 도주+카이팅 중복 시 DashSmash가 전체의 90%
|
|||
|
|
// 수정: 배율 완화 + Throw도 약간 남겨서 패턴 다양성 확보
|
|||
|
|
if (isKiting) // 조건이 맞으면 실행할거에요 -> 카이팅 감지되면
|
|||
|
|
{
|
|||
|
|
wDash *= 2.0f; // 올릴거에요 -> 대시를 (빠르게 붙기, v5: 3.0 → 2.0)
|
|||
|
|
wDashSmash *= 2.5f; // 올릴거에요 -> 콤보 대시를 (v5: 4.0 → 2.5)
|
|||
|
|
wThrow *= 0.3f; // 낮출거에요 -> 던지기를 (v5: 0.2 → 0.3, 약간 남김)
|
|||
|
|
wSmash *= 0.1f; // 낮출거에요 -> 근접기를 (닿을 수가 없으니)
|
|||
|
|
wSweep *= 0.1f; // 낮출거에요 -> 근접기를 (닿을 수가 없으니)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// ── [v3 추가] 5) 중거리 캠핑 감지 → 갭클로저 + 던지기 강화 ──
|
|||
|
|
// "멀리 서서 때리고만 있으면 무조건 쫓아가거나 던진다"
|
|||
|
|
// 조건: 플레이어가 정지 + Smash 타격 범위 밖 + 사거리 안
|
|||
|
|
// 기존 문제: 보스가 중거리에서 Smash만 반복 → 전부 빗나감
|
|||
|
|
// 해결: Smash/Sweep 가중치를 강제로 0으로, 갭클로저를 크게 올림
|
|||
|
|
bool isMidRangeCamping = _playerStillTimer >= stillPunishTime // 조건 1: 플레이어가 오래 정지 중
|
|||
|
|
&& dist > actualSmashRange // 조건 2: Smash가 닿지 않는 거리
|
|||
|
|
&& dist <= throwRange; // 조건 3: 사거리 안 (throwRange 이내)
|
|||
|
|
if (isMidRangeCamping) // 조건이 맞으면 실행할거에요 -> 중거리 캠핑 감지되면
|
|||
|
|
{
|
|||
|
|
wSmash = 0f; // 강제할거에요 -> Smash를 0으로 (어차피 안 닿으니)
|
|||
|
|
wSweep = 0f; // 강제할거에요 -> Sweep도 0으로 (근접기 전부 차단)
|
|||
|
|
wDash *= 2.5f; // 올릴거에요 -> 대시를 (거리를 좁혀서 근접)
|
|||
|
|
wDashSmash *= 3.0f; // 올릴거에요 -> 콤보 대시를 (돌진 후 내려찍기)
|
|||
|
|
if (ballIsHeld) wThrow *= 2.5f; // 올릴거에요 -> 던지기를 (가만히 있으면 던져서 맞춤)
|
|||
|
|
Debug.Log($"[Boss] 중거리 캠핑 감지! dist={dist:F1}m > Smash범위{actualSmashRange:F1}m → 갭클로저/던지기 강화"); // 로그를 찍을거에요
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// ── [연속 방지] 직전 패턴 가중치 감소 ─────────────
|
|||
|
|
// 같은 패턴이 2회 이상 연속되면 가중치를 대폭 줄여요.
|
|||
|
|
// 완전히 0으로 만들지는 않아요 (가끔 의도적 반복 = 읽기 어려움).
|
|||
|
|
if (_samePatternCount >= 1) // 조건이 맞으면 실행할거에요 -> 같은 패턴이 최소 1회 나왔으면
|
|||
|
|
{
|
|||
|
|
float penalty = _samePatternCount >= 2 ? 0.05f : 0.25f; // 계산할거에요 -> 감쇠 배율을 (2연속이면 95% 감소, 1연속이면 75% 감소)
|
|||
|
|
switch (_lastPattern) // 분기할거에요 -> 직전 패턴에 따라
|
|||
|
|
{
|
|||
|
|
case BossPattern.Throw: wThrow *= penalty; break; // 감소시킬거에요 -> Throw 가중치를
|
|||
|
|
case BossPattern.Smash: wSmash *= penalty; break; // 감소시킬거에요 -> Smash 가중치를
|
|||
|
|
case BossPattern.Sweep: wSweep *= penalty; break; // 감소시킬거에요 -> Sweep 가중치를
|
|||
|
|
case BossPattern.Dash: wDash *= penalty; break; // 감소시킬거에요 -> Dash 가중치를
|
|||
|
|
case BossPattern.DashSmash: wDashSmash *= penalty; break; // 감소시킬거에요 -> DashSmash 가중치를
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// ── [히스토리 기반] 최근 패턴 등장 빈도 감쇠 → counterSystem에 위임 ──
|
|||
|
|
if (counterSystem != null) // 조건이 맞으면 실행할거에요 -> 카운터 시스템 있으면
|
|||
|
|
{
|
|||
|
|
wThrow *= counterSystem.GetHistoryPenalty(0); // 적용할거에요 -> Throw(0) 히스토리 감쇠를
|
|||
|
|
wSmash *= counterSystem.GetHistoryPenalty(1); // 적용할거에요 -> Smash(1) 히스토리 감쇠를
|
|||
|
|
wSweep *= counterSystem.GetHistoryPenalty(2); // 적용할거에요 -> Sweep(2) 히스토리 감쇠를
|
|||
|
|
wDash *= counterSystem.GetHistoryPenalty(3); // 적용할거에요 -> Dash(3) 히스토리 감쇠를
|
|||
|
|
wDashSmash *= counterSystem.GetHistoryPenalty(4); // 적용할거에요 -> DashSmash(4) 히스토리 감쇠를
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// ── 가중치 룰렛 (Weighted Random) ────────────────
|
|||
|
|
float total = wThrow + wSmash + wSweep + wDash + wDashSmash; // 합산할거에요 -> 전체 가중치를
|
|||
|
|
if (total <= 0f) total = 1f; // 방어할거에요 -> 0 나누기 방지
|
|||
|
|
|
|||
|
|
float roll = Random.value * total; // 굴릴거에요 -> 0~total 사이 랜덤을
|
|||
|
|
BossPattern pattern; // 선언할거에요 -> 최종 선택 패턴을
|
|||
|
|
|
|||
|
|
if (roll < wThrow) // 판단할거에요 -> Throw 구간이면
|
|||
|
|
pattern = BossPattern.Throw;
|
|||
|
|
else if (roll < wThrow + wSmash) // 판단할거에요 -> Smash 구간이면
|
|||
|
|
pattern = BossPattern.Smash;
|
|||
|
|
else if (roll < wThrow + wSmash + wSweep) // 판단할거에요 -> Sweep 구간이면
|
|||
|
|
pattern = BossPattern.Sweep;
|
|||
|
|
else if (roll < wThrow + wSmash + wSweep + wDash) // 판단할거에요 -> Dash 구간이면
|
|||
|
|
pattern = BossPattern.Dash;
|
|||
|
|
else // 나머지 = DashSmash
|
|||
|
|
pattern = BossPattern.DashSmash;
|
|||
|
|
|
|||
|
|
// ── 연속 카운터 갱신 ────────────────────────────
|
|||
|
|
if (pattern == _lastPattern) // 조건이 맞으면 실행할거에요 -> 같은 패턴이 또 나왔으면
|
|||
|
|
_samePatternCount++; // 증가시킬거에요 -> 연속 카운터를
|
|||
|
|
else
|
|||
|
|
_samePatternCount = 0; // 초기화할거에요 -> 다른 패턴이니 리셋
|
|||
|
|
_lastPattern = pattern; // 기록할거에요 -> 이번 패턴을 (다음 비교용)
|
|||
|
|
|
|||
|
|
if (counterSystem != null) counterSystem.RecordPattern((int)pattern); // 기록할거에요 -> 선택된 패턴을 카운터 시스템 히스토리에
|
|||
|
|
|
|||
|
|
// [v6 추가] SelectAndFire에서 Dash/DashSmash 선택 시 전역 대시 쿨다운 설정
|
|||
|
|
// v5 문제: FSM 트리거(Chase/PreAttack)에서만 쿨다운 설정 → SelectAndFire에서 선택된 대시는 쿨다운 미적용
|
|||
|
|
// → 쿨타임 만료 후 SelectAndFire에서 Dash 선택 → 즉시 Chase에서 또 대시 발동 가능
|
|||
|
|
// v6 수정: SelectAndFire에서도 대시 선택 시 _dashCooldownTimer 설정 → 전역 쿨다운 일관성
|
|||
|
|
if (pattern == BossPattern.Dash || pattern == BossPattern.DashSmash) // 조건이 맞으면 실행할거에요 -> 대시 계열 패턴이면
|
|||
|
|
_dashCooldownTimer = dashCooldownTime; // 설정할거에요 -> 대시 쿨다운을 (다음 대시까지 6초 대기)
|
|||
|
|
|
|||
|
|
Debug.Log($"[Boss] 패턴 선택: {pattern} dist={dist:F1}m Phase={(_isPhase3 ? "3" : _isPhase2 ? "2" : "1")} 콤보#{_comboCounter} " +
|
|||
|
|
$"가중치=[T:{wThrow:F0} S:{wSmash:F0} Sw:{wSweep:F0} D:{wDash:F0} DS:{wDashSmash:F0}] " +
|
|||
|
|
$"정지={_playerStillTimer:F1}s 접근={_playerApproachTimer:F1}s 도주={_playerFleeTimer:F1}s"); // 로그를 찍을거에요
|
|||
|
|
StartPattern(pattern); // 실행할거에요 -> 선택된 패턴을
|
|||
|
|
}
|
|||
|
|
}
|