Degulleo3D/Assets/Scripts/Character/Enemy/PldDogController.cs
fiore 7ed35864cb [feat] 팔라딘 SFX 추가
- 폭탄 던지는 소리
- 칼 휘두르는 소리 재생 추가
2025-05-12 14:33:50 +09:00

224 lines
6.6 KiB
C#

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using Unity.VisualScripting;
using UnityEngine;
using UnityEngine.Serialization;
using Random = UnityEngine.Random;
public class PldDogController : EnemyController
{
// ----
// 팔라딘 독 고유 액션
private static readonly int WindUp = Animator.StringToHash("WindUp");
private static readonly int Slash = Animator.StringToHash("Slash");
private static readonly int BoomShot = Animator.StringToHash("BoomShot");
[Header("공격 패턴 관련")]
[SerializeField] private float patternInterval = 3f;
[SerializeField] private float meleeRange = 2f;
[SerializeField] private float bombTriggerDelay = 1.5f;
[Header("폭탄 패턴 설정")]
[SerializeField] private int bombCount = 1;
[SerializeField] private Vector3 bombScale = new Vector3(5f, 5f, 5f);
[Header("각종 데미지 이펙트 세트")]
[SerializeField] private GameObject chariotSlashWarning;
[SerializeField] private GameObject chariotSlash;
[SerializeField] private GameObject boomExplosion;
[Space(10)]
[SerializeField] private GameObject verticalWarning;
[SerializeField] private GameObject verticalSlash;
[Space(10)]
[SerializeField] private GameObject horizontalWarning;
[SerializeField] private GameObject horizontalSlash;
// SFX
[Space(10)]
[Header("SFX")]
[SerializeField] private AudioClip slashSound;
[SerializeField] private AudioClip boomSound;
private float _patternTimer = 0f;
private int _lastPatternIndex = -1;
private bool _isPatternRunning = false;
private bool _isFirstAttack = true;
private List<Action> _patternActions;
protected override void Awake()
{
base.Awake();
_patternActions = new List<Action>
{
ChariotSlashPattern,
VerticalSlashPattern,
HorizontalSlashPattern
};
}
public override void BattleSequence()
{
_patternTimer += Time.deltaTime;
if (_isPatternRunning) return;
float distanceToPlayer = Vector3.Distance(transform.position, TraceTargetTransform.position);
if (distanceToPlayer <= meleeRange) // 근접 범위
{
if (!Agent.isStopped) Agent.isStopped = true;
if (!_isPatternRunning && (_isFirstAttack || _patternTimer >= patternInterval))
{
ExecutePattern();
_isFirstAttack = false;
}
}
else
{
if (Agent.isStopped) Agent.isStopped = false;
Agent.SetDestination(TraceTargetTransform.position);
if (!_isPatternRunning && _patternTimer >= patternInterval)
{
Debug.Log("## 폭탄 던질 조건 만족");
BombThrowPattern();
}
}
}
private void ExecutePattern()
{
_isPatternRunning = true;
Agent.isStopped = true;
IsMeleeCombat = true;
var available = Enumerable
.Range(0, _patternActions.Count)
.Where(i => i != _lastPatternIndex)
.ToList();
int nextIndex = available[Random.Range(0, available.Count)];
_patternActions[nextIndex]?.Invoke();
_lastPatternIndex = nextIndex;
}
// 순환 패턴과 별개로 동작하는 특수 패턴
private void BombThrowPattern()
{
Debug.Log("BombThrowPattern: 보스가 폭탄을 던집니다.");
SetAnimation(BoomShot);
SoundManager.Instance.PlaySFX(boomSound);
_isPatternRunning = true;
Agent.isStopped = true;
for (int i = 0; i < bombCount; i++)
{
Vector3 targetPos = TraceTargetTransform.position;
targetPos.y += 0.1f; // 지면에 맞춤
var warning = Instantiate(chariotSlashWarning, targetPos, Quaternion.identity);
warning.transform.localScale = bombScale;
var aoe = warning.GetComponent<BoomAoeController>();
var effectData = new DamageEffectData
{
damage = (int)attackPower,
radius = bombScale.x,
delay = bombTriggerDelay,
targetLayer = TargetLayerMask,
explosionEffectPrefab = boomExplosion
};
aoe.SetEffect(effectData, null, PatternClear);
}
}
private void ChariotSlashPattern()
{
Debug.Log("ChariotSlashPattern: 보스가 차지 슬래시를 사용합니다.");
WindUpAnimation();
var warning = Instantiate(chariotSlashWarning, transform.position, Quaternion.identity)
.GetComponent<ChariotAoeController>();
var effectData = new DamageEffectData
{
damage = (int)attackPower,
radius = 7.5f,
delay = 2.5f,
targetLayer = TargetLayerMask,
explosionEffectPrefab = chariotSlash
};
warning.SetEffect(effectData, SlashAnimationPlay, PatternClear);
}
private void VerticalSlashPattern()
{
Debug.Log("VerticalSlashPattern: 보스가 수직 슬래시를 사용합니다.");
WindUpAnimation();
var warning = Instantiate(verticalWarning, transform.position, transform.rotation)
.GetComponent<VerticalAoeController>();
var effectData = new DamageEffectData
{
damage = (int)attackPower,
radius = 5f,
delay = 2f,
targetLayer = TargetLayerMask,
explosionEffectPrefab = verticalSlash
};
warning.SetEffect(effectData, SlashAnimationPlay, PatternClear);
}
private void HorizontalSlashPattern()
{
Debug.Log("HorizontalSlashPattern: 보스가 횡적 슬래시를 사용합니다.");
WindUpAnimation();
var warning = Instantiate(horizontalWarning, transform.position, transform.rotation)
.GetComponent<HorizontalAoeController>();
var effectData = new DamageEffectData
{
damage = (int)attackPower,
radius = 15f,
delay = 2f,
targetLayer = TargetLayerMask,
explosionEffectPrefab = horizontalSlash
};
warning.SetEffect(effectData, SlashAnimationPlay, PatternClear);
}
private void WindUpAnimation()
{
SetAnimation(WindUp);
}
private void SlashAnimationPlay()
{
SetAnimation(Slash);
SoundManager.Instance.PlaySFX(slashSound);
}
private void PatternClear()
{
_isPatternRunning = false;
IsMeleeCombat = false;
_patternTimer = 0f;
Agent.isStopped = false;
}
}