DEG-41 근접 범위패턴, 거리가 멀면 원거리 공격 패턴 추가
This commit is contained in:
parent
c0fde7a8d2
commit
b6e0458350
@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:b9e37c8d0a91f3599d34a7715c632cbcf76fd3c0a96c5d5335ab9d6ff65d3b4c
|
||||
size 18916
|
||||
oid sha256:481922b21d2de476145ad4fefaccad66d344052ffc0a2808e577b717e59be4e9
|
||||
size 18696
|
||||
|
BIN
Assets/JYY/Scenes/MonsterTest.unity
(Stored with Git LFS)
BIN
Assets/JYY/Scenes/MonsterTest.unity
(Stored with Git LFS)
Binary file not shown.
3
Assets/Scripts/Character/Enemy/BossPattern.meta
Normal file
3
Assets/Scripts/Character/Enemy/BossPattern.meta
Normal file
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d3b800a343fe42afa7494329ef235461
|
||||
timeCreated: 1745300808
|
@ -17,15 +17,17 @@ public struct DamageEffectData
|
||||
|
||||
public class ChariotAoeController : MonoBehaviour
|
||||
{
|
||||
private DamageEffectData _data;
|
||||
[SerializeField] private GameObject warningEffectInstance;
|
||||
|
||||
private EnemyController _enemyController;
|
||||
private DamageEffectData _data;
|
||||
private Action _destroyAction;
|
||||
private Action _slashAction;
|
||||
|
||||
public void SetEffect(DamageEffectData data, EnemyController enemyController)
|
||||
public void SetEffect(DamageEffectData data, Action slashAction, Action destroyAction)
|
||||
{
|
||||
_data = data;
|
||||
_enemyController = enemyController;
|
||||
_slashAction = slashAction;
|
||||
_destroyAction = destroyAction;
|
||||
|
||||
ShowWarningEffect();
|
||||
Invoke(nameof(Explode), _data.delay);
|
||||
@ -45,8 +47,11 @@ public class ChariotAoeController : MonoBehaviour
|
||||
// 공격 전조 제거
|
||||
warningEffectInstance.SetActive(false);
|
||||
|
||||
// 공격 애니메이션 실행
|
||||
_slashAction.Invoke();
|
||||
|
||||
effect.transform.localScale = new Vector3(_data.radius, _data.radius, _data.radius);
|
||||
_enemyController.SetAttackTrigger(true);
|
||||
|
||||
// 폭발 반경 내의 모든 콜라이더 가져오기
|
||||
Collider[] hitColliders = Physics.OverlapSphere(transform.position, _data.radius, _data.targetLayer);
|
||||
foreach (Collider hit in hitColliders)
|
||||
@ -69,8 +74,7 @@ public class ChariotAoeController : MonoBehaviour
|
||||
|
||||
private void OnDestroy()
|
||||
{
|
||||
_enemyController.SetAttackTrigger(false);
|
||||
_enemyController = null;
|
||||
_destroyAction.Invoke();
|
||||
}
|
||||
|
||||
private void OnDrawGizmosSelected()
|
@ -12,26 +12,12 @@ public abstract class EnemyController : CharacterBase
|
||||
[SerializeField] private float detectCircleRadius = 10f; // 플레이어 탐지 범위
|
||||
[SerializeField] private LayerMask targetLayerMask; // 플레이어 레이어 마스크
|
||||
|
||||
public Transform TraceTargetTransform { get; private set; }
|
||||
public NavMeshAgent Agent { get; private set; }
|
||||
public Animator EnemyAnimator { get; private set; }
|
||||
public EnemyState CurrentState {get; private set;}
|
||||
public LayerMask TargetLayerMask => targetLayerMask;
|
||||
public bool AttackTrigger { get; protected set; }
|
||||
|
||||
public bool IsInBattle { get => _isInBattle; protected set=> _isInBattle = value; }
|
||||
private bool _isInBattle = false;
|
||||
|
||||
|
||||
public bool IsBoss { get => _isBoss; protected set => _isBoss = value; }
|
||||
private bool _isBoss = false;
|
||||
public float WalkSpeed => walkSpeed;
|
||||
public float RunSpeed => runSpeed;
|
||||
|
||||
public Transform TraceTargetTransform { get; private set; }
|
||||
|
||||
[Header("이동 능력")]
|
||||
[SerializeField] private float walkSpeed = 5;
|
||||
[SerializeField] private float runSpeed = 8;
|
||||
public float MoveSpeed => moveSpeed;
|
||||
|
||||
// -----
|
||||
// 상태 변수
|
||||
@ -40,7 +26,6 @@ public abstract class EnemyController : CharacterBase
|
||||
private EnemyStateAttack _enemyStateAttack;
|
||||
private EnemyStateDead _enemyStateDead;
|
||||
|
||||
|
||||
private Dictionary<EnemyState, IEnemyState> _enemyStates;
|
||||
|
||||
protected virtual void Awake()
|
||||
@ -88,11 +73,6 @@ public abstract class EnemyController : CharacterBase
|
||||
_enemyStates[CurrentState].Enter(this);
|
||||
}
|
||||
|
||||
public void SetInBattle(bool battle)
|
||||
{
|
||||
_isInBattle = battle;
|
||||
}
|
||||
|
||||
|
||||
public override void Die()
|
||||
{
|
||||
@ -101,11 +81,6 @@ public abstract class EnemyController : CharacterBase
|
||||
|
||||
}
|
||||
|
||||
public void SetAttackTrigger(bool value)
|
||||
{
|
||||
AttackTrigger = value;
|
||||
}
|
||||
|
||||
#region 적 탐지
|
||||
|
||||
// 일정 반경에 플레이어가 진입하면 플레이어 소리를 감지했다고 판단
|
||||
|
@ -4,52 +4,22 @@ using UnityEngine;
|
||||
|
||||
public class EnemyStateAttack : IEnemyState
|
||||
{
|
||||
private static readonly int VertiSlash = Animator.StringToHash("VertiSlash");
|
||||
private static readonly int VertiAttack = Animator.StringToHash("VertiAttack");
|
||||
|
||||
private EnemyController _enemyController;
|
||||
private Animator _animator;
|
||||
private Coroutine _attackRoutine;
|
||||
|
||||
private const float AttackInterval = 2f;
|
||||
private float _attackTimer = 0f;
|
||||
|
||||
public void Enter(EnemyController enemyController)
|
||||
{
|
||||
_enemyController = enemyController;
|
||||
_animator = _enemyController.EnemyAnimator;
|
||||
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
if (!_enemyController.IsBoss)
|
||||
NonBossSequence();
|
||||
|
||||
if (_enemyController.AttackTrigger)
|
||||
{
|
||||
_animator.SetTrigger(VertiSlash);
|
||||
_enemyController.SetState(EnemyState.Trace);
|
||||
}
|
||||
}
|
||||
|
||||
private void NonBossSequence()
|
||||
{
|
||||
_animator.SetBool(VertiAttack, true);
|
||||
_attackTimer += Time.deltaTime;
|
||||
|
||||
if (_attackTimer >= AttackInterval)
|
||||
{
|
||||
_animator.SetTrigger(VertiSlash);
|
||||
_attackTimer = 0f;
|
||||
_enemyController.SetState(EnemyState.Trace);
|
||||
}
|
||||
}
|
||||
|
||||
public void Exit()
|
||||
{
|
||||
_enemyController.SetAttackTrigger(false);
|
||||
_animator.SetBool(VertiAttack, false);
|
||||
_animator = null;
|
||||
_enemyController = null;
|
||||
}
|
||||
|
@ -6,7 +6,6 @@
|
||||
{
|
||||
_enemyController = enemyController;
|
||||
_enemyController.EnemyAnimator.SetTrigger("Dead");
|
||||
_enemyController.SetInBattle(false);
|
||||
}
|
||||
|
||||
public void Update()
|
||||
|
@ -2,13 +2,13 @@
|
||||
|
||||
public class EnemyStateIdle: IEnemyState
|
||||
{
|
||||
private static readonly int Idle = Animator.StringToHash("Idle");
|
||||
private EnemyController _enemyController;
|
||||
|
||||
public void Enter(EnemyController enemyController)
|
||||
{
|
||||
_enemyController = enemyController;
|
||||
_enemyController.EnemyAnimator.SetBool("Idle", true);
|
||||
_enemyController.SetInBattle(false);
|
||||
_enemyController.EnemyAnimator.SetBool(Idle, true);
|
||||
}
|
||||
|
||||
public void Update()
|
||||
@ -22,7 +22,7 @@ public class EnemyStateIdle: IEnemyState
|
||||
|
||||
public void Exit()
|
||||
{
|
||||
_enemyController.EnemyAnimator.SetBool("Idle", false);
|
||||
_enemyController.EnemyAnimator.SetBool(Idle, false);
|
||||
_enemyController = null;
|
||||
}
|
||||
}
|
@ -29,11 +29,12 @@ public class EnemyStateTrace : IEnemyState
|
||||
}
|
||||
|
||||
_enemyController.EnemyAnimator.SetBool(Trace, true);
|
||||
_enemyController.SetInBattle(true);
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
if (_enemyController.Agent.enabled != true) return;
|
||||
|
||||
// 일정 주기로 찾은 플레이어의 위치를 갱신해서 갱신된 위치로 이동
|
||||
FindTargetPosition();
|
||||
|
||||
@ -44,7 +45,6 @@ public class EnemyStateTrace : IEnemyState
|
||||
// TODO: 타겟에 도착함 -> 공격 준비
|
||||
_enemyController.SetState(EnemyState.Attack);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void FindTargetPosition()
|
||||
@ -70,24 +70,12 @@ public class EnemyStateTrace : IEnemyState
|
||||
{
|
||||
float distance = (_detectPlayerTransform.position - _enemyController.transform.position).magnitude;
|
||||
|
||||
if (distance > 5f)
|
||||
{
|
||||
// 먼 거리: 뛰기
|
||||
_enemyController.Agent.speed = _enemyController.RunSpeed;
|
||||
_enemyController.Agent.acceleration = 20f;
|
||||
_enemyController.Agent.angularSpeed = 270f;
|
||||
// _enemyController.EnemyAnimator.SetFloat("MoveSpeed", 1f); // 애니메이션도 Run으로
|
||||
|
||||
// NavMeshAgent 회전에 맡기기
|
||||
_enemyController.Agent.updateRotation = true;
|
||||
}
|
||||
else if (distance > 2f)
|
||||
if (distance > 2f)
|
||||
{
|
||||
// 가까운 거리: 걷기
|
||||
_enemyController.Agent.speed = _enemyController.WalkSpeed;
|
||||
_enemyController.Agent.speed = _enemyController.MoveSpeed;
|
||||
_enemyController.Agent.acceleration = 8f;
|
||||
_enemyController.Agent.angularSpeed = 720f;
|
||||
// _enemyController.EnemyAnimator.SetFloat("MoveSpeed", 0.4f); // Walk 애니메이션
|
||||
|
||||
_enemyController.Agent.updateRotation = true;
|
||||
}
|
||||
@ -108,11 +96,6 @@ public class EnemyStateTrace : IEnemyState
|
||||
Time.deltaTime * 10f // 회전 속도
|
||||
);
|
||||
}
|
||||
|
||||
// _enemyController.Agent.angularSpeed = 1080f;
|
||||
// _enemyController.Agent.acceleration = 999f;
|
||||
|
||||
// _enemyController.EnemyAnimator.SetFloat("MoveSpeed", 0f);
|
||||
}
|
||||
|
||||
// 실제 속도 기반으로 애니메이션 제어
|
||||
|
@ -2,9 +2,13 @@ using System;
|
||||
using System.Collections;
|
||||
using Unity.VisualScripting;
|
||||
using UnityEngine;
|
||||
using Random = UnityEngine.Random;
|
||||
|
||||
public class PldDogController : EnemyController
|
||||
{
|
||||
private static readonly int WindUp = Animator.StringToHash("WindUp");
|
||||
private static readonly int VertiSlash = Animator.StringToHash("VertiSlash");
|
||||
|
||||
[Header("공격 패턴 관련")]
|
||||
[SerializeField] private float patternInterval = 3f;
|
||||
|
||||
@ -12,7 +16,6 @@ public class PldDogController : EnemyController
|
||||
private int _currentPatternIndex = 0;
|
||||
private bool _isPatternRunning = false;
|
||||
|
||||
|
||||
[Header("각종 데미지 이펙트 세트")]
|
||||
[SerializeField] private GameObject chariotSlashWarning;
|
||||
[SerializeField] private GameObject chariotSlash;
|
||||
@ -25,27 +28,64 @@ public class PldDogController : EnemyController
|
||||
[SerializeField] private GameObject horizontalWarning;
|
||||
[SerializeField] private GameObject horizontalSlash;
|
||||
|
||||
// 몬스터의 행동 스크립트
|
||||
// IsBoos = 보스몬스터 여부
|
||||
// IsInBattle = 전투중인지 여부
|
||||
protected override void Awake()
|
||||
{
|
||||
base.Awake();
|
||||
IsBoss = true;
|
||||
}
|
||||
private bool _isInTrace;
|
||||
private bool _isInAttack;
|
||||
private bool _isFirstAttack = true;
|
||||
|
||||
private void Update()
|
||||
{
|
||||
base.Update();
|
||||
|
||||
if (IsInBattle && !_isPatternRunning && CurrentState == EnemyState.Attack)
|
||||
CheckIsInBattle();
|
||||
|
||||
if (_isInAttack)
|
||||
{
|
||||
_patternTimer += Time.deltaTime;
|
||||
if (_patternTimer >= patternInterval)
|
||||
|
||||
if (!_isPatternRunning && (_isFirstAttack || _patternTimer >= patternInterval))
|
||||
{
|
||||
ExecutePattern(0);
|
||||
Agent.enabled = false;
|
||||
|
||||
// TODO: 순서대로 패턴 실행
|
||||
ExecutePattern(_currentPatternIndex);
|
||||
|
||||
// _currentPatternIndex = (_currentPatternIndex + 1) % 3; // 패턴 순환
|
||||
|
||||
_isFirstAttack = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (_isInTrace)
|
||||
{
|
||||
_patternTimer += Time.deltaTime;
|
||||
|
||||
if (!_isPatternRunning && _patternTimer >= patternInterval)
|
||||
{
|
||||
_isPatternRunning = true;
|
||||
|
||||
float distanceToPlayer = Vector3.Distance(transform.position, TraceTargetTransform.position);
|
||||
|
||||
if (distanceToPlayer > 3f)
|
||||
{
|
||||
BombThrowPattern();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void CheckIsInBattle()
|
||||
{
|
||||
switch (CurrentState)
|
||||
{
|
||||
case EnemyState.Attack:
|
||||
_isInAttack = true;
|
||||
_isInTrace = false;
|
||||
break;
|
||||
case EnemyState.Trace:
|
||||
_isInTrace = true;
|
||||
_isInAttack = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void ExecutePattern(int patternIndex)
|
||||
@ -70,11 +110,41 @@ public class PldDogController : EnemyController
|
||||
}
|
||||
}
|
||||
|
||||
private void BombThrowPattern()
|
||||
{
|
||||
Debug.Log("BombThrowPattern: 보스가 폭탄을 던집니다.");
|
||||
|
||||
int bombCount = 1; // 한 번에 몇 개 던질지
|
||||
float radius = 2f;
|
||||
|
||||
for (int i = 0; i < bombCount; i++)
|
||||
{
|
||||
Vector3 randomPos = TraceTargetTransform.position + (Random.insideUnitSphere * radius);
|
||||
randomPos.y = 0.1f; // 지면에 맞추기
|
||||
|
||||
var boomObj = Instantiate(chariotSlashWarning, randomPos, Quaternion.identity);
|
||||
boomObj.transform.localScale = new Vector3(5f, 5f, 5f);
|
||||
var boom = boomObj.GetComponent<ChariotAoeController>();
|
||||
|
||||
DamageEffectData effectData = new DamageEffectData()
|
||||
{
|
||||
damage = (int)attackPower,
|
||||
radius = 5f,
|
||||
delay = 1.5f,
|
||||
targetLayer = TargetLayerMask,
|
||||
explosionEffectPrefab = chariotSlash
|
||||
};
|
||||
|
||||
boom.SetEffect(effectData,()=>{ }, PatternClear);
|
||||
}
|
||||
}
|
||||
|
||||
private void ChariotSlashPattern()
|
||||
{
|
||||
Debug.Log("ChariotSlashPattern: 보스가 차지 슬래시를 사용합니다.");
|
||||
EnemyAnimator.SetBool("VertiAttack", true);
|
||||
var warning = Instantiate(chariotSlashWarning, transform.position, Quaternion.identity)
|
||||
WindUpAnimationStart();
|
||||
|
||||
var slash = Instantiate(chariotSlashWarning, transform.position, Quaternion.identity)
|
||||
.GetComponent<ChariotAoeController>();
|
||||
|
||||
DamageEffectData effectData = new DamageEffectData()
|
||||
@ -85,6 +155,36 @@ public class PldDogController : EnemyController
|
||||
targetLayer = TargetLayerMask,
|
||||
explosionEffectPrefab = chariotSlash
|
||||
};
|
||||
warning.SetEffect(effectData, this);
|
||||
|
||||
slash.SetEffect(effectData, SlashAnimationPlay,
|
||||
() =>
|
||||
{
|
||||
PatternClear();
|
||||
WindUpAnimationEnd();
|
||||
SetState(EnemyState.Trace);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
private void WindUpAnimationStart()
|
||||
{
|
||||
EnemyAnimator.SetBool(WindUp, true);
|
||||
}
|
||||
|
||||
private void WindUpAnimationEnd()
|
||||
{
|
||||
EnemyAnimator.SetBool(WindUp, false);
|
||||
}
|
||||
|
||||
private void SlashAnimationPlay()
|
||||
{
|
||||
EnemyAnimator.SetTrigger(VertiSlash);
|
||||
}
|
||||
|
||||
private void PatternClear()
|
||||
{
|
||||
_isPatternRunning = false;
|
||||
_patternTimer = 0f;
|
||||
Agent.enabled = true;
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user