From 2a033581a099ff081e7387c74cffc37f95d4c6a0 Mon Sep 17 00:00:00 2001 From: hydrozen Date: Sat, 21 Feb 2026 03:19:49 +0900 Subject: [PATCH] =?UTF-8?q?=EB=AA=AC=EC=8A=A4=ED=84=B0=20=EC=95=A0?= =?UTF-8?q?=EB=8B=88=EB=A9=94=EC=9D=B4=EC=85=98=20=EC=97=B0=EB=8F=99=20?= =?UTF-8?q?=EB=B2=84=EA=B7=B8=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .plastic/plastic.changes | Bin 0 -> 2551 bytes .plastic/plastic.wktree | Bin 1893986 -> 1894189 bytes Assets/0.SCENE/MainGame.unity | 13658 +++---- .../MyMonster/KamikazeMonster.prefab | 13 +- .../1.myPrefab/MyMonster/SwordMonster.prefab | 12 +- .../1.myPrefab/MyMonster/ThrowMonster.prefab | 3 +- .../BossAnimation'/scavenger_run.anim | 1174 +- .../Animations/Walk.anim | 29360 ++++++++++++++++ .../Animations/Walk.anim.meta | 8 + .../ghoul_animator_controller.controller | 58 +- Assets/Scripts/Enemy/AI/ExplodeMonster.cs | 11 +- Assets/Scripts/Enemy/AI/MonsterClass.cs | 29 +- Assets/Scripts/Enemy/AI/NormalMonster.cs | 11 +- Assets/Scripts/Enemy/AI/Range Monster.cs | 5 + 14 files changed, 35195 insertions(+), 9147 deletions(-) create mode 100644 .plastic/plastic.changes create mode 100644 Assets/Animation_human/2 Handed Warrior Mecanim Animation Pack/Animations/Walk.anim create mode 100644 Assets/Animation_human/2 Handed Warrior Mecanim Animation Pack/Animations/Walk.anim.meta diff --git a/.plastic/plastic.changes b/.plastic/plastic.changes new file mode 100644 index 0000000000000000000000000000000000000000..713db5819ca3f1fe238fb69bcbe68be2c26f7b66 GIT binary patch literal 2551 zcmbVOO^@3|7R6!j^@7d*^2 z_Ez_oR#%F8*}hwEaUgf>H^HTFG@tdVW-)uJhnadGiF9@}x_{sP9^XFv<>m($lV7jn z#{mB9s=b5H<6sLN@Z zgtSlt@EoQTa(RUqj+e>ub}gQGXnp_Rw7R|cayjfw+c1AL)Aff4DS-AhZ8uj*F5~ltmsCD@>tm7^Y7>h^uzHoFYev0#3?-z{-gvbb$XN z0Ui#p6i$&B0qk$nea1bzyFFd6i z`x#nu4ZU1ulp&pv#zIkyHKD+u(s}X3M?jM7Ze!6vP&a_K2K>kaoO;{R#7WKFzlp9b zR*+R%>2bGmGLz#idJ3YMcwa_-o+0bpZiyN)ZS2V8O7580q-U+{)DXVoL*aL)xdd5R zk0$e#qjs-4AM!c}3Z2#hQ~2jwtEz$Z7D86L&6-FPd?`Q=1;vlTqo&1;3J%f|V5dD+ zA0_HlGb~LE7G^Mo{l`8O?$kI{lDQ@DWx;q@yzj^2M^}j4@$`HWFZQKllx?*^y(XYO zjZN^=Cl=2QA#SB24as`ErM;a&VLTA<7VkH804GjVY$xJ3q}UDLvGt?vR@L>OgW%6U>=ZT<$&QNXaM1W z1)2ohR*u>H>|t}^R|Se)B}h@hVd9wYrcUCe_J|)b^>RNJJI`-pb8W?j2xy;NA9>D? zCw|U<)dh_iAej}SwUbIS)tgsjaZ*#ami`4N7f#^r)XKtXK93Krc%$UET;vks*&1y| z6YW_gFJ#8)*?ckHmhPJ)BK{dUx;O)AXFP(2h7<*8`0teS=%|7B$mge5IW^w(;q;qp fh($wJy1c;Gnv=BHf^@-5nNi%0et6xQx?#g-wmX-D literal 0 HcmV?d00001 diff --git a/.plastic/plastic.wktree b/.plastic/plastic.wktree index e3c7a6318db7233047cf266aca2c0b4aaa437ca1..0e6f65a0e8dee9084a64aa8463be9800e18f07dc 100644 GIT binary patch delta 499 zcmaEKrg-hS;)WK+Elk119RHzUdUP?90yASk#P+&krfX6N@t8i4cwWTz`aUK#Muhm< zevo)U#P$pQOv0-W;;${46}T8*Mle9Y^aGa6iqkdza*AyCvSOaCi%|GBof&Arh&Am#vKP9Ww2Vs0Sj0b*Vt<^y7WAQk{(K_C_aVqqW_0b)@g76W2& zAeI1PNg$R2V(IMy88REf1Yw>nSL6b_j&=IMtJ30}jBNQ($9~)=V>InLH_LYQ{W2{~ z^_<~}IoW!Nd6~H|oeT^x7R-#VPyuGBhhg%JFa}f{NHHRqU}HdBKDZTnxv3?I2u(ni V6PO3H=nGViB#X8$JScNe1pv(m*#-ar delta 294 zcmZ2`uK3ZJ;)WK+Elk11903swU@$$pm`Q<|;ULrYx?-klQXF|O@t8i4`0}9b^?gig zj2s0p@wNRR@n=liFZ44Bui|(K6Mt>VtT27UIce_c2SF^2znmi5y{wpL>vBwvf?D-9 zof)Y0VNkn31~U+|05K~NvjH(X5OV-AClGT1F*gwN05LBR^8qnG5DNgYAP@@yu`m#e z0I?_#ivh7X5K92DBoIphvGjI<44DmKf^7K^yUP{1zzo*u2d_#iP5-=4#$b9uhX~7d V_5Cs}Ow)7aSOm7W9g [SerializeField] private bool showExplodeDebugLog = true; // 변수를 선언할거에요 -> 디버그 로그 on/off를 private bool hasExploded = false; // 변수를 선언할거에요 -> 폭발 완료 여부를 + private string _lastLoggedState = ""; // 변수를 선언할거에요 -> 직전 로그 State 이름을 // ───────────────────────────────────────────────────────── // AI 로직 @@ -38,8 +39,7 @@ public class ExplodeMonster : MonsterClass // 클래스를 선언할거에요 -> StartCoroutine(ExplodeRoutine()); // 실행할거에요 -> 자폭 코루틴을 else // 조건이 틀리면 실행할거에요 -> 멀면 ChasePlayer(); // 실행할거에요 -> 추격을 - } - private string _lastLoggedState = ""; // 변수를 선언할거에요 -> 직전 로그 State 이름을 + } // ───────────────────────────────────────────────────────── // 초기화 @@ -115,6 +115,11 @@ public class ExplodeMonster : MonsterClass // 클래스를 선언할거에요 -> } } + // ───────────────────────────────────────────────────────── + // 추격 + // ───────────────────────────────────────────────────────── + + private void ChasePlayer() // ← 빠져있던 메서드 선언부 복원 { if (agent != null && agent.isOnNavMesh) // 조건이 맞으면 실행할거에요 -> 에이전트가 정상이면 { @@ -126,7 +131,7 @@ public class ExplodeMonster : MonsterClass // 클래스를 선언할거에요 -> if (!animator.GetCurrentAnimatorStateInfo(0).IsName(runAnim)) // 조건이 맞으면 실행할거에요 -> 달리기 State가 아니면 animator.Play(runAnim, 0, 0f); // 재생할거에요 -> 달리기 애니를 - } + } // ───────────────────────────────────────────────────────── // 자폭 코루틴 diff --git a/Assets/Scripts/Enemy/AI/MonsterClass.cs b/Assets/Scripts/Enemy/AI/MonsterClass.cs index c4ddf7b6..9405ffb5 100644 --- a/Assets/Scripts/Enemy/AI/MonsterClass.cs +++ b/Assets/Scripts/Enemy/AI/MonsterClass.cs @@ -65,6 +65,15 @@ public abstract class MonsterClass : MonoBehaviour, IDamageable // 추상 클래 protected virtual void Awake() // 함수를 실행할거에요 -> 컴포넌트 캐싱을 { + animator = GetComponent(); // 가져올거에요 -> 애니메이터를 + agent = GetComponent(); // 가져올거에요 -> 에이전트를 + audioSource = GetComponent(); // 가져올거에요 -> 오디오 소스를 + mobRenderer = GetComponentInChildren(); // 가져올거에요 -> 렌더러를 + // statusProcessor = GetComponent(); // 가져올거에요 -> 상태이상 처리기를 + + if (agent != null) agent.speed = moveSpeed; // 설정할거에요 -> 이동 속도를 + + Init(); // 실행할거에요 -> 자식 클래스 추가 초기화를 } protected virtual void OnEnable() // 함수를 실행할거에요 -> 활성화/스폰될 때마다 @@ -77,8 +86,6 @@ public abstract class MonsterClass : MonoBehaviour, IDamageable // 추상 클래 protected virtual void Init() { } // 가상 함수를 선언할거에요 -> 자식 클래스 전용 추가 초기화를 - protected virtual void Init() { } // 비워둘거에요 -> MobUpdateManager가 OnManagedUpdate를 담당하니까 - protected virtual void OnDisable() // 함수를 실행할거에요 -> 비활성화 시 { if (MobUpdateManager.Instance != null) MobUpdateManager.Instance.UnregisterMob(this); // 해제할거에요 -> 매니저에서 @@ -122,8 +129,9 @@ public abstract class MonsterClass : MonoBehaviour, IDamageable // 추상 클래 agent.isStopped = false; // 재개할거에요 -> 이동을 if (IsAggroed && playerTransform != null) agent.SetDestination(playerTransform.position); // 이동할거에요 -> 플레이어에게 - } } + } + protected abstract void ExecuteAILogic(); // 추상 함수를 선언할거에요 -> 자식이 반드시 구현해야 하는 AI를 protected virtual void OnResetStats() { } // 가상 함수를 선언할거에요 -> 자식 클래스 추가 리셋을 @@ -179,6 +187,7 @@ public abstract class MonsterClass : MonoBehaviour, IDamageable // 추상 클래 if (!animator.GetCurrentAnimatorStateInfo(0).IsName(Monster_Idle)) animator.Play(Monster_Idle, 0, 0f); // 재생할거에요 -> 대기 애니를 } + } // ← 빠져있던 닫는 중괄호 복원 // ───────────────────────────────────────────────────────── // 피격 처리 @@ -199,10 +208,10 @@ public abstract class MonsterClass : MonoBehaviour, IDamageable // 추상 클래 OnHealthChanged?.Invoke(currentHP, maxHP); // 알릴거에요 -> UI에 체력 변경을 if (currentHP <= 0) // 조건이 맞으면 실행할거에요 -> 체력이 바닥났으면 - { + { Die(); // 실행할거에요 -> 사망 처리를 return; - } + } if (!isHit) // 조건이 맞으면 실행할거에요 -> 아직 피격 상태가 아니면 StartHit(); // 실행할거에요 -> 피격 처리를 @@ -216,6 +225,7 @@ public abstract class MonsterClass : MonoBehaviour, IDamageable // 추상 클래 OnHealthChanged?.Invoke(currentHP, maxHP); // 알릴거에요 -> UI에 } + private void StartHit() // ← 빠져있던 메서드 선언부 복원 { isHit = true; // 설정할거에요 -> 피격 상태를 isAttacking = false; // 해제할거에요 -> 공격 상태를 @@ -271,6 +281,7 @@ public abstract class MonsterClass : MonoBehaviour, IDamageable // 추상 클래 if (myWeapon != null) myWeapon.DisableHitBox(); // 끌거에요 -> 무기 판정을 } + public virtual void OnHitEnd() // ← 빠져있던 메서드 선언부 복원 { isHit = false; // 해제할거에요 -> 피격 상태를 _hitCoroutine = null; // 초기화할거에요 -> 코루틴 핸들을 @@ -321,16 +332,20 @@ public abstract class MonsterClass : MonoBehaviour, IDamageable // 추상 클래 isAttacking = true; // 설정할거에요 -> 공격 중으로 isResting = false; // 해제할거에요 -> 휴식 상태를 if (myWeapon != null) myWeapon.EnableHitBox(); // 켤거에요 -> 무기 판정을 - } + } + public virtual void OnAttackEnd() // ← 빠져있던 메서드 선언부 복원 { if (myWeapon != null) myWeapon.DisableHitBox(); // 끌거에요 -> 무기 판정을 isAttacking = false; // 해제할거에요 -> 공격 상태를 if (!isDead && !isHit) StartCoroutine(RestAfterAttack()); // 시작할거에요 -> 공격 후 휴식을 - } + } protected virtual IEnumerator RestAfterAttack() // 코루틴을 선언할거에요 -> 공격 후 휴식 로직을 { + isResting = true; // 설정할거에요 -> 휴식 상태를 + yield return new WaitForSeconds(attackRestDuration); // 기다릴거에요 -> 휴식 시간만큼 + isResting = false; // 해제할거에요 -> 휴식 상태를 } // ───────────────────────────────────────────────────────── diff --git a/Assets/Scripts/Enemy/AI/NormalMonster.cs b/Assets/Scripts/Enemy/AI/NormalMonster.cs index 75c04c1c..4a4b675a 100644 --- a/Assets/Scripts/Enemy/AI/NormalMonster.cs +++ b/Assets/Scripts/Enemy/AI/NormalMonster.cs @@ -58,12 +58,21 @@ public class MeleeMonster : MonsterClass // 클래스를 선언할거에요 -> } } + private void TryAttack() // ← 빠져있던 메서드 선언부 복원 { + if (Time.time - lastAttackTime < attackDelay) return; // 중단할거에요 -> 딜레이 안 지났으면 + lastAttackTime = Time.time; // 갱신할거에요 -> 마지막 공격 시간을 + + if (agent.isOnNavMesh) { agent.isStopped = true; agent.velocity = Vector3.zero; } // 멈출거에요 -> 이동을 + + Vector3 dir = (playerTransform.position - transform.position).normalized; // 계산할거에요 -> 방향을 + dir.y = 0; // 수평으로 보정할거에요 + transform.rotation = Quaternion.LookRotation(dir); // 회전할거에요 -> 플레이어를 바라보게 string animName = attackAnimations[attackIndex]; // 가져올거에요 -> 애니 이름을 attackIndex = (attackIndex + 1) % attackAnimations.Length; // 갱신할거에요 -> 인덱스를 animator.Play(animName, 0, 0f); // 재생할거에요 -> 공격 애니를 (레이어 0 명시) - } + } protected override void OnDie() // 함수를 실행할거에요 -> 사망 시 { diff --git a/Assets/Scripts/Enemy/AI/Range Monster.cs b/Assets/Scripts/Enemy/AI/Range Monster.cs index 49185ece..1d0b1511 100644 --- a/Assets/Scripts/Enemy/AI/Range Monster.cs +++ b/Assets/Scripts/Enemy/AI/Range Monster.cs @@ -41,7 +41,12 @@ public class UniversalRangedMonster : MonsterClass // 클래스를 선언할거 } } + private void TryAttack() // ← 빠져있던 메서드 선언부 복원 { + if (Time.time - lastAttackTime < attackDelay) return; // 중단할거에요 -> 딜레이 안 지났으면 + lastAttackTime = Time.time; // 갱신할거에요 -> 마지막 공격 시간을 + + if (agent.isOnNavMesh) { agent.isStopped = true; agent.velocity = Vector3.zero; } // 멈출거에요 -> 이동을 Vector3 dir = (playerTransform.position - transform.position).normalized; dir.y = 0; // 계산할거에요 -> 방향을 transform.rotation = Quaternion.LookRotation(dir); // 회전할거에요 -> 방향대로