몬스터 애니메이션 연동 버그 수정

This commit is contained in:
윤기주_playm 2026-02-21 03:19:49 +09:00
parent 9d2873644b
commit 2a033581a0
14 changed files with 35195 additions and 9147 deletions

BIN
.plastic/plastic.changes Normal file

Binary file not shown.

Binary file not shown.

File diff suppressed because it is too large Load Diff

View File

@ -903,6 +903,10 @@ PrefabInstance:
propertyPath: m_LocalEulerAnglesHint.z
value: 0
objectReference: {fileID: 0}
- target: {fileID: 9500000, guid: 74236a73e891a4540a264993ac8d337b, type: 3}
propertyPath: m_Avatar
value:
objectReference: {fileID: 9000000, guid: 62d084832da52460c8e4037dbeb673a9, type: 3}
- target: {fileID: 9500000, guid: 74236a73e891a4540a264993ac8d337b, type: 3}
propertyPath: m_Controller
value:
@ -992,9 +996,9 @@ MonoBehaviour:
expReward: 10
moveSpeed: 3.5
myWeapon: {fileID: 0}
Monster_Idle: scavenger_idle
Monster_GetDamage: scavenger_damage
Monster_Die: scavenger_die
Monster_Idle: 'scavenger_idle '
Monster_GetDamage: 'scavenger_damage '
Monster_Die: 'scavenger_die '
hitRecoverFallback: 1
attackRestDuration: 1.5
detectionRange: 10
@ -1012,8 +1016,9 @@ MonoBehaviour:
fuseEffect: {fileID: 0}
fuseSound: {fileID: 0}
explosionSound: {fileID: 0}
runAnim: scavenger_run
runAnim: 'scavenger_run '
fuseAnim: scavenger_Fuse
showExplodeDebugLog: 1
--- !u!136 &4824808582826185509
CapsuleCollider:
m_ObjectHideFlags: 0

View File

@ -1388,9 +1388,7 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: 9eb5b341f7503494e9b0f88cc4b1c17d, type: 3}
m_Name:
m_EditorClassIdentifier:
healthSource: {fileID: 1727176290165168055}
hpFillImage: {fileID: 197665650599347112}
hpText: {fileID: 6986518538193087157}
targetObject: {fileID: 0}
--- !u!1 &3511228176158128295
GameObject:
m_ObjectHideFlags: 0
@ -1989,7 +1987,7 @@ MonoBehaviour:
m_Name:
m_EditorClassIdentifier:
optimizationDistance: 40
maxHP: 150
maxHP: 100
attackDamage: 20
expReward: 8
moveSpeed: 3.5
@ -1997,7 +1995,10 @@ MonoBehaviour:
Monster_Idle: ghoul_idle
Monster_GetDamage: ghoul_gethit
Monster_Die: ghoul_die
hitRecoverFallback: 1
attackRestDuration: 1.5
detectionRange: 10
showDebugGizmos: 0
hitSound: {fileID: 0}
deathSound: {fileID: 0}
deathEffectPrefab: {fileID: 0}
@ -2013,9 +2014,6 @@ MonoBehaviour:
attackAnimations:
- ghoul_attack
Monster_Walk: ghoul_walk
stopBuffer: 0.3
patrolRadius: 5
patrolInterval: 2
--- !u!195 &8274003280596335008
NavMeshAgent:
m_ObjectHideFlags: 0

View File

@ -1544,7 +1544,7 @@ MonoBehaviour:
m_Name:
m_EditorClassIdentifier:
optimizationDistance: 40
maxHP: 300
maxHP: 100
attackDamage: 10
expReward: 10
moveSpeed: 3.5
@ -1552,6 +1552,7 @@ MonoBehaviour:
Monster_Idle: Monster_Idle
Monster_GetDamage: Monster_GetDamage
Monster_Die: Monster_Die
hitRecoverFallback: 1
attackRestDuration: 1.5
detectionRange: 10
showDebugGizmos: 1

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 7cea8855ca3183f4abf3654fdff23011
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 7400000
userData:
assetBundleName:
assetBundleVariant:

View File

@ -171,12 +171,12 @@ AnimatorStateMachine:
- serializedVersion: 1
m_State: {fileID: 1071916381367737375}
m_Position: {x: 220, y: 350, z: 0}
- serializedVersion: 1
m_State: {fileID: 1597451026196869062}
m_Position: {x: 310, y: 450, z: 0}
- serializedVersion: 1
m_State: {fileID: -5161057755351849107}
m_Position: {x: 190, y: 290, z: 0}
- serializedVersion: 1
m_State: {fileID: 6957203282615137037}
m_Position: {x: 270, y: 450, z: 0}
m_ChildStateMachines: []
m_AnyStateTransitions: []
m_EntryTransitions: []
@ -187,32 +187,6 @@ AnimatorStateMachine:
m_ExitPosition: {x: 800, y: 120, z: 0}
m_ParentStateMachinePosition: {x: 800, y: 20, z: 0}
m_DefaultState: {fileID: 4817866092193183352}
--- !u!1102 &1597451026196869062
AnimatorState:
serializedVersion: 6
m_ObjectHideFlags: 1
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: ghoul_walk
m_Speed: 1
m_CycleOffset: 0
m_Transitions: []
m_StateMachineBehaviours: []
m_Position: {x: 50, y: 50, z: 0}
m_IKOnFeet: 0
m_WriteDefaultValues: 1
m_Mirror: 0
m_SpeedParameterActive: 0
m_MirrorParameterActive: 0
m_CycleOffsetParameterActive: 0
m_TimeParameterActive: 0
m_Motion: {fileID: 7400000, guid: 6aa2008e4fe28b443b5c93d5b9f768d7, type: 3}
m_Tag:
m_SpeedParameter:
m_MirrorParameter:
m_CycleOffsetParameter:
m_TimeParameter:
--- !u!1102 &4817866092193183352
AnimatorState:
serializedVersion: 6
@ -239,3 +213,29 @@ AnimatorState:
m_MirrorParameter:
m_CycleOffsetParameter:
m_TimeParameter:
--- !u!1102 &6957203282615137037
AnimatorState:
serializedVersion: 6
m_ObjectHideFlags: 1
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: ghoul_walk
m_Speed: 1
m_CycleOffset: 0
m_Transitions: []
m_StateMachineBehaviours: []
m_Position: {x: 50, y: 50, z: 0}
m_IKOnFeet: 0
m_WriteDefaultValues: 1
m_Mirror: 0
m_SpeedParameterActive: 0
m_MirrorParameterActive: 0
m_CycleOffsetParameterActive: 0
m_TimeParameterActive: 0
m_Motion: {fileID: 7400000, guid: 7cea8855ca3183f4abf3654fdff23011, type: 2}
m_Tag:
m_SpeedParameter:
m_MirrorParameter:
m_CycleOffsetParameter:
m_TimeParameter:

View File

@ -23,6 +23,7 @@ public class ExplodeMonster : MonsterClass // 클래스를 선언할거에요 ->
[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); // 재생할거에요 -> 달리기 애니를
}
}
// ─────────────────────────────────────────────────────────
// 자폭 코루틴

View File

@ -65,6 +65,15 @@ public abstract class MonsterClass : MonoBehaviour, IDamageable // 추상 클래
protected virtual void Awake() // 함수를 실행할거에요 -> 컴포넌트 캐싱을
{
animator = GetComponent<Animator>(); // 가져올거에요 -> 애니메이터를
agent = GetComponent<NavMeshAgent>(); // 가져올거에요 -> 에이전트를
audioSource = GetComponent<AudioSource>(); // 가져올거에요 -> 오디오 소스를
mobRenderer = GetComponentInChildren<Renderer>(); // 가져올거에요 -> 렌더러를
// statusProcessor = GetComponent<StatusEffectProcessor>(); // 가져올거에요 -> 상태이상 처리기를
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; // 해제할거에요 -> 휴식 상태를
}
// ─────────────────────────────────────────────────────────

View File

@ -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() // 함수를 실행할거에요 -> 사망 시
{

View File

@ -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); // 회전할거에요 -> 방향대로