From 3694483a9c3af6f99048669fd0d885cee32e3c8f Mon Sep 17 00:00:00 2001 From: fiore Date: Mon, 21 Apr 2025 16:24:23 +0900 Subject: [PATCH 1/7] =?UTF-8?q?DEG-41=20=EC=A0=84=ED=88=AC=20=ED=8C=A8?= =?UTF-8?q?=ED=84=B4=20=EA=B5=AC=ED=98=84=20=EC=8B=9C=EC=9E=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Assets/JYY/Prefabs/AOEIndicator.prefab | 3 --- Assets/JYY/Prefabs/AOEIndicator.prefab.meta | 7 ------- Assets/JYY/Prefabs/AOEIndicatorChariot.prefab | 4 ++-- .../Scripts/Character/Enemy/EnemyDemageField.cs | 7 +++++++ .../Character/Enemy/EnemyDemageField.cs.meta | 3 +++ .../Enemy/EnemyState/EnemyStateAttack.cs | 15 +++++++-------- 6 files changed, 19 insertions(+), 20 deletions(-) delete mode 100644 Assets/JYY/Prefabs/AOEIndicator.prefab delete mode 100644 Assets/JYY/Prefabs/AOEIndicator.prefab.meta create mode 100644 Assets/Scripts/Character/Enemy/EnemyDemageField.cs create mode 100644 Assets/Scripts/Character/Enemy/EnemyDemageField.cs.meta diff --git a/Assets/JYY/Prefabs/AOEIndicator.prefab b/Assets/JYY/Prefabs/AOEIndicator.prefab deleted file mode 100644 index 6ac5eda7..00000000 --- a/Assets/JYY/Prefabs/AOEIndicator.prefab +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:8b8cb01bd819acc4a85f049a7fa119e05a3587e1f3b9e88ce1f0f0729a09b326 -size 4274 diff --git a/Assets/JYY/Prefabs/AOEIndicator.prefab.meta b/Assets/JYY/Prefabs/AOEIndicator.prefab.meta deleted file mode 100644 index 0035b785..00000000 --- a/Assets/JYY/Prefabs/AOEIndicator.prefab.meta +++ /dev/null @@ -1,7 +0,0 @@ -fileFormatVersion: 2 -guid: 36d2fcfec062c074ba2dad3a0b0116be -PrefabImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/JYY/Prefabs/AOEIndicatorChariot.prefab b/Assets/JYY/Prefabs/AOEIndicatorChariot.prefab index 5b73b6cb..6991ab32 100644 --- a/Assets/JYY/Prefabs/AOEIndicatorChariot.prefab +++ b/Assets/JYY/Prefabs/AOEIndicatorChariot.prefab @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:db1f3ad7db0d99b20fdfe95c0ba7248476edee0875596606eb05ac19c33e84f2 -size 4283 +oid sha256:4487834d50c67ef719d45ea081a895bebc943de247d782072226e7c6b7dc6d5a +size 4703 diff --git a/Assets/Scripts/Character/Enemy/EnemyDemageField.cs b/Assets/Scripts/Character/Enemy/EnemyDemageField.cs new file mode 100644 index 00000000..4b22b760 --- /dev/null +++ b/Assets/Scripts/Character/Enemy/EnemyDemageField.cs @@ -0,0 +1,7 @@ +using UnityEngine; + +public class EnemyDemageField : MonoBehaviour +{ + private float damage; + +} \ No newline at end of file diff --git a/Assets/Scripts/Character/Enemy/EnemyDemageField.cs.meta b/Assets/Scripts/Character/Enemy/EnemyDemageField.cs.meta new file mode 100644 index 00000000..7afc07ba --- /dev/null +++ b/Assets/Scripts/Character/Enemy/EnemyDemageField.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 8ac23a14eeef4226962782ab20ec78e0 +timeCreated: 1745219566 \ No newline at end of file diff --git a/Assets/Scripts/Character/Enemy/EnemyState/EnemyStateAttack.cs b/Assets/Scripts/Character/Enemy/EnemyState/EnemyStateAttack.cs index 6cc865a5..6a35e710 100644 --- a/Assets/Scripts/Character/Enemy/EnemyState/EnemyStateAttack.cs +++ b/Assets/Scripts/Character/Enemy/EnemyState/EnemyStateAttack.cs @@ -36,20 +36,19 @@ public class EnemyStateAttack : IEnemyState private IEnumerator VerticalAttackSequence() { - // 1. 전조 이펙트 생성 + yield return new WaitForSeconds(0.1f); + // 1. 전조 이펙트 생성, 검을 들어올림 _enemyAttackController.TriggerRandomWarning(_enemyController.transform.position, _enemyController.transform.rotation); - // 2. 검을 들어올림 - yield return new WaitForSeconds(3f); + // 2. 대기(전조와 검 들어올리는 애니메이션을 위함) + yield return new WaitForSeconds(2f); - // 3. 대기(전조와 검 들어올리는 애니메이션을 위함) - - // 4. 검 휘두르기 + // 3. 검 휘두르기 _animator.SetTrigger(VertiSlash); _enemyAttackController.DestroyWarningArea(); - // TODO : 5. 공격 판정 발생 + // TODO : 4. 공격 판정 발생 yield return new WaitForSeconds(1f); - // 6. 애니메이션 트리거 종료 -> 애니메이터 상태 머신으로 처리 + // 5. 애니메이션 트리거 종료 -> 애니메이터 상태 머신으로 처리 _enemyController.SetState(EnemyState.Trace); } From c0fde7a8d295e9976c2b03a798b8d4d58f8bc4b0 Mon Sep 17 00:00:00 2001 From: fiore Date: Tue, 22 Apr 2025 14:24:03 +0900 Subject: [PATCH 2/7] =?UTF-8?q?DEG-41=20=EC=82=AC=EC=9A=A9=ED=95=98?= =?UTF-8?q?=EC=A7=80=20=EC=95=8A=EB=8A=94=20=ED=8C=A8=ED=84=B4=20=EC=A0=95?= =?UTF-8?q?=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Assets/Editor/EnemyControllerEditor.cs | 10 +-- Assets/JYY/Prefabs/AOEIndicatorChariot.prefab | 3 - Assets/JYY/Prefabs/AOEIndicatorDynamo.prefab | 4 +- .../JYY/Prefabs/AOEIndicatorHorizontal.prefab | 2 +- .../JYY/Prefabs/AOEIndicatorVertical.prefab | 2 +- .../JYY/Prefabs/AoE Indicator Chariot.prefab | 3 + ...meta => AoE Indicator Chariot.prefab.meta} | 2 +- .../JYY/Prefabs/AoE Slash Blue Chariot.prefab | 3 + .../AoE Slash Blue Chariot.prefab.meta | 7 ++ Assets/JYY/Prefabs/[Enemy] PldDog.prefab | 4 +- Assets/JYY/Scenes/MonsterTest.unity | 4 +- .../Character/Enemy/ChariotAoeController.cs | 81 ++++++++++++++++++ ...r.cs.meta => ChariotAoeController.cs.meta} | 0 .../Enemy/EnemyAnimatorStateAttack.cs | 14 ---- .../Enemy/EnemyAnimatorStateAttack.cs.meta | 11 --- .../Character/Enemy/EnemyAttackController.cs | 42 ---------- .../Character/Enemy/EnemyController.cs | 44 ++++++---- .../Character/Enemy/EnemyDemageField.cs | 7 -- .../Character/Enemy/EnemyDemageField.cs.meta | 3 - .../Enemy/EnemyState/EnemyStateAttack.cs | 53 +++++------- .../Enemy/EnemyState/EnemyStateDead.cs | 1 + .../Enemy/EnemyState/EnemyStateGetHit.cs | 19 ----- .../Enemy/EnemyState/EnemyStateGetHit.cs.meta | 3 - .../Enemy/EnemyState/EnemyStateIdle.cs | 6 +- .../Enemy/EnemyState/EnemyStateMove.cs | 19 ----- .../Enemy/EnemyState/EnemyStateMove.cs.meta | 3 - .../Enemy/EnemyState/EnemyStateTrace.cs | 1 + .../Character/Enemy/PldDogController.cs | 83 +++++++++++++++++++ 28 files changed, 243 insertions(+), 191 deletions(-) delete mode 100644 Assets/JYY/Prefabs/AOEIndicatorChariot.prefab create mode 100644 Assets/JYY/Prefabs/AoE Indicator Chariot.prefab rename Assets/JYY/Prefabs/{AOEIndicatorChariot.prefab.meta => AoE Indicator Chariot.prefab.meta} (74%) create mode 100644 Assets/JYY/Prefabs/AoE Slash Blue Chariot.prefab create mode 100644 Assets/JYY/Prefabs/AoE Slash Blue Chariot.prefab.meta create mode 100644 Assets/Scripts/Character/Enemy/ChariotAoeController.cs rename Assets/Scripts/Character/Enemy/{EnemyAttackController.cs.meta => ChariotAoeController.cs.meta} (100%) delete mode 100644 Assets/Scripts/Character/Enemy/EnemyAnimatorStateAttack.cs delete mode 100644 Assets/Scripts/Character/Enemy/EnemyAnimatorStateAttack.cs.meta delete mode 100644 Assets/Scripts/Character/Enemy/EnemyAttackController.cs delete mode 100644 Assets/Scripts/Character/Enemy/EnemyDemageField.cs delete mode 100644 Assets/Scripts/Character/Enemy/EnemyDemageField.cs.meta delete mode 100644 Assets/Scripts/Character/Enemy/EnemyState/EnemyStateGetHit.cs delete mode 100644 Assets/Scripts/Character/Enemy/EnemyState/EnemyStateGetHit.cs.meta delete mode 100644 Assets/Scripts/Character/Enemy/EnemyState/EnemyStateMove.cs delete mode 100644 Assets/Scripts/Character/Enemy/EnemyState/EnemyStateMove.cs.meta diff --git a/Assets/Editor/EnemyControllerEditor.cs b/Assets/Editor/EnemyControllerEditor.cs index 23ac07cc..82dc98de 100644 --- a/Assets/Editor/EnemyControllerEditor.cs +++ b/Assets/Editor/EnemyControllerEditor.cs @@ -30,12 +30,6 @@ public class EnemyControllerEditor : Editor case EnemyState.Attack: GUI.backgroundColor = new Color(1, 1, 0, 1f); break; - case EnemyState.Move: - GUI.backgroundColor = new Color(0, 1, 1, 1f); - break; - case EnemyState.GetHit: - GUI.backgroundColor = new Color(0.1f, 0.1f, 0.1f, 1f); - break; case EnemyState.Dead: GUI.backgroundColor = new Color(1, 0, 0, 1f); break; @@ -55,12 +49,10 @@ public class EnemyControllerEditor : Editor EditorGUILayout.BeginHorizontal(); if (GUILayout.Button("Idle")) enemyController.SetState(EnemyState.Idle); if (GUILayout.Button("Trace")) enemyController.SetState(EnemyState.Trace); - if (GUILayout.Button("Attack")) enemyController.SetState(EnemyState.Attack); EditorGUILayout.EndHorizontal(); EditorGUILayout.BeginHorizontal(); - if (GUILayout.Button("Move")) enemyController.SetState(EnemyState.Move); - if (GUILayout.Button("GetHit")) enemyController.SetState(EnemyState.GetHit); + if (GUILayout.Button("Attack")) enemyController.SetState(EnemyState.Attack); if (GUILayout.Button("Dead")) enemyController.SetState(EnemyState.Dead); EditorGUILayout.EndHorizontal(); } diff --git a/Assets/JYY/Prefabs/AOEIndicatorChariot.prefab b/Assets/JYY/Prefabs/AOEIndicatorChariot.prefab deleted file mode 100644 index 6991ab32..00000000 --- a/Assets/JYY/Prefabs/AOEIndicatorChariot.prefab +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:4487834d50c67ef719d45ea081a895bebc943de247d782072226e7c6b7dc6d5a -size 4703 diff --git a/Assets/JYY/Prefabs/AOEIndicatorDynamo.prefab b/Assets/JYY/Prefabs/AOEIndicatorDynamo.prefab index 72d92b28..10a01d7f 100644 --- a/Assets/JYY/Prefabs/AOEIndicatorDynamo.prefab +++ b/Assets/JYY/Prefabs/AOEIndicatorDynamo.prefab @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:bf0fd0659c187d35c8492ff925145c94fc5cac08dead6b13188f3f4cbb2f3052 -size 3988 +oid sha256:5fd0a892305c7a4c4e18543cf88703c940210e639e0a0a94aba30f0fe7fb4a2d +size 3986 diff --git a/Assets/JYY/Prefabs/AOEIndicatorHorizontal.prefab b/Assets/JYY/Prefabs/AOEIndicatorHorizontal.prefab index d6ba9554..2617bea6 100644 --- a/Assets/JYY/Prefabs/AOEIndicatorHorizontal.prefab +++ b/Assets/JYY/Prefabs/AOEIndicatorHorizontal.prefab @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e5dfaa59aeffa4e948edd40e96f05e2c708e491bb80c2a3446d9d1335b05adf0 +oid sha256:a8dcf363afeb774bbc49dde7a349e233c2ff8531d33694113013455fc7a4c7ca size 3995 diff --git a/Assets/JYY/Prefabs/AOEIndicatorVertical.prefab b/Assets/JYY/Prefabs/AOEIndicatorVertical.prefab index 28217b13..7acabcd4 100644 --- a/Assets/JYY/Prefabs/AOEIndicatorVertical.prefab +++ b/Assets/JYY/Prefabs/AOEIndicatorVertical.prefab @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:02ada0ed142206f604609397dd5b6a2349df7db879e9ab1cb7bdfc1fca8e6f75 +oid sha256:e8da3f157ed92e5524a0fb90cbd4335a8b757a2ef2889f00ae2e66bd704017e6 size 3985 diff --git a/Assets/JYY/Prefabs/AoE Indicator Chariot.prefab b/Assets/JYY/Prefabs/AoE Indicator Chariot.prefab new file mode 100644 index 00000000..36214cb6 --- /dev/null +++ b/Assets/JYY/Prefabs/AoE Indicator Chariot.prefab @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:acaadac3ed9caf040e05fc0f05648346d053813c3be9a3062dd7eeed0a8730b6 +size 4760 diff --git a/Assets/JYY/Prefabs/AOEIndicatorChariot.prefab.meta b/Assets/JYY/Prefabs/AoE Indicator Chariot.prefab.meta similarity index 74% rename from Assets/JYY/Prefabs/AOEIndicatorChariot.prefab.meta rename to Assets/JYY/Prefabs/AoE Indicator Chariot.prefab.meta index 1d15c4e7..0035b785 100644 --- a/Assets/JYY/Prefabs/AOEIndicatorChariot.prefab.meta +++ b/Assets/JYY/Prefabs/AoE Indicator Chariot.prefab.meta @@ -1,5 +1,5 @@ fileFormatVersion: 2 -guid: e9e020ef2784edf4ca2a83ae9e1edefd +guid: 36d2fcfec062c074ba2dad3a0b0116be PrefabImporter: externalObjects: {} userData: diff --git a/Assets/JYY/Prefabs/AoE Slash Blue Chariot.prefab b/Assets/JYY/Prefabs/AoE Slash Blue Chariot.prefab new file mode 100644 index 00000000..995bcd81 --- /dev/null +++ b/Assets/JYY/Prefabs/AoE Slash Blue Chariot.prefab @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:0d42386e12ec2eec2385f13fdcd2558718c9150245a834d5a667060f750b1ced +size 3100 diff --git a/Assets/JYY/Prefabs/AoE Slash Blue Chariot.prefab.meta b/Assets/JYY/Prefabs/AoE Slash Blue Chariot.prefab.meta new file mode 100644 index 00000000..5ba3ecc5 --- /dev/null +++ b/Assets/JYY/Prefabs/AoE Slash Blue Chariot.prefab.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 3f431e991bd65014c833e89305ddd5e3 +PrefabImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/JYY/Prefabs/[Enemy] PldDog.prefab b/Assets/JYY/Prefabs/[Enemy] PldDog.prefab index f383c5f8..8b998d43 100644 --- a/Assets/JYY/Prefabs/[Enemy] PldDog.prefab +++ b/Assets/JYY/Prefabs/[Enemy] PldDog.prefab @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c7b23e4a2f6475f6cfe0641a03fd4415fe2b732fe649a14f93b72ea104f250f3 -size 80026 +oid sha256:a4cedd199100ba2d66a0dfe22b6ab902677fcc6485b02d0553115d0e012b3c97 +size 79510 diff --git a/Assets/JYY/Scenes/MonsterTest.unity b/Assets/JYY/Scenes/MonsterTest.unity index a2f28549..471eda89 100644 --- a/Assets/JYY/Scenes/MonsterTest.unity +++ b/Assets/JYY/Scenes/MonsterTest.unity @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ec97ec66df4283ed273c243f4aa1642c492661d1163184ce650d833e5a36bd87 -size 19269 +oid sha256:ccea4dffb67fe759672ab88a8aae903251498785bbe1d83673c2e0a7a89ace8f +size 19724 diff --git a/Assets/Scripts/Character/Enemy/ChariotAoeController.cs b/Assets/Scripts/Character/Enemy/ChariotAoeController.cs new file mode 100644 index 00000000..f38a905f --- /dev/null +++ b/Assets/Scripts/Character/Enemy/ChariotAoeController.cs @@ -0,0 +1,81 @@ +using System; +using System.Collections.Generic; +using UnityEngine; +using UnityEngine.Serialization; + + +[System.Serializable] +public struct DamageEffectData +{ + public int damage; + public float radius; + public float delay; + public LayerMask targetLayer; + + public GameObject explosionEffectPrefab; +} + +public class ChariotAoeController : MonoBehaviour +{ + private DamageEffectData _data; + [SerializeField] private GameObject warningEffectInstance; + + private EnemyController _enemyController; + + public void SetEffect(DamageEffectData data, EnemyController enemyController) + { + _data = data; + _enemyController = enemyController; + + ShowWarningEffect(); + Invoke(nameof(Explode), _data.delay); + } + + private void ShowWarningEffect() + { + warningEffectInstance.SetActive(true); + float diameter = _data.radius * 2f; + gameObject.transform.localScale = new Vector3(diameter, 1f, diameter); + } + + private void Explode() + { + var effect = Instantiate(_data.explosionEffectPrefab, transform.position, Quaternion.identity); + + // 공격 전조 제거 + warningEffectInstance.SetActive(false); + + 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) + { + if (hit.CompareTag("Player")) + { + // TODO : 데미지 부여 + Debug.Log(hit.name +"에게 공격 적중"); + } + } + + Exit(effect); + } + + private void Exit(GameObject effect) + { + Destroy(effect, 2f); + Destroy(gameObject, 2f); + } + + private void OnDestroy() + { + _enemyController.SetAttackTrigger(false); + _enemyController = null; + } + + private void OnDrawGizmosSelected() + { + Gizmos.color = Color.red; + Gizmos.DrawWireSphere(transform.position, _data.radius); + } +} \ No newline at end of file diff --git a/Assets/Scripts/Character/Enemy/EnemyAttackController.cs.meta b/Assets/Scripts/Character/Enemy/ChariotAoeController.cs.meta similarity index 100% rename from Assets/Scripts/Character/Enemy/EnemyAttackController.cs.meta rename to Assets/Scripts/Character/Enemy/ChariotAoeController.cs.meta diff --git a/Assets/Scripts/Character/Enemy/EnemyAnimatorStateAttack.cs b/Assets/Scripts/Character/Enemy/EnemyAnimatorStateAttack.cs deleted file mode 100644 index 91bdc4a1..00000000 --- a/Assets/Scripts/Character/Enemy/EnemyAnimatorStateAttack.cs +++ /dev/null @@ -1,14 +0,0 @@ -using System.Collections; -using System.Collections.Generic; -using UnityEngine; - -public class EnemyAnimatorStateAttack : StateMachineBehaviour -{ - // OnStateExit is called when a transition ends and the state machine finishes evaluating this state - // override public void OnStateExit(Animator animator, AnimatorStateInfo stateInfo, int layerIndex) - // { - // animator.gameObject.GetComponent().SetState(EnemyState.Trace); - // } - - -} diff --git a/Assets/Scripts/Character/Enemy/EnemyAnimatorStateAttack.cs.meta b/Assets/Scripts/Character/Enemy/EnemyAnimatorStateAttack.cs.meta deleted file mode 100644 index 032dac99..00000000 --- a/Assets/Scripts/Character/Enemy/EnemyAnimatorStateAttack.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: a5765847dbef51e4f9bccde712eeda30 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/Scripts/Character/Enemy/EnemyAttackController.cs b/Assets/Scripts/Character/Enemy/EnemyAttackController.cs deleted file mode 100644 index 543db2f9..00000000 --- a/Assets/Scripts/Character/Enemy/EnemyAttackController.cs +++ /dev/null @@ -1,42 +0,0 @@ -using System.Collections.Generic; -using UnityEngine; - -public class EnemyAttackController : MonoBehaviour -{ - [Header("각종 전조 오브젝트")] - [SerializeField] private GameObject verticalWarningArea; - [SerializeField] private GameObject horizontalWarningArea; - [SerializeField] private GameObject chariotWarningArea; - [SerializeField] private GameObject dynamoWarningArea; - - // 배열에 담아서 관리 - private List warningAreas; - private GameObject _activeArea; - - private void Awake() - { - warningAreas = new List() - { - verticalWarningArea, - horizontalWarningArea, - chariotWarningArea, - dynamoWarningArea - }; - } - - // 랜덤 전조 호출 - public void TriggerRandomWarning(Vector3 spawnPosition, Quaternion spawnRotation) - { - // 0 ~ Count-1 사이 랜덤 인덱스 - int idx = Random.Range(0, warningAreas.Count); - GameObject selected = warningAreas[idx]; - - // 예시: Instantiate 방식으로 화면에 띄우기 - _activeArea = Instantiate(selected, spawnPosition, spawnRotation); - } - - public void DestroyWarningArea() - { - Destroy(_activeArea); - } -} \ No newline at end of file diff --git a/Assets/Scripts/Character/Enemy/EnemyController.cs b/Assets/Scripts/Character/Enemy/EnemyController.cs index 58534e20..d93966fa 100644 --- a/Assets/Scripts/Character/Enemy/EnemyController.cs +++ b/Assets/Scripts/Character/Enemy/EnemyController.cs @@ -2,11 +2,10 @@ using UnityEngine; using UnityEngine.AI; -public enum EnemyState { None, Idle, Trace, Attack, GetHit, Move, Dead } +public enum EnemyState { None, Idle, Trace, Attack, Dead } [RequireComponent(typeof(NavMeshAgent))] [RequireComponent(typeof(Animator))] -[RequireComponent(typeof(EnemyAttackController))] public abstract class EnemyController : CharacterBase { [Header("AI")] @@ -15,36 +14,39 @@ public abstract class EnemyController : CharacterBase 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 EnemyAttackController EnemyAttackController { get; private 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; - // ----- // 상태 변수 private EnemyStateIdle _enemyStateIdle; private EnemyStateTrace _enemyStateTrace; private EnemyStateAttack _enemyStateAttack; - private EnemyStateGetHit _enemyStateGetHit; private EnemyStateDead _enemyStateDead; - private EnemyStateMove _enemyStateMove; + private Dictionary _enemyStates; - private void Awake() + protected virtual void Awake() { EnemyAnimator = GetComponent(); Agent = GetComponent(); - EnemyAttackController = GetComponent(); } protected override void Start() @@ -55,24 +57,20 @@ public abstract class EnemyController : CharacterBase _enemyStateIdle = new EnemyStateIdle(); _enemyStateTrace = new EnemyStateTrace(); _enemyStateAttack = new EnemyStateAttack(); - _enemyStateGetHit = new EnemyStateGetHit(); _enemyStateDead = new EnemyStateDead(); - _enemyStateMove = new EnemyStateMove(); _enemyStates = new Dictionary { { EnemyState.Idle, _enemyStateIdle }, { EnemyState.Trace, _enemyStateTrace }, { EnemyState.Attack, _enemyStateAttack }, - { EnemyState.GetHit, _enemyStateGetHit }, { EnemyState.Dead, _enemyStateDead }, - { EnemyState.Move, _enemyStateMove} }; SetState(EnemyState.Idle); } - private void Update() + protected void Update() { if (CurrentState != EnemyState.None) { @@ -90,6 +88,24 @@ public abstract class EnemyController : CharacterBase _enemyStates[CurrentState].Enter(this); } + public void SetInBattle(bool battle) + { + _isInBattle = battle; + } + + + public override void Die() + { + base.Die(); + // TODO : 사망 후 동작 + + } + + public void SetAttackTrigger(bool value) + { + AttackTrigger = value; + } + #region 적 탐지 // 일정 반경에 플레이어가 진입하면 플레이어 소리를 감지했다고 판단 diff --git a/Assets/Scripts/Character/Enemy/EnemyDemageField.cs b/Assets/Scripts/Character/Enemy/EnemyDemageField.cs deleted file mode 100644 index 4b22b760..00000000 --- a/Assets/Scripts/Character/Enemy/EnemyDemageField.cs +++ /dev/null @@ -1,7 +0,0 @@ -using UnityEngine; - -public class EnemyDemageField : MonoBehaviour -{ - private float damage; - -} \ No newline at end of file diff --git a/Assets/Scripts/Character/Enemy/EnemyDemageField.cs.meta b/Assets/Scripts/Character/Enemy/EnemyDemageField.cs.meta deleted file mode 100644 index 7afc07ba..00000000 --- a/Assets/Scripts/Character/Enemy/EnemyDemageField.cs.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: 8ac23a14eeef4226962782ab20ec78e0 -timeCreated: 1745219566 \ No newline at end of file diff --git a/Assets/Scripts/Character/Enemy/EnemyState/EnemyStateAttack.cs b/Assets/Scripts/Character/Enemy/EnemyState/EnemyStateAttack.cs index 6a35e710..1442509b 100644 --- a/Assets/Scripts/Character/Enemy/EnemyState/EnemyStateAttack.cs +++ b/Assets/Scripts/Character/Enemy/EnemyState/EnemyStateAttack.cs @@ -10,58 +10,47 @@ public class EnemyStateAttack : IEnemyState private EnemyController _enemyController; private Animator _animator; private Coroutine _attackRoutine; - private EnemyAttackController _enemyAttackController; - private enum AttackType - { - VerticalAttack, // 위에서 아래로 베는 것 - HorizontalAttack, // 옆으로 베는 것 - ChariotAttack, // 원형 - DynamoAttack, // 도넛 - }; - private AttackType _currentAttackType; + private const float AttackInterval = 2f; + private float _attackTimer = 0f; public void Enter(EnemyController enemyController) { _enemyController = enemyController; _animator = _enemyController.EnemyAnimator; - _enemyAttackController = _enemyController.EnemyAttackController; - _animator.SetBool(VertiAttack, true); - _attackRoutine = _enemyController.StartCoroutine(VerticalAttackSequence()); + } public void Update() { + if (!_enemyController.IsBoss) + NonBossSequence(); + + if (_enemyController.AttackTrigger) + { + _animator.SetTrigger(VertiSlash); + _enemyController.SetState(EnemyState.Trace); + } } - private IEnumerator VerticalAttackSequence() + private void NonBossSequence() { - yield return new WaitForSeconds(0.1f); - // 1. 전조 이펙트 생성, 검을 들어올림 - _enemyAttackController.TriggerRandomWarning(_enemyController.transform.position, _enemyController.transform.rotation); - // 2. 대기(전조와 검 들어올리는 애니메이션을 위함) - yield return new WaitForSeconds(2f); + _animator.SetBool(VertiAttack, true); + _attackTimer += Time.deltaTime; - // 3. 검 휘두르기 - _animator.SetTrigger(VertiSlash); - _enemyAttackController.DestroyWarningArea(); - // TODO : 4. 공격 판정 발생 - - yield return new WaitForSeconds(1f); - // 5. 애니메이션 트리거 종료 -> 애니메이터 상태 머신으로 처리 - _enemyController.SetState(EnemyState.Trace); + if (_attackTimer >= AttackInterval) + { + _animator.SetTrigger(VertiSlash); + _attackTimer = 0f; + _enemyController.SetState(EnemyState.Trace); + } } public void Exit() { - if (_attackRoutine != null) - { - _enemyController.StopCoroutine(_attackRoutine); - _attackRoutine = null; - } + _enemyController.SetAttackTrigger(false); _animator.SetBool(VertiAttack, false); _animator = null; - _enemyAttackController = null; _enemyController = null; } } \ No newline at end of file diff --git a/Assets/Scripts/Character/Enemy/EnemyState/EnemyStateDead.cs b/Assets/Scripts/Character/Enemy/EnemyState/EnemyStateDead.cs index 158b9eab..7ded15d5 100644 --- a/Assets/Scripts/Character/Enemy/EnemyState/EnemyStateDead.cs +++ b/Assets/Scripts/Character/Enemy/EnemyState/EnemyStateDead.cs @@ -6,6 +6,7 @@ { _enemyController = enemyController; _enemyController.EnemyAnimator.SetTrigger("Dead"); + _enemyController.SetInBattle(false); } public void Update() diff --git a/Assets/Scripts/Character/Enemy/EnemyState/EnemyStateGetHit.cs b/Assets/Scripts/Character/Enemy/EnemyState/EnemyStateGetHit.cs deleted file mode 100644 index b4c44e8a..00000000 --- a/Assets/Scripts/Character/Enemy/EnemyState/EnemyStateGetHit.cs +++ /dev/null @@ -1,19 +0,0 @@ -public class EnemyStateGetHit: IEnemyState -{ - private EnemyController _enemyController; - - public void Enter(EnemyController enemyController) - { - _enemyController = enemyController; - } - - public void Update() - { - - } - - public void Exit() - { - _enemyController = null; - } -} \ No newline at end of file diff --git a/Assets/Scripts/Character/Enemy/EnemyState/EnemyStateGetHit.cs.meta b/Assets/Scripts/Character/Enemy/EnemyState/EnemyStateGetHit.cs.meta deleted file mode 100644 index e0212137..00000000 --- a/Assets/Scripts/Character/Enemy/EnemyState/EnemyStateGetHit.cs.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: 7067b1b0eacf490c863a4cb68c290d3a -timeCreated: 1744799049 \ No newline at end of file diff --git a/Assets/Scripts/Character/Enemy/EnemyState/EnemyStateIdle.cs b/Assets/Scripts/Character/Enemy/EnemyState/EnemyStateIdle.cs index b8714ef6..587c91a5 100644 --- a/Assets/Scripts/Character/Enemy/EnemyState/EnemyStateIdle.cs +++ b/Assets/Scripts/Character/Enemy/EnemyState/EnemyStateIdle.cs @@ -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.EnemyAnimator.SetBool("Idle", true); + _enemyController.SetInBattle(false); } 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; } } \ No newline at end of file diff --git a/Assets/Scripts/Character/Enemy/EnemyState/EnemyStateMove.cs b/Assets/Scripts/Character/Enemy/EnemyState/EnemyStateMove.cs deleted file mode 100644 index e68bdcd3..00000000 --- a/Assets/Scripts/Character/Enemy/EnemyState/EnemyStateMove.cs +++ /dev/null @@ -1,19 +0,0 @@ -public class EnemyStateMove : IEnemyState -{ - private EnemyController _enemyController; - - public void Enter(EnemyController enemyController) - { - _enemyController = enemyController; - } - - public void Update() - { - - } - - public void Exit() - { - _enemyController = null; - } -} \ No newline at end of file diff --git a/Assets/Scripts/Character/Enemy/EnemyState/EnemyStateMove.cs.meta b/Assets/Scripts/Character/Enemy/EnemyState/EnemyStateMove.cs.meta deleted file mode 100644 index 05ec512c..00000000 --- a/Assets/Scripts/Character/Enemy/EnemyState/EnemyStateMove.cs.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: 5abb29c9137942fe95bc66670d8ef521 -timeCreated: 1744799142 \ No newline at end of file diff --git a/Assets/Scripts/Character/Enemy/EnemyState/EnemyStateTrace.cs b/Assets/Scripts/Character/Enemy/EnemyState/EnemyStateTrace.cs index ae814987..e69433c5 100644 --- a/Assets/Scripts/Character/Enemy/EnemyState/EnemyStateTrace.cs +++ b/Assets/Scripts/Character/Enemy/EnemyState/EnemyStateTrace.cs @@ -29,6 +29,7 @@ public class EnemyStateTrace : IEnemyState } _enemyController.EnemyAnimator.SetBool(Trace, true); + _enemyController.SetInBattle(true); } public void Update() diff --git a/Assets/Scripts/Character/Enemy/PldDogController.cs b/Assets/Scripts/Character/Enemy/PldDogController.cs index 1a9eb28d..41b26f51 100644 --- a/Assets/Scripts/Character/Enemy/PldDogController.cs +++ b/Assets/Scripts/Character/Enemy/PldDogController.cs @@ -1,7 +1,90 @@ using System; +using System.Collections; +using Unity.VisualScripting; using UnityEngine; public class PldDogController : EnemyController { + [Header("공격 패턴 관련")] + [SerializeField] private float patternInterval = 3f; + private float _patternTimer = 0f; + private int _currentPatternIndex = 0; + private bool _isPatternRunning = false; + + + [Header("각종 데미지 이펙트 세트")] + [SerializeField] private GameObject chariotSlashWarning; + [SerializeField] private GameObject chariotSlash; + + [Space(10)] + [SerializeField] private GameObject verticalWarning; + [SerializeField] private GameObject verticalSlash; + + [Space(10)] + [SerializeField] private GameObject horizontalWarning; + [SerializeField] private GameObject horizontalSlash; + + // 몬스터의 행동 스크립트 + // IsBoos = 보스몬스터 여부 + // IsInBattle = 전투중인지 여부 + protected override void Awake() + { + base.Awake(); + IsBoss = true; + } + + private void Update() + { + base.Update(); + + if (IsInBattle && !_isPatternRunning && CurrentState == EnemyState.Attack) + { + _patternTimer += Time.deltaTime; + if (_patternTimer >= patternInterval) + { + ExecutePattern(0); + } + } + } + + private void ExecutePattern(int patternIndex) + { + _isPatternRunning = true; + + switch (patternIndex) + { + case 0: + { + ChariotSlashPattern(); + break; + } + case 1: + { + break; + } + case 2: + { + break; + } + } + } + + private void ChariotSlashPattern() + { + Debug.Log("ChariotSlashPattern: 보스가 차지 슬래시를 사용합니다."); + EnemyAnimator.SetBool("VertiAttack", true); + var warning = Instantiate(chariotSlashWarning, transform.position, Quaternion.identity) + .GetComponent(); + + DamageEffectData effectData = new DamageEffectData() + { + damage = (int)attackPower, + radius = 7.5f, + delay = 2.5f, + targetLayer = TargetLayerMask, + explosionEffectPrefab = chariotSlash + }; + warning.SetEffect(effectData, this); + } } From b6e0458350aa6ea3be379a6dea06db3a85feaf31 Mon Sep 17 00:00:00 2001 From: fiore Date: Tue, 22 Apr 2025 18:02:56 +0900 Subject: [PATCH 3/7] =?UTF-8?q?DEG-41=20=EA=B7=BC=EC=A0=91=20=EB=B2=94?= =?UTF-8?q?=EC=9C=84=ED=8C=A8=ED=84=B4,=20=EA=B1=B0=EB=A6=AC=EA=B0=80=20?= =?UTF-8?q?=EB=A9=80=EB=A9=B4=20=EC=9B=90=EA=B1=B0=EB=A6=AC=20=EA=B3=B5?= =?UTF-8?q?=EA=B2=A9=20=ED=8C=A8=ED=84=B4=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Assets/JYY/Animator/PldDogControl.controller | 4 +- Assets/JYY/Scenes/MonsterTest.unity | 4 +- .../Scripts/Character/Enemy/BossPattern.meta | 3 + .../{ => BossPattern}/ChariotAoeController.cs | 18 ++- .../ChariotAoeController.cs.meta | 0 .../Character/Enemy/EnemyController.cs | 29 +--- .../Enemy/EnemyState/EnemyStateAttack.cs | 30 ---- .../Enemy/EnemyState/EnemyStateDead.cs | 1 - .../Enemy/EnemyState/EnemyStateIdle.cs | 6 +- .../Enemy/EnemyState/EnemyStateTrace.cs | 25 +--- .../Character/Enemy/PldDogController.cs | 130 ++++++++++++++++-- 11 files changed, 142 insertions(+), 108 deletions(-) create mode 100644 Assets/Scripts/Character/Enemy/BossPattern.meta rename Assets/Scripts/Character/Enemy/{ => BossPattern}/ChariotAoeController.cs (84%) rename Assets/Scripts/Character/Enemy/{ => BossPattern}/ChariotAoeController.cs.meta (100%) diff --git a/Assets/JYY/Animator/PldDogControl.controller b/Assets/JYY/Animator/PldDogControl.controller index a67e40bf..9d61f13d 100644 --- a/Assets/JYY/Animator/PldDogControl.controller +++ b/Assets/JYY/Animator/PldDogControl.controller @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b9e37c8d0a91f3599d34a7715c632cbcf76fd3c0a96c5d5335ab9d6ff65d3b4c -size 18916 +oid sha256:481922b21d2de476145ad4fefaccad66d344052ffc0a2808e577b717e59be4e9 +size 18696 diff --git a/Assets/JYY/Scenes/MonsterTest.unity b/Assets/JYY/Scenes/MonsterTest.unity index 471eda89..9e0ad0dc 100644 --- a/Assets/JYY/Scenes/MonsterTest.unity +++ b/Assets/JYY/Scenes/MonsterTest.unity @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ccea4dffb67fe759672ab88a8aae903251498785bbe1d83673c2e0a7a89ace8f -size 19724 +oid sha256:6a0de3e23ef1211a5b26d9fb80ba8911d8000a07e40a8b67cf4b33cb106539e6 +size 19722 diff --git a/Assets/Scripts/Character/Enemy/BossPattern.meta b/Assets/Scripts/Character/Enemy/BossPattern.meta new file mode 100644 index 00000000..e375e2dd --- /dev/null +++ b/Assets/Scripts/Character/Enemy/BossPattern.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: d3b800a343fe42afa7494329ef235461 +timeCreated: 1745300808 \ No newline at end of file diff --git a/Assets/Scripts/Character/Enemy/ChariotAoeController.cs b/Assets/Scripts/Character/Enemy/BossPattern/ChariotAoeController.cs similarity index 84% rename from Assets/Scripts/Character/Enemy/ChariotAoeController.cs rename to Assets/Scripts/Character/Enemy/BossPattern/ChariotAoeController.cs index f38a905f..c433f081 100644 --- a/Assets/Scripts/Character/Enemy/ChariotAoeController.cs +++ b/Assets/Scripts/Character/Enemy/BossPattern/ChariotAoeController.cs @@ -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() diff --git a/Assets/Scripts/Character/Enemy/ChariotAoeController.cs.meta b/Assets/Scripts/Character/Enemy/BossPattern/ChariotAoeController.cs.meta similarity index 100% rename from Assets/Scripts/Character/Enemy/ChariotAoeController.cs.meta rename to Assets/Scripts/Character/Enemy/BossPattern/ChariotAoeController.cs.meta diff --git a/Assets/Scripts/Character/Enemy/EnemyController.cs b/Assets/Scripts/Character/Enemy/EnemyController.cs index d93966fa..0cdca95a 100644 --- a/Assets/Scripts/Character/Enemy/EnemyController.cs +++ b/Assets/Scripts/Character/Enemy/EnemyController.cs @@ -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 _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 적 탐지 // 일정 반경에 플레이어가 진입하면 플레이어 소리를 감지했다고 판단 diff --git a/Assets/Scripts/Character/Enemy/EnemyState/EnemyStateAttack.cs b/Assets/Scripts/Character/Enemy/EnemyState/EnemyStateAttack.cs index 1442509b..b102ce4e 100644 --- a/Assets/Scripts/Character/Enemy/EnemyState/EnemyStateAttack.cs +++ b/Assets/Scripts/Character/Enemy/EnemyState/EnemyStateAttack.cs @@ -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; } diff --git a/Assets/Scripts/Character/Enemy/EnemyState/EnemyStateDead.cs b/Assets/Scripts/Character/Enemy/EnemyState/EnemyStateDead.cs index 7ded15d5..158b9eab 100644 --- a/Assets/Scripts/Character/Enemy/EnemyState/EnemyStateDead.cs +++ b/Assets/Scripts/Character/Enemy/EnemyState/EnemyStateDead.cs @@ -6,7 +6,6 @@ { _enemyController = enemyController; _enemyController.EnemyAnimator.SetTrigger("Dead"); - _enemyController.SetInBattle(false); } public void Update() diff --git a/Assets/Scripts/Character/Enemy/EnemyState/EnemyStateIdle.cs b/Assets/Scripts/Character/Enemy/EnemyState/EnemyStateIdle.cs index 587c91a5..b8714ef6 100644 --- a/Assets/Scripts/Character/Enemy/EnemyState/EnemyStateIdle.cs +++ b/Assets/Scripts/Character/Enemy/EnemyState/EnemyStateIdle.cs @@ -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; } } \ No newline at end of file diff --git a/Assets/Scripts/Character/Enemy/EnemyState/EnemyStateTrace.cs b/Assets/Scripts/Character/Enemy/EnemyState/EnemyStateTrace.cs index e69433c5..4d9dce94 100644 --- a/Assets/Scripts/Character/Enemy/EnemyState/EnemyStateTrace.cs +++ b/Assets/Scripts/Character/Enemy/EnemyState/EnemyStateTrace.cs @@ -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); } // 실제 속도 기반으로 애니메이션 제어 diff --git a/Assets/Scripts/Character/Enemy/PldDogController.cs b/Assets/Scripts/Character/Enemy/PldDogController.cs index 41b26f51..6ce9513b 100644 --- a/Assets/Scripts/Character/Enemy/PldDogController.cs +++ b/Assets/Scripts/Character/Enemy/PldDogController.cs @@ -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(); + + 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(); 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; } } From 6f81f0d68b915484e65bcf49aa21898b896acb10 Mon Sep 17 00:00:00 2001 From: fiore Date: Wed, 23 Apr 2025 09:44:17 +0900 Subject: [PATCH 4/7] =?UTF-8?q?DEG-41=20=EC=9B=90=EA=B1=B0=EB=A6=AC=20?= =?UTF-8?q?=EA=B3=B5=EA=B2=A9=EC=9D=84=20=ED=83=80=EA=B2=9F=20=EC=9C=84?= =?UTF-8?q?=EC=B9=98=EC=97=90=20=EB=8D=98=EC=A7=80=EB=8F=84=EB=A1=9D=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Assets/Scripts/Character/Enemy/PldDogController.cs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/Assets/Scripts/Character/Enemy/PldDogController.cs b/Assets/Scripts/Character/Enemy/PldDogController.cs index 6ce9513b..18a1fa0a 100644 --- a/Assets/Scripts/Character/Enemy/PldDogController.cs +++ b/Assets/Scripts/Character/Enemy/PldDogController.cs @@ -115,14 +115,15 @@ public class PldDogController : EnemyController Debug.Log("BombThrowPattern: 보스가 폭탄을 던집니다."); int bombCount = 1; // 한 번에 몇 개 던질지 - float radius = 2f; + float radius = 2f; // 무작위로 던질 경우 범위 for (int i = 0; i < bombCount; i++) { - Vector3 randomPos = TraceTargetTransform.position + (Random.insideUnitSphere * radius); - randomPos.y = 0.1f; // 지면에 맞추기 + // Vector3 randomPos = TraceTargetTransform.position + (Random.insideUnitSphere * radius); + Vector3 targetPos = TraceTargetTransform.position; + targetPos.y = 0.1f; // 지면에 맞추기 - var boomObj = Instantiate(chariotSlashWarning, randomPos, Quaternion.identity); + var boomObj = Instantiate(chariotSlashWarning, targetPos, Quaternion.identity); boomObj.transform.localScale = new Vector3(5f, 5f, 5f); var boom = boomObj.GetComponent(); @@ -135,7 +136,7 @@ public class PldDogController : EnemyController explosionEffectPrefab = chariotSlash }; - boom.SetEffect(effectData,()=>{ }, PatternClear); + boom.SetEffect(effectData, ()=>{ }, PatternClear); } } From 05bdaafce2c7e8224c715f32866808df0dfe8ccf Mon Sep 17 00:00:00 2001 From: fiore Date: Wed, 23 Apr 2025 10:28:52 +0900 Subject: [PATCH 5/7] =?UTF-8?q?DEG-41=20=EC=A3=BC=EC=84=9D=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80=20:=20=EC=9D=B4=ED=9B=84=20=EC=B2=98=EB=A6=AC?= =?UTF-8?q?=ED=95=A0=20=EB=82=B4=EC=9A=A9=20TODO=EB=A1=9C=20=EC=9E=91?= =?UTF-8?q?=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Scripts/Character/Enemy/BossPattern/ChariotAoeController.cs | 2 +- Assets/Scripts/Character/Enemy/PldDogController.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Assets/Scripts/Character/Enemy/BossPattern/ChariotAoeController.cs b/Assets/Scripts/Character/Enemy/BossPattern/ChariotAoeController.cs index c433f081..ed686c4d 100644 --- a/Assets/Scripts/Character/Enemy/BossPattern/ChariotAoeController.cs +++ b/Assets/Scripts/Character/Enemy/BossPattern/ChariotAoeController.cs @@ -4,7 +4,7 @@ using UnityEngine; using UnityEngine.Serialization; -[System.Serializable] +[Serializable] public struct DamageEffectData { public int damage; diff --git a/Assets/Scripts/Character/Enemy/PldDogController.cs b/Assets/Scripts/Character/Enemy/PldDogController.cs index 18a1fa0a..9ca31e90 100644 --- a/Assets/Scripts/Character/Enemy/PldDogController.cs +++ b/Assets/Scripts/Character/Enemy/PldDogController.cs @@ -124,7 +124,7 @@ public class PldDogController : EnemyController targetPos.y = 0.1f; // 지면에 맞추기 var boomObj = Instantiate(chariotSlashWarning, targetPos, Quaternion.identity); - boomObj.transform.localScale = new Vector3(5f, 5f, 5f); + boomObj.transform.localScale = new Vector3(5f, 5f, 5f); // TODO : 하드 코딩됨 | 개선... 해야겠지?? var boom = boomObj.GetComponent(); DamageEffectData effectData = new DamageEffectData() From 9c03bfd00a917a805077652201df3f0e26b8374a Mon Sep 17 00:00:00 2001 From: fiore Date: Thu, 24 Apr 2025 10:40:40 +0900 Subject: [PATCH 6/7] =?UTF-8?q?DEG-41=20DEG-93=20=EA=B3=B5=EA=B2=A9=20?= =?UTF-8?q?=ED=8C=A8=ED=84=B4=20=EB=B0=8F=20=EC=95=A0=EB=8B=88=EB=A9=94?= =?UTF-8?q?=EC=9D=B4=EC=85=98=20=EC=A1=B0=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 부채꼴 가로 베기 - 직선 횡 베기 - 근접 원형 공격 - 원거리 폭탄 --- Assets/JYY/Animator/PldDogControl.controller | 4 +- Assets/JYY/Models.meta | 8 + Assets/JYY/Models/Y Bot.fbx | 3 + Assets/JYY/Models/Y Bot.fbx.meta | 109 ++++++++++ .../JYY/Prefabs/AoE Indicator Chariot.prefab | 4 +- .../Prefabs/AoE Indicator Horizontal.prefab | 3 + ...a => AoE Indicator Horizontal.prefab.meta} | 0 .../JYY/Prefabs/AoE Indicator Vertical.prefab | 3 + ...eta => AoE Indicator Vertical.prefab.meta} | 0 Assets/JYY/Prefabs/Charge slash red.prefab | 3 + .../JYY/Prefabs/Charge slash red.prefab.meta | 7 + Assets/JYY/Prefabs/Explosion.prefab | 3 + Assets/JYY/Prefabs/Explosion.prefab.meta | 7 + .../JYY/Prefabs/Red energy explosion 1.prefab | 3 + .../Red energy explosion 1.prefab.meta | 7 + Assets/JYY/Prefabs/Snow slash 1.prefab | 3 + Assets/JYY/Prefabs/Snow slash 1.prefab.meta | 7 + Assets/JYY/Scenes/MonsterTest.unity | 4 +- .../Enemy/BossPattern/AoeControllerBase.cs | 109 ++++++++++ .../BossPattern/AoeControllerBase.cs.meta | 3 + .../Enemy/BossPattern/BoomAoeController.cs | 4 + .../BossPattern/BoomAoeController.cs.meta | 3 + .../Enemy/BossPattern/ChariotAoeController.cs | 86 +------- .../BossPattern/HorizontalAoeController.cs | 52 +++++ .../HorizontalAoeController.cs.meta | 3 + .../BossPattern/VerticalAoeController.cs | 51 +++++ .../BossPattern/VerticalAoeController.cs.meta | 3 + .../Character/Enemy/EnemyController.cs | 45 ++++- .../Enemy/EnemyState/EnemyStateAttack.cs | 4 +- .../Enemy/EnemyState/EnemyStateDead.cs | 2 +- .../Enemy/EnemyState/EnemyStateIdle.cs | 7 +- .../Enemy/EnemyState/EnemyStateTrace.cs | 34 ++-- .../Character/Enemy/PldDogController.cs | 187 ++++++++++-------- 33 files changed, 576 insertions(+), 195 deletions(-) create mode 100644 Assets/JYY/Models.meta create mode 100644 Assets/JYY/Models/Y Bot.fbx create mode 100644 Assets/JYY/Models/Y Bot.fbx.meta create mode 100644 Assets/JYY/Prefabs/AoE Indicator Horizontal.prefab rename Assets/JYY/Prefabs/{AOEIndicatorHorizontal.prefab.meta => AoE Indicator Horizontal.prefab.meta} (100%) create mode 100644 Assets/JYY/Prefabs/AoE Indicator Vertical.prefab rename Assets/JYY/Prefabs/{AOEIndicatorVertical.prefab.meta => AoE Indicator Vertical.prefab.meta} (100%) create mode 100644 Assets/JYY/Prefabs/Charge slash red.prefab create mode 100644 Assets/JYY/Prefabs/Charge slash red.prefab.meta create mode 100644 Assets/JYY/Prefabs/Explosion.prefab create mode 100644 Assets/JYY/Prefabs/Explosion.prefab.meta create mode 100644 Assets/JYY/Prefabs/Red energy explosion 1.prefab create mode 100644 Assets/JYY/Prefabs/Red energy explosion 1.prefab.meta create mode 100644 Assets/JYY/Prefabs/Snow slash 1.prefab create mode 100644 Assets/JYY/Prefabs/Snow slash 1.prefab.meta create mode 100644 Assets/Scripts/Character/Enemy/BossPattern/AoeControllerBase.cs create mode 100644 Assets/Scripts/Character/Enemy/BossPattern/AoeControllerBase.cs.meta create mode 100644 Assets/Scripts/Character/Enemy/BossPattern/BoomAoeController.cs create mode 100644 Assets/Scripts/Character/Enemy/BossPattern/BoomAoeController.cs.meta create mode 100644 Assets/Scripts/Character/Enemy/BossPattern/HorizontalAoeController.cs create mode 100644 Assets/Scripts/Character/Enemy/BossPattern/HorizontalAoeController.cs.meta create mode 100644 Assets/Scripts/Character/Enemy/BossPattern/VerticalAoeController.cs create mode 100644 Assets/Scripts/Character/Enemy/BossPattern/VerticalAoeController.cs.meta diff --git a/Assets/JYY/Animator/PldDogControl.controller b/Assets/JYY/Animator/PldDogControl.controller index 9d61f13d..7b80e503 100644 --- a/Assets/JYY/Animator/PldDogControl.controller +++ b/Assets/JYY/Animator/PldDogControl.controller @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:481922b21d2de476145ad4fefaccad66d344052ffc0a2808e577b717e59be4e9 -size 18696 +oid sha256:9473c357cb74d4228523205a76d0a1a1cc71d82baf736270906c82a171efe7e6 +size 16154 diff --git a/Assets/JYY/Models.meta b/Assets/JYY/Models.meta new file mode 100644 index 00000000..7143abc3 --- /dev/null +++ b/Assets/JYY/Models.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: ac3af37988877784e91ab90c4ade37d9 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/JYY/Models/Y Bot.fbx b/Assets/JYY/Models/Y Bot.fbx new file mode 100644 index 00000000..a5c4d7be --- /dev/null +++ b/Assets/JYY/Models/Y Bot.fbx @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:470fcb658dd731d414d635615d6232be394e7ea23915fb92ad41a0fca4d592bc +size 1982368 diff --git a/Assets/JYY/Models/Y Bot.fbx.meta b/Assets/JYY/Models/Y Bot.fbx.meta new file mode 100644 index 00000000..2e914645 --- /dev/null +++ b/Assets/JYY/Models/Y Bot.fbx.meta @@ -0,0 +1,109 @@ +fileFormatVersion: 2 +guid: decb96f75d6a2344baa18f902f21a131 +ModelImporter: + serializedVersion: 22200 + internalIDToNameTable: [] + externalObjects: {} + materials: + materialImportMode: 2 + materialName: 0 + materialSearch: 1 + materialLocation: 1 + animations: + legacyGenerateAnimations: 4 + bakeSimulation: 0 + resampleCurves: 1 + optimizeGameObjects: 0 + removeConstantScaleCurves: 0 + motionNodeName: + rigImportErrors: + rigImportWarnings: + animationImportErrors: + animationImportWarnings: + animationRetargetingWarnings: + animationDoRetargetingWarnings: 0 + importAnimatedCustomProperties: 0 + importConstraints: 0 + animationCompression: 3 + animationRotationError: 0.5 + animationPositionError: 0.5 + animationScaleError: 0.5 + animationWrapMode: 0 + extraExposedTransformPaths: [] + extraUserProperties: [] + clipAnimations: [] + isReadable: 0 + meshes: + lODScreenPercentages: [] + globalScale: 1 + meshCompression: 0 + addColliders: 0 + useSRGBMaterialColor: 1 + sortHierarchyByName: 1 + importPhysicalCameras: 1 + importVisibility: 1 + importBlendShapes: 1 + importCameras: 1 + importLights: 1 + nodeNameCollisionStrategy: 1 + fileIdsGeneration: 2 + swapUVChannels: 0 + generateSecondaryUV: 0 + useFileUnits: 1 + keepQuads: 0 + weldVertices: 1 + bakeAxisConversion: 0 + preserveHierarchy: 0 + skinWeightsMode: 0 + maxBonesPerVertex: 4 + minBoneWeight: 0.001 + optimizeBones: 1 + meshOptimizationFlags: -1 + indexFormat: 0 + secondaryUVAngleDistortion: 8 + secondaryUVAreaDistortion: 15.000001 + secondaryUVHardAngle: 88 + secondaryUVMarginMethod: 1 + secondaryUVMinLightmapResolution: 40 + secondaryUVMinObjectScale: 1 + secondaryUVPackMargin: 4 + useFileScale: 1 + strictVertexDataChecks: 0 + tangentSpace: + normalSmoothAngle: 60 + normalImportMode: 0 + tangentImportMode: 3 + normalCalculationMode: 4 + legacyComputeAllNormalsFromSmoothingGroupsWhenMeshHasBlendShapes: 0 + blendShapeNormalImportMode: 1 + normalSmoothingSource: 0 + referencedClips: [] + importAnimation: 1 + humanDescription: + serializedVersion: 3 + human: [] + skeleton: [] + armTwist: 0.5 + foreArmTwist: 0.5 + upperLegTwist: 0.5 + legTwist: 0.5 + armStretch: 0.05 + legStretch: 0.05 + feetSpacing: 0 + globalScale: 1 + rootMotionBoneName: + hasTranslationDoF: 0 + hasExtraRoot: 1 + skeletonHasParents: 1 + lastHumanDescriptionAvatarSource: {instanceID: 0} + autoGenerateAvatarMappingIfUnspecified: 1 + animationType: 3 + humanoidOversampling: 1 + avatarSetup: 1 + addHumanoidExtraRootOnlyWhenUsingAvatar: 1 + importBlendShapeDeformPercent: 1 + remapMaterialsIfMaterialImportModeIsNone: 0 + additionalBone: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/JYY/Prefabs/AoE Indicator Chariot.prefab b/Assets/JYY/Prefabs/AoE Indicator Chariot.prefab index 36214cb6..20a9ce49 100644 --- a/Assets/JYY/Prefabs/AoE Indicator Chariot.prefab +++ b/Assets/JYY/Prefabs/AoE Indicator Chariot.prefab @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:acaadac3ed9caf040e05fc0f05648346d053813c3be9a3062dd7eeed0a8730b6 -size 4760 +oid sha256:da22007db35be49ea0f412048256923f214ff6be182768aba94ea8137146c067 +size 5237 diff --git a/Assets/JYY/Prefabs/AoE Indicator Horizontal.prefab b/Assets/JYY/Prefabs/AoE Indicator Horizontal.prefab new file mode 100644 index 00000000..3b79cddf --- /dev/null +++ b/Assets/JYY/Prefabs/AoE Indicator Horizontal.prefab @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:27404af56e20a87bf6555fc1bbad80f7756f8412d15bccca896ea8c98a221ff7 +size 4474 diff --git a/Assets/JYY/Prefabs/AOEIndicatorHorizontal.prefab.meta b/Assets/JYY/Prefabs/AoE Indicator Horizontal.prefab.meta similarity index 100% rename from Assets/JYY/Prefabs/AOEIndicatorHorizontal.prefab.meta rename to Assets/JYY/Prefabs/AoE Indicator Horizontal.prefab.meta diff --git a/Assets/JYY/Prefabs/AoE Indicator Vertical.prefab b/Assets/JYY/Prefabs/AoE Indicator Vertical.prefab new file mode 100644 index 00000000..438c2522 --- /dev/null +++ b/Assets/JYY/Prefabs/AoE Indicator Vertical.prefab @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e6f2c2d8b80d4562e9a72bfc313a716717ae8bf33192053e85b12aeea9b9b9ff +size 4459 diff --git a/Assets/JYY/Prefabs/AOEIndicatorVertical.prefab.meta b/Assets/JYY/Prefabs/AoE Indicator Vertical.prefab.meta similarity index 100% rename from Assets/JYY/Prefabs/AOEIndicatorVertical.prefab.meta rename to Assets/JYY/Prefabs/AoE Indicator Vertical.prefab.meta diff --git a/Assets/JYY/Prefabs/Charge slash red.prefab b/Assets/JYY/Prefabs/Charge slash red.prefab new file mode 100644 index 00000000..3f562bef --- /dev/null +++ b/Assets/JYY/Prefabs/Charge slash red.prefab @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:401068a261779945bc03fed98b231b07965d7520470f19f5b1ff2b6bf73b4f59 +size 710841 diff --git a/Assets/JYY/Prefabs/Charge slash red.prefab.meta b/Assets/JYY/Prefabs/Charge slash red.prefab.meta new file mode 100644 index 00000000..bf5f20d3 --- /dev/null +++ b/Assets/JYY/Prefabs/Charge slash red.prefab.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 8a0ddc8dd6d760e4e93999c4d49dc16c +PrefabImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/JYY/Prefabs/Explosion.prefab b/Assets/JYY/Prefabs/Explosion.prefab new file mode 100644 index 00000000..780b51ec --- /dev/null +++ b/Assets/JYY/Prefabs/Explosion.prefab @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a95da2a8bdc43724d48bc36adc162d419090185d28b9df881af7de481a53c4f3 +size 473754 diff --git a/Assets/JYY/Prefabs/Explosion.prefab.meta b/Assets/JYY/Prefabs/Explosion.prefab.meta new file mode 100644 index 00000000..5f3ac223 --- /dev/null +++ b/Assets/JYY/Prefabs/Explosion.prefab.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 2ccd5acc2f6d74d4bb687fd2ee94b9de +PrefabImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/JYY/Prefabs/Red energy explosion 1.prefab b/Assets/JYY/Prefabs/Red energy explosion 1.prefab new file mode 100644 index 00000000..39f7c17d --- /dev/null +++ b/Assets/JYY/Prefabs/Red energy explosion 1.prefab @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1364f3853992b0997dcd5fb86204334c243e4b464bf6d96da6374dcb2e98f8d9 +size 1305159 diff --git a/Assets/JYY/Prefabs/Red energy explosion 1.prefab.meta b/Assets/JYY/Prefabs/Red energy explosion 1.prefab.meta new file mode 100644 index 00000000..a8bb01f0 --- /dev/null +++ b/Assets/JYY/Prefabs/Red energy explosion 1.prefab.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 49ada3fea2be23f4a988d4bc21dcaa32 +PrefabImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/JYY/Prefabs/Snow slash 1.prefab b/Assets/JYY/Prefabs/Snow slash 1.prefab new file mode 100644 index 00000000..4b1759bb --- /dev/null +++ b/Assets/JYY/Prefabs/Snow slash 1.prefab @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:72a13e9bb38f18954e603c863b4b610882f8b43d55ba27499daf3bcfe42830b8 +size 474114 diff --git a/Assets/JYY/Prefabs/Snow slash 1.prefab.meta b/Assets/JYY/Prefabs/Snow slash 1.prefab.meta new file mode 100644 index 00000000..a886fdef --- /dev/null +++ b/Assets/JYY/Prefabs/Snow slash 1.prefab.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 03a874e2d684ee04a9729b8363fdbb9c +PrefabImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/JYY/Scenes/MonsterTest.unity b/Assets/JYY/Scenes/MonsterTest.unity index 9e0ad0dc..f315080d 100644 --- a/Assets/JYY/Scenes/MonsterTest.unity +++ b/Assets/JYY/Scenes/MonsterTest.unity @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6a0de3e23ef1211a5b26d9fb80ba8911d8000a07e40a8b67cf4b33cb106539e6 -size 19722 +oid sha256:70e2e15667c9821fdb140d6ca8987d4caf3436e36abc139ba9da1192a5428331 +size 21018 diff --git a/Assets/Scripts/Character/Enemy/BossPattern/AoeControllerBase.cs b/Assets/Scripts/Character/Enemy/BossPattern/AoeControllerBase.cs new file mode 100644 index 00000000..bf689d3f --- /dev/null +++ b/Assets/Scripts/Character/Enemy/BossPattern/AoeControllerBase.cs @@ -0,0 +1,109 @@ +using System; +using System.Collections; +using UnityEngine; + + +[Serializable] +public struct DamageEffectData +{ + public int damage; + public float radius; + public float delay; + public LayerMask targetLayer; + public GameObject explosionEffectPrefab; +} + +/// +/// AOE 범위 공격의 공통 로직을 처리하는 추상 베이스 클래스입니다. +/// +public abstract class AoeControllerBase : MonoBehaviour +{ + [Header("경고 이펙트")] + [SerializeField] protected GameObject warningEffectInstance; + + protected DamageEffectData _data; + private Action _slashAction; + private Action _destroyAction; + + /// + /// 범위 공격 이펙트를 설정하고, 딜레이 후 폭발을 실행합니다. + /// + public void SetEffect(DamageEffectData data, Action slashAction, Action destroyAction) + { + _data = data; + _slashAction = slashAction; + _destroyAction = destroyAction; + + ShowWarningEffect(); + StartCoroutine(ExplodeAfterDelay()); + } + + protected virtual void ShowWarningEffect() + { + if (warningEffectInstance != null) + warningEffectInstance.SetActive(true); + + float diameter = _data.radius * 2f; + transform.localScale = new Vector3(diameter, 1f, diameter); + } + + private IEnumerator ExplodeAfterDelay() + { + yield return new WaitForSeconds(_data.delay); + Explode(); + } + + /// + /// 폭발 이펙트 생성, 데미지 처리, 콜백 호출 순서로 실행합니다. + /// + protected virtual void Explode() + { + // 경고 이펙트 숨기기 + if (warningEffectInstance != null) + warningEffectInstance.SetActive(false); + + ShowDamageEffect(); + + // 슬래시 액션(애니메이션 트리거) 호출 + _slashAction?.Invoke(); + + // 범위 내 데미지 처리 + HitCheck(); + + // 패턴 클리어 콜백 + _destroyAction?.Invoke(); + + // 자기 자신 제거 + Destroy(gameObject, 2f); + } + + protected virtual void HitCheck() + { + var hits = Physics.OverlapSphere(transform.position, _data.radius, _data.targetLayer); + foreach (var hit in hits) + { + if (hit.CompareTag("Player")) + { + Debug.Log($"{hit.name}에게 {_data.damage} 데미지 적용"); + // TODO: 실제 데미지 처리 로직 호출 + } + } + } + + protected virtual void ShowDamageEffect() + { + // 폭발 이펙트 생성 + if (_data.explosionEffectPrefab != null) + { + var effect = Instantiate(_data.explosionEffectPrefab, transform.position, transform.rotation); + effect.transform.localScale = new Vector3(_data.radius, _data.radius, _data.radius); + Destroy(effect, 2f); + } + } + + protected virtual void OnDrawGizmosSelected() + { + Gizmos.color = Color.red; + Gizmos.DrawWireSphere(transform.position, _data.radius); + } +} \ No newline at end of file diff --git a/Assets/Scripts/Character/Enemy/BossPattern/AoeControllerBase.cs.meta b/Assets/Scripts/Character/Enemy/BossPattern/AoeControllerBase.cs.meta new file mode 100644 index 00000000..532cedaa --- /dev/null +++ b/Assets/Scripts/Character/Enemy/BossPattern/AoeControllerBase.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 1dd40dca214a4038be21f64ce645e5d9 +timeCreated: 1745393630 \ No newline at end of file diff --git a/Assets/Scripts/Character/Enemy/BossPattern/BoomAoeController.cs b/Assets/Scripts/Character/Enemy/BossPattern/BoomAoeController.cs new file mode 100644 index 00000000..560b885d --- /dev/null +++ b/Assets/Scripts/Character/Enemy/BossPattern/BoomAoeController.cs @@ -0,0 +1,4 @@ +public class BoomAoeController : AoeControllerBase +{ + +} \ No newline at end of file diff --git a/Assets/Scripts/Character/Enemy/BossPattern/BoomAoeController.cs.meta b/Assets/Scripts/Character/Enemy/BossPattern/BoomAoeController.cs.meta new file mode 100644 index 00000000..8bf641f6 --- /dev/null +++ b/Assets/Scripts/Character/Enemy/BossPattern/BoomAoeController.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: e32c2002701d49df83faa36b3da55436 +timeCreated: 1745395178 \ No newline at end of file diff --git a/Assets/Scripts/Character/Enemy/BossPattern/ChariotAoeController.cs b/Assets/Scripts/Character/Enemy/BossPattern/ChariotAoeController.cs index ed686c4d..e658d92a 100644 --- a/Assets/Scripts/Character/Enemy/BossPattern/ChariotAoeController.cs +++ b/Assets/Scripts/Character/Enemy/BossPattern/ChariotAoeController.cs @@ -1,85 +1,19 @@ using System; -using System.Collections.Generic; +using System.Collections; using UnityEngine; -using UnityEngine.Serialization; -[Serializable] -public struct DamageEffectData + +public class ChariotAoeController : AoeControllerBase { - public int damage; - public float radius; - public float delay; - public LayerMask targetLayer; - - public GameObject explosionEffectPrefab; -} - -public class ChariotAoeController : MonoBehaviour -{ - [SerializeField] private GameObject warningEffectInstance; - - private DamageEffectData _data; - private Action _destroyAction; - private Action _slashAction; - - public void SetEffect(DamageEffectData data, Action slashAction, Action destroyAction) + protected override void ShowDamageEffect() { - _data = data; - _slashAction = slashAction; - _destroyAction = destroyAction; - - ShowWarningEffect(); - Invoke(nameof(Explode), _data.delay); - } - - private void ShowWarningEffect() - { - warningEffectInstance.SetActive(true); - float diameter = _data.radius * 2f; - gameObject.transform.localScale = new Vector3(diameter, 1f, diameter); - } - - private void Explode() - { - var effect = Instantiate(_data.explosionEffectPrefab, transform.position, Quaternion.identity); - - // 공격 전조 제거 - warningEffectInstance.SetActive(false); - - // 공격 애니메이션 실행 - _slashAction.Invoke(); - - effect.transform.localScale = new Vector3(_data.radius, _data.radius, _data.radius); - - // 폭발 반경 내의 모든 콜라이더 가져오기 - Collider[] hitColliders = Physics.OverlapSphere(transform.position, _data.radius, _data.targetLayer); - foreach (Collider hit in hitColliders) + // 폭발 이펙트 생성 + if (_data.explosionEffectPrefab != null) { - if (hit.CompareTag("Player")) - { - // TODO : 데미지 부여 - Debug.Log(hit.name +"에게 공격 적중"); - } + var effect = Instantiate(_data.explosionEffectPrefab, transform.position, transform.rotation); + effect.transform.localScale = new Vector3(2f, 2f, 2f); + Destroy(effect, 2f); } - - Exit(effect); } - - private void Exit(GameObject effect) - { - Destroy(effect, 2f); - Destroy(gameObject, 2f); - } - - private void OnDestroy() - { - _destroyAction.Invoke(); - } - - private void OnDrawGizmosSelected() - { - Gizmos.color = Color.red; - Gizmos.DrawWireSphere(transform.position, _data.radius); - } -} \ No newline at end of file +} diff --git a/Assets/Scripts/Character/Enemy/BossPattern/HorizontalAoeController.cs b/Assets/Scripts/Character/Enemy/BossPattern/HorizontalAoeController.cs new file mode 100644 index 00000000..6ef4c7c0 --- /dev/null +++ b/Assets/Scripts/Character/Enemy/BossPattern/HorizontalAoeController.cs @@ -0,0 +1,52 @@ +using UnityEngine; + +public class HorizontalAoeController : AoeControllerBase +{ + private float slashAngle = 270f; + private int gizmoSegments = 20; + protected override void HitCheck() + { + var hits = Physics.OverlapSphere(transform.position, _data.radius, _data.targetLayer); + foreach (var hit in hits) + { + if (!hit.CompareTag("Player")) continue; + + Vector3 dir = hit.transform.position - transform.position; + dir.y = 0; + float angleToForward = Vector3.Angle(transform.forward, dir); + + if (angleToForward <= slashAngle * 0.5f) + { + Debug.Log($"{hit.name}이(가) 횡적 슬래시 데미지 범위에 있습니다."); + Debug.Log($"{hit.name}에게 {_data.damage} 데미지 적용"); + // TODO: 실제 데미지 처리 로직 호출 + } + } + } + + private void OnDrawGizmosSelected() + { + // 부채꼴 형태 기즈모 드로잉 + Gizmos.color = Color.red; + Vector3 origin = transform.position; + float halfAngle = slashAngle * 0.5f; + float step = slashAngle / gizmoSegments; + + // 시작 포인트 + Vector3 prevDir = Quaternion.AngleAxis(-halfAngle, Vector3.up) * transform.forward; + Vector3 prevPoint = origin + prevDir.normalized * _data.radius; + Gizmos.DrawLine(origin, prevPoint); + + for (int i = 1; i <= gizmoSegments; i++) + { + float currentAngle = -halfAngle + step * i; + Vector3 currDir = Quaternion.AngleAxis(currentAngle, Vector3.up) * transform.forward; + Vector3 currPoint = origin + currDir.normalized * _data.radius; + Gizmos.DrawLine(prevPoint, currPoint); + prevPoint = currPoint; + } + + // 마지막 라인 + Gizmos.DrawLine(origin, prevPoint); + } +} \ No newline at end of file diff --git a/Assets/Scripts/Character/Enemy/BossPattern/HorizontalAoeController.cs.meta b/Assets/Scripts/Character/Enemy/BossPattern/HorizontalAoeController.cs.meta new file mode 100644 index 00000000..0fc4ea79 --- /dev/null +++ b/Assets/Scripts/Character/Enemy/BossPattern/HorizontalAoeController.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: e77da766410d47f9a7effebd30fd33f6 +timeCreated: 1745394588 \ No newline at end of file diff --git a/Assets/Scripts/Character/Enemy/BossPattern/VerticalAoeController.cs b/Assets/Scripts/Character/Enemy/BossPattern/VerticalAoeController.cs new file mode 100644 index 00000000..37b3fbb0 --- /dev/null +++ b/Assets/Scripts/Character/Enemy/BossPattern/VerticalAoeController.cs @@ -0,0 +1,51 @@ +using UnityEngine; + +public class VerticalAoeController : AoeControllerBase +{ + + protected override void ShowWarningEffect() + { + if (warningEffectInstance != null) + warningEffectInstance.SetActive(true); + + var centerCap = Vector3.forward * _data.radius; + float diameter = _data.radius * 2f; + transform.localScale = new Vector3(_data.radius, 1f, diameter); + transform.Translate(centerCap, Space.Self); + } + + protected override void ShowDamageEffect() + { + // 폭발 이펙트 생성 + if (_data.explosionEffectPrefab != null) + { + var effect = Instantiate(_data.explosionEffectPrefab, transform.position, transform.rotation); + effect.transform.localScale = new Vector3(_data.radius, _data.radius, _data.radius); + Destroy(effect, 2f); + } + } + + protected override void HitCheck() + { + // 박스 판정 (사각형 직선) + Vector3 halfExtents = new Vector3(_data.radius, 1f, _data.radius * 2f); + Collider[] hits = Physics.OverlapBox(transform.position, halfExtents, transform.rotation, _data.targetLayer); + + foreach (var hit in hits) + { + if (!hit.CompareTag("Player")) continue; + Debug.Log($"{hit.name} 사각형 범위에 있어 데미지 적용"); + // TODO: 데미지 로직 + } + } + + private void OnDrawGizmosSelected() + { + Gizmos.color = Color.red; + Vector3 center = transform.position; + Vector3 size = new Vector3(_data.radius, 1f, _data.radius * 2f); + Gizmos.matrix = Matrix4x4.TRS(center, transform.rotation, Vector3.one); + Gizmos.DrawWireCube(Vector3.zero, size); + Gizmos.matrix = Matrix4x4.identity; + } +} \ No newline at end of file diff --git a/Assets/Scripts/Character/Enemy/BossPattern/VerticalAoeController.cs.meta b/Assets/Scripts/Character/Enemy/BossPattern/VerticalAoeController.cs.meta new file mode 100644 index 00000000..9fe09225 --- /dev/null +++ b/Assets/Scripts/Character/Enemy/BossPattern/VerticalAoeController.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 8eb40ee5f0d943469026d2b6522dbe46 +timeCreated: 1745393484 \ No newline at end of file diff --git a/Assets/Scripts/Character/Enemy/EnemyController.cs b/Assets/Scripts/Character/Enemy/EnemyController.cs index 0cdca95a..56a57950 100644 --- a/Assets/Scripts/Character/Enemy/EnemyController.cs +++ b/Assets/Scripts/Character/Enemy/EnemyController.cs @@ -18,6 +18,16 @@ public abstract class EnemyController : CharacterBase public EnemyState CurrentState {get; private set;} public LayerMask TargetLayerMask => targetLayerMask; public float MoveSpeed => moveSpeed; + public bool IsMeleeCombat { get; protected set; } + + // ----- + // 애니메이션 관련 + private int _currentAnimationTrigger = -1; + + // 애니메이션 파라미터 해시값 + public static readonly int Idle = Animator.StringToHash("Idle"); + public static readonly int Dead = Animator.StringToHash("Dead"); + public static readonly int Trace = Animator.StringToHash("Trace"); // ----- // 상태 변수 @@ -55,7 +65,7 @@ public abstract class EnemyController : CharacterBase SetState(EnemyState.Idle); } - protected void Update() + protected virtual void Update() { if (CurrentState != EnemyState.None) { @@ -98,5 +108,38 @@ public abstract class EnemyController : CharacterBase #endregion + #region 애니메이션 제어 + + // Trigger + public void SetAnimation(int hashName) + { + if (_currentAnimationTrigger != -1) + { + EnemyAnimator.ResetTrigger(_currentAnimationTrigger); + } + + EnemyAnimator.SetTrigger(hashName); + _currentAnimationTrigger = hashName; + } + + // Bool + public void SetAnimation(int hashName, bool value) + { + EnemyAnimator.SetBool(hashName, value); + } + + // Float + public void SetAnimation(int hashName, float value) + { + EnemyAnimator.SetFloat(hashName, value); + } + + // Integer + public void SetAnimation(int hashName, int value) + { + EnemyAnimator.SetInteger(hashName, value); + } + + #endregion } diff --git a/Assets/Scripts/Character/Enemy/EnemyState/EnemyStateAttack.cs b/Assets/Scripts/Character/Enemy/EnemyState/EnemyStateAttack.cs index b102ce4e..194ce30c 100644 --- a/Assets/Scripts/Character/Enemy/EnemyState/EnemyStateAttack.cs +++ b/Assets/Scripts/Character/Enemy/EnemyState/EnemyStateAttack.cs @@ -5,12 +5,11 @@ using UnityEngine; public class EnemyStateAttack : IEnemyState { private EnemyController _enemyController; - private Animator _animator; + public void Enter(EnemyController enemyController) { _enemyController = enemyController; - _animator = _enemyController.EnemyAnimator; } public void Update() @@ -20,7 +19,6 @@ public class EnemyStateAttack : IEnemyState public void Exit() { - _animator = null; _enemyController = null; } } \ No newline at end of file diff --git a/Assets/Scripts/Character/Enemy/EnemyState/EnemyStateDead.cs b/Assets/Scripts/Character/Enemy/EnemyState/EnemyStateDead.cs index 158b9eab..ba34bb17 100644 --- a/Assets/Scripts/Character/Enemy/EnemyState/EnemyStateDead.cs +++ b/Assets/Scripts/Character/Enemy/EnemyState/EnemyStateDead.cs @@ -5,7 +5,7 @@ public void Enter(EnemyController enemyController) { _enemyController = enemyController; - _enemyController.EnemyAnimator.SetTrigger("Dead"); + _enemyController.SetAnimation(EnemyController.Dead); } public void Update() diff --git a/Assets/Scripts/Character/Enemy/EnemyState/EnemyStateIdle.cs b/Assets/Scripts/Character/Enemy/EnemyState/EnemyStateIdle.cs index b8714ef6..a0fbbc52 100644 --- a/Assets/Scripts/Character/Enemy/EnemyState/EnemyStateIdle.cs +++ b/Assets/Scripts/Character/Enemy/EnemyState/EnemyStateIdle.cs @@ -2,13 +2,14 @@ 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); + Debug.Log("## Idle 상태 진입"); + _enemyController.SetAnimation(EnemyController.Idle, true); } public void Update() @@ -22,7 +23,7 @@ public class EnemyStateIdle: IEnemyState public void Exit() { - _enemyController.EnemyAnimator.SetBool(Idle, false); + _enemyController.SetAnimation(EnemyController.Idle, false); _enemyController = null; } } \ No newline at end of file diff --git a/Assets/Scripts/Character/Enemy/EnemyState/EnemyStateTrace.cs b/Assets/Scripts/Character/Enemy/EnemyState/EnemyStateTrace.cs index 4d9dce94..b301d19a 100644 --- a/Assets/Scripts/Character/Enemy/EnemyState/EnemyStateTrace.cs +++ b/Assets/Scripts/Character/Enemy/EnemyState/EnemyStateTrace.cs @@ -2,9 +2,6 @@ public class EnemyStateTrace : IEnemyState { - private static readonly int MoveSpeed = Animator.StringToHash("MoveSpeed"); - private static readonly int Trace = Animator.StringToHash("Trace"); - private EnemyController _enemyController; private Transform _detectPlayerTransform; @@ -14,7 +11,7 @@ public class EnemyStateTrace : IEnemyState public void Enter(EnemyController enemyController) { _enemyController = enemyController; - + Debug.Log("## Trace 상태 진입"); _detectPlayerTransform = _enemyController.TraceTargetTransform; if (!_detectPlayerTransform) { @@ -28,25 +25,31 @@ public class EnemyStateTrace : IEnemyState _enemyController.Agent.SetDestination(_detectPlayerTransform.position); } - _enemyController.EnemyAnimator.SetBool(Trace, true); + _enemyController.SetAnimation(EnemyController.Trace, true); } public void Update() { + if(_enemyController.IsMeleeCombat) return; if (_enemyController.Agent.enabled != true) return; - // 일정 주기로 찾은 플레이어의 위치를 갱신해서 갱신된 위치로 이동 - FindTargetPosition(); - PlayerTracking(); if (_enemyController.Agent.remainingDistance <= _enemyController.Agent.stoppingDistance) { // TODO: 타겟에 도착함 -> 공격 준비 - _enemyController.SetState(EnemyState.Attack); + // _enemyController.SetState(EnemyState.Attack); } } + public void Exit() + { + _detectPlayerTransform = null; + _enemyController.SetAnimation(EnemyController.Trace, false); + _enemyController = null; + } + + // 일정 주기로 찾은 플레이어의 위치를 갱신해서 갱신된 위치로 이동 private void FindTargetPosition() { if (_detectPlayerInCircleWaitTime > MaxDetectPlayerInCircleWaitTime) @@ -68,6 +71,8 @@ public class EnemyStateTrace : IEnemyState // 플레이어를 추적하는 속도를 제어하는 함수 private void PlayerTracking() { + FindTargetPosition(); + float distance = (_detectPlayerTransform.position - _enemyController.transform.position).magnitude; if (distance > 2f) @@ -97,17 +102,6 @@ public class EnemyStateTrace : IEnemyState ); } } - - // 실제 속도 기반으로 애니메이션 제어 - float currentSpeed = _enemyController.Agent.velocity.magnitude; - _enemyController.EnemyAnimator.SetFloat(MoveSpeed, currentSpeed); - } - - public void Exit() - { - _detectPlayerTransform = null; - _enemyController.EnemyAnimator.SetBool(Trace, false); - _enemyController = null; } } diff --git a/Assets/Scripts/Character/Enemy/PldDogController.cs b/Assets/Scripts/Character/Enemy/PldDogController.cs index 9ca31e90..2655b9e8 100644 --- a/Assets/Scripts/Character/Enemy/PldDogController.cs +++ b/Assets/Scripts/Character/Enemy/PldDogController.cs @@ -1,24 +1,30 @@ using System; using System.Collections; +using System.Collections.Generic; 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 VertiSlash = Animator.StringToHash("VertiSlash"); + 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; - private float _patternTimer = 0f; - private int _currentPatternIndex = 0; - private bool _isPatternRunning = false; + [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; @@ -28,127 +34,109 @@ public class PldDogController : EnemyController [SerializeField] private GameObject horizontalWarning; [SerializeField] private GameObject horizontalSlash; - private bool _isInTrace; - private bool _isInAttack; + private float _patternTimer = 0f; + private int _currentPatternIndex = 0; + private bool _isPatternRunning = false; private bool _isFirstAttack = true; - private void Update() + private List _patternActions; + + protected override void Awake() + { + base.Awake(); + + _patternActions = new List + { + ChariotSlashPattern, + VerticalSlashPattern, + HorizontalSlashPattern + }; + } + + protected override void Update() { base.Update(); - CheckIsInBattle(); + if (CurrentState != EnemyState.Trace || _isPatternRunning) + return; - if (_isInAttack) + float distanceToPlayer = Vector3.Distance(transform.position, TraceTargetTransform.position); + + if (distanceToPlayer <= meleeRange) // 근접 범위 { + if (!Agent.isStopped) Agent.isStopped = true; _patternTimer += Time.deltaTime; if (!_isPatternRunning && (_isFirstAttack || _patternTimer >= patternInterval)) { - Agent.enabled = false; - - // TODO: 순서대로 패턴 실행 ExecutePattern(_currentPatternIndex); - // _currentPatternIndex = (_currentPatternIndex + 1) % 3; // 패턴 순환 - _isFirstAttack = false; } } - - if (_isInTrace) + else { + if (Agent.isStopped) Agent.isStopped = false; + Agent.SetDestination(TraceTargetTransform.position); _patternTimer += Time.deltaTime; if (!_isPatternRunning && _patternTimer >= patternInterval) { - _isPatternRunning = true; - - float distanceToPlayer = Vector3.Distance(transform.position, TraceTargetTransform.position); - - if (distanceToPlayer > 3f) - { - BombThrowPattern(); - } + 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) { _isPatternRunning = true; + Agent.isStopped = true; + IsMeleeCombat = true; - switch (patternIndex) - { - case 0: - { - ChariotSlashPattern(); - break; - } - case 1: - { - break; - } - case 2: - { - break; - } - } + _patternActions[_currentPatternIndex]?.Invoke(); + + _currentPatternIndex = (_currentPatternIndex + 1) % _patternActions.Count; // 패턴 순환 } + // 순환 패턴과 별개로 동작하는 특수 패턴 private void BombThrowPattern() { Debug.Log("BombThrowPattern: 보스가 폭탄을 던집니다."); - - int bombCount = 1; // 한 번에 몇 개 던질지 - float radius = 2f; // 무작위로 던질 경우 범위 + SetAnimation(BoomShot); + _isPatternRunning = true; + Agent.isStopped = true; for (int i = 0; i < bombCount; i++) { - // Vector3 randomPos = TraceTargetTransform.position + (Random.insideUnitSphere * radius); Vector3 targetPos = TraceTargetTransform.position; - targetPos.y = 0.1f; // 지면에 맞추기 + targetPos.y = 0.1f; // 지면에 맞춤 - var boomObj = Instantiate(chariotSlashWarning, targetPos, Quaternion.identity); - boomObj.transform.localScale = new Vector3(5f, 5f, 5f); // TODO : 하드 코딩됨 | 개선... 해야겠지?? - var boom = boomObj.GetComponent(); + var warning = Instantiate(chariotSlashWarning, targetPos, Quaternion.identity); + warning.transform.localScale = bombScale; + var aoe = warning.GetComponent(); - DamageEffectData effectData = new DamageEffectData() + var effectData = new DamageEffectData { damage = (int)attackPower, - radius = 5f, - delay = 1.5f, + radius = bombScale.x, + delay = bombTriggerDelay, targetLayer = TargetLayerMask, - explosionEffectPrefab = chariotSlash + explosionEffectPrefab = boomExplosion }; - boom.SetEffect(effectData, ()=>{ }, PatternClear); + aoe.SetEffect(effectData, null, PatternClear); } } private void ChariotSlashPattern() { Debug.Log("ChariotSlashPattern: 보스가 차지 슬래시를 사용합니다."); - WindUpAnimationStart(); + WindUpAnimation(); - var slash = Instantiate(chariotSlashWarning, transform.position, Quaternion.identity) + var warning = Instantiate(chariotSlashWarning, transform.position, Quaternion.identity) .GetComponent(); - DamageEffectData effectData = new DamageEffectData() + var effectData = new DamageEffectData { damage = (int)attackPower, radius = 7.5f, @@ -157,35 +145,64 @@ public class PldDogController : EnemyController explosionEffectPrefab = chariotSlash }; - slash.SetEffect(effectData, SlashAnimationPlay, - () => - { - PatternClear(); - WindUpAnimationEnd(); - SetState(EnemyState.Trace); - } - ); + warning.SetEffect(effectData, SlashAnimationPlay, PatternClear); } - private void WindUpAnimationStart() + private void VerticalSlashPattern() { - EnemyAnimator.SetBool(WindUp, true); + Debug.Log("VerticalSlashPattern: 보스가 수직 슬래시를 사용합니다."); + WindUpAnimation(); + + var warning = Instantiate(verticalWarning, transform.position, transform.rotation) + .GetComponent(); + + var effectData = new DamageEffectData + { + damage = (int)attackPower, + radius = 5f, + delay = 2f, + targetLayer = TargetLayerMask, + explosionEffectPrefab = verticalSlash + }; + + warning.SetEffect(effectData, SlashAnimationPlay, PatternClear); } - private void WindUpAnimationEnd() + private void HorizontalSlashPattern() { - EnemyAnimator.SetBool(WindUp, false); + Debug.Log("HorizontalSlashPattern: 보스가 횡적 슬래시를 사용합니다."); + WindUpAnimation(); + + var warning = Instantiate(horizontalWarning, transform.position, transform.rotation) + .GetComponent(); + + 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() { - EnemyAnimator.SetTrigger(VertiSlash); + SetAnimation(Slash); } private void PatternClear() { _isPatternRunning = false; + IsMeleeCombat = false; _patternTimer = 0f; - Agent.enabled = true; + Agent.isStopped = false; } } From 503c576bf05b9c017cba7fe8f7b6da46b58d2d0d Mon Sep 17 00:00:00 2001 From: fiore Date: Thu, 24 Apr 2025 13:05:31 +0900 Subject: [PATCH 7/7] =?UTF-8?q?DEG-41=20=EB=A9=94=ED=83=80=ED=8C=8C?= =?UTF-8?q?=EC=9D=BC=20=EC=B6=94=EA=B0=80=EB=90=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Assets/JYY/Prefabs/AOEIndicatorHorizontal.prefab.meta | 7 +++++++ Assets/JYY/Prefabs/AOEIndicatorVertical.prefab.meta | 7 +++++++ 2 files changed, 14 insertions(+) create mode 100644 Assets/JYY/Prefabs/AOEIndicatorHorizontal.prefab.meta create mode 100644 Assets/JYY/Prefabs/AOEIndicatorVertical.prefab.meta diff --git a/Assets/JYY/Prefabs/AOEIndicatorHorizontal.prefab.meta b/Assets/JYY/Prefabs/AOEIndicatorHorizontal.prefab.meta new file mode 100644 index 00000000..49096c4a --- /dev/null +++ b/Assets/JYY/Prefabs/AOEIndicatorHorizontal.prefab.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 0e60f1766f73dbc439ff69a154cc9a99 +PrefabImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/JYY/Prefabs/AOEIndicatorVertical.prefab.meta b/Assets/JYY/Prefabs/AOEIndicatorVertical.prefab.meta new file mode 100644 index 00000000..877a5f21 --- /dev/null +++ b/Assets/JYY/Prefabs/AOEIndicatorVertical.prefab.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: dc0537feab3e2944aa554e23fb3923a3 +PrefabImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: