DEG-28 DEG-33 [feat] 몬스터 공격 액션 추가

This commit is contained in:
fiore 2025-04-18 13:10:28 +09:00
parent e290f9af76
commit ad2e4a7f6e
48 changed files with 417 additions and 66 deletions

3
Assets/Editor.meta Normal file
View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 612dfb3f3c0e45e3aaa9d5def5189516
timeCreated: 1744852718

View File

@ -0,0 +1,82 @@
using UnityEditor;
using UnityEngine;
[CustomEditor(typeof(PldDogController))]
public class EnemyControllerEditor : Editor
{
public override void OnInspectorGUI()
{
// 기본 인스펙터를 그리기
base.OnInspectorGUI();
// 타겟 컴포넌트 참조 가져오기
EnemyController enemyController = (EnemyController)target;
// 여백 추가
EditorGUILayout.Space();
EditorGUILayout.LabelField("상태 디버그 정보", EditorStyles.boldLabel);
EditorGUILayout.BeginVertical(EditorStyles.helpBox);
// 상태별 색상 지정
switch (enemyController.CurrentState)
{
case EnemyState.Idle:
GUI.backgroundColor = new Color(0, 0, 1, 1f);
break;
case EnemyState.Trace:
GUI.backgroundColor = new Color(1, 0, 1, 1f);
break;
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;
}
EditorGUILayout.BeginVertical(EditorStyles.helpBox);
EditorGUILayout.LabelField("현재 상태", enemyController.CurrentState.ToString(),
EditorStyles.boldLabel);
EditorGUILayout.EndVertical();
EditorGUILayout.EndVertical();
EditorGUILayout.Space();
EditorGUILayout.LabelField("상태 변경", EditorStyles.boldLabel);
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("Dead")) enemyController.SetState(EnemyState.Dead);
EditorGUILayout.EndHorizontal();
}
private void OnEnable()
{
EditorApplication.update += OnEditorUpdate;
}
private void OnDisable()
{
EditorApplication.update -= OnEditorUpdate;
}
private void OnEditorUpdate()
{
if (target != null)
Repaint();
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 9e73fc154fc447fea93336f02b6df5ea
timeCreated: 1744852745

BIN
Assets/JYY/Animation/Attack01.anim (Stored with Git LFS) Normal file

Binary file not shown.

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 6019f1b4a095b0b4396f5561a51fee89
timeCreated: 1544605028
licenseType: Store
NativeFormatImporter:
userData:
assetBundleName:
assetBundleVariant:

BIN
Assets/JYY/Animation/Attack02.anim (Stored with Git LFS) Normal file

Binary file not shown.

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: eccbae3cfc77ad245ade46e143aa3200
timeCreated: 1544605040
licenseType: Store
NativeFormatImporter:
userData:
assetBundleName:
assetBundleVariant:

BIN
Assets/JYY/Animation/Defend.anim (Stored with Git LFS) Normal file

Binary file not shown.

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: cf357b5409b4ad54a82c45d7684564e1
timeCreated: 1544607741
licenseType: Store
NativeFormatImporter:
userData:
assetBundleName:
assetBundleVariant:

BIN
Assets/JYY/Animation/Die.anim (Stored with Git LFS) Normal file

Binary file not shown.

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 5d190d8211c88a64281f7b90c69f3eb3
timeCreated: 1544605073
licenseType: Store
NativeFormatImporter:
userData:
assetBundleName:
assetBundleVariant:

BIN
Assets/JYY/Animation/DieRecover.anim (Stored with Git LFS) Normal file

Binary file not shown.

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 4a3671dbe6670524b8b6d9ad3664c179
timeCreated: 1544607752
licenseType: Store
NativeFormatImporter:
userData:
assetBundleName:
assetBundleVariant:

BIN
Assets/JYY/Animation/Dizzy.anim (Stored with Git LFS) Normal file

Binary file not shown.

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 30d4fe7af77240a44b9354aaed8e5beb
timeCreated: 1544607757
licenseType: Store
NativeFormatImporter:
userData:
assetBundleName:
assetBundleVariant:

BIN
Assets/JYY/Animation/GetHit.anim (Stored with Git LFS) Normal file

Binary file not shown.

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 1588532e68f51a040bda71c68cfab177
timeCreated: 1544605085
licenseType: Store
NativeFormatImporter:
userData:
assetBundleName:
assetBundleVariant:

BIN
Assets/JYY/Animation/Idle_Battle.anim (Stored with Git LFS) Normal file

Binary file not shown.

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: b79ff7bb68348be479d3db6b7fe8a569
timeCreated: 1544605090
licenseType: Store
NativeFormatImporter:
userData:
assetBundleName:
assetBundleVariant:

BIN
Assets/JYY/Animation/RunForwardBattle.anim (Stored with Git LFS) Normal file

Binary file not shown.

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 9f0e03164414016409d28995a128ba98
timeCreated: 1544605137
licenseType: Store
NativeFormatImporter:
userData:
assetBundleName:
assetBundleVariant:

BIN
Assets/JYY/Animation/WalkForwardBattle.anim (Stored with Git LFS) Normal file

Binary file not shown.

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: f0c8c1d913b359a428b42d53947d3e93
timeCreated: 1544607284
licenseType: Store
NativeFormatImporter:
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:5ae32e910b172b4f7b04fbf91607ef7d871adec9ee0233990fd3b38d3be5a807
size 10132
oid sha256:302f67e12e0abc61d39c9173fbe83f6d3acfd3a5efacf45923fc36c4962cae34
size 13077

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: f736a70ba6c488a48b743638353258e9
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

BIN
Assets/JYY/Scenes/MonsterTest.unity (Stored with Git LFS)

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 0ea1affa28401cb4388633bac551449a
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 23800000
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,22 +1,27 @@
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;
public enum EnemyState { None, Idle, Trace, Attack, GetHit, Move, Dead }
[RequireComponent(typeof(NavMeshAgent))]
[RequireComponent(typeof(Animator))]
public class EnemyController : CharacterBase
public abstract class EnemyController : CharacterBase
{
[Header("AI")]
[SerializeField] private float detectCircleRadius = 10f; // 플레이어 탐지 범위
[SerializeField] private LayerMask targetLayerMask; // 플레이어 레이어 마스크
public NavMeshAgent Agent { get; private set; }
public Animator EnemyAnimator { get; private set; }
public EnemyState CurrentState { get; private set; }
private EnemyState _currentState = EnemyState.Idle;
public EnemyState CurrentState {get; private set;}
public float WalkSpeed => walkSpeed;
public float RunSpeed => runSpeed;
[SerializeField] private float walkSpeed = 5;
[SerializeField] private float runSpeed = 8;
// -----
// 상태 변수
@ -29,10 +34,15 @@ public class EnemyController : CharacterBase
private Dictionary<EnemyState, IEnemyState> _enemyStates;
private void Awake()
{
EnemyAnimator = GetComponent<Animator>();
Agent = GetComponent<NavMeshAgent>();
}
protected override void Start()
{
base.Start();
EnemyAnimator = GetComponent<Animator>();
// 상태 객체 생성
_enemyStateIdle = new EnemyStateIdle();
@ -84,10 +94,8 @@ public class EnemyController : CharacterBase
{
return hitColliders[0].transform;
}
else
{
return null;
}
return null;
}
#endregion

View File

@ -1,16 +1,40 @@
public class EnemyStateAttack : IEnemyState
using System.Collections;
using UnityEngine;
public class EnemyStateAttack : IEnemyState
{
private EnemyController _enemyController;
public void Enter(EnemyController enemyController)
{
_enemyController = enemyController;
_enemyController.EnemyAnimator.SetTrigger("Attack");
}
public void Update()
{
_enemyController.SetState(EnemyState.Trace);
}
// private IEnumerator AttackSequence()
// {
// // 1. 전조 이펙트 생성
//
// // 2. 검을 들어올리는 애니메이션 재생
//
// // 3. 대기(전조와 검 들어올리는 애니메이션을 위함)
//
// // 4. 전조 제거
//
// // 회전 초기화
//
// // 5. 검 휘두르기
//
// // 6. 공격 판정 발생
//
// // 7. 상태 전환
// }
public void Exit()
{
_enemyController = null;

View File

@ -1,18 +1,122 @@
public class EnemyStateTrace : IEnemyState
using UnityEngine;
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;
private const float MaxDetectPlayerInCircleWaitTime = 0.2f;
private float _detectPlayerInCircleWaitTime = 0f;
public void Enter(EnemyController enemyController)
{
_enemyController = enemyController;
_detectPlayerTransform = _enemyController.DetectPlayerInCircle();
if (!_detectPlayerTransform)
{
_enemyController.SetState(EnemyState.Idle);
return;
}
if (_enemyController.Agent.enabled == true)
{
_enemyController.Agent.isStopped = false;
_enemyController.Agent.SetDestination(_detectPlayerTransform.position);
}
_enemyController.EnemyAnimator.SetBool(Trace, true);
}
public void Update()
{
// 일정 주기로 찾은 플레이어의 위치를 갱신해서 갱신된 위치로 이동
FindTargetPosition();
PlayerTracking();
if (_enemyController.Agent.remainingDistance <= _enemyController.Agent.stoppingDistance)
{
// TODO: 타겟에 도착함 -> 공격 준비
_enemyController.SetState(EnemyState.Attack);
}
}
private void FindTargetPosition()
{
if (_detectPlayerInCircleWaitTime > MaxDetectPlayerInCircleWaitTime)
{
_enemyController.Agent.SetDestination(_detectPlayerTransform.position);
_detectPlayerInCircleWaitTime = 0f;
}
_detectPlayerInCircleWaitTime += Time.deltaTime;
}
// 플레이어를 추적하는 속도를 제어하는 함수
private void PlayerTracking()
{
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)
{
// 가까운 거리: 걷기
_enemyController.Agent.speed = _enemyController.WalkSpeed;
_enemyController.Agent.acceleration = 8f;
_enemyController.Agent.angularSpeed = 720f;
// _enemyController.EnemyAnimator.SetFloat("MoveSpeed", 0.4f); // Walk 애니메이션
_enemyController.Agent.updateRotation = true;
}
else
{
// 매우 가까움: 직접 타겟 바라보기
_enemyController.Agent.updateRotation = false;
Vector3 direction = _detectPlayerTransform.position - _enemyController.transform.position;
direction.y = 0f; // 수직 회전 방지
if (direction.sqrMagnitude > 0.01f)
{
Quaternion lookRotation = Quaternion.LookRotation(direction);
_enemyController.transform.rotation = Quaternion.Slerp(
_enemyController.transform.rotation,
lookRotation,
Time.deltaTime * 10f // 회전 속도
);
}
// _enemyController.Agent.angularSpeed = 1080f;
// _enemyController.Agent.acceleration = 999f;
// _enemyController.EnemyAnimator.SetFloat("MoveSpeed", 0f);
}
// 실제 속도 기반으로 애니메이션 제어
float currentSpeed = _enemyController.Agent.velocity.magnitude;
_enemyController.EnemyAnimator.SetFloat(MoveSpeed, currentSpeed);
}
public void Exit()
{
_detectPlayerTransform = null;
_enemyController.EnemyAnimator.SetBool(Trace, false);
_enemyController = null;
}
}
}

View File

@ -4,16 +4,4 @@ using UnityEngine;
public class PldDogController : EnemyController
{
private void Awake()
{
}
private void Update()
{
}
}

View File

@ -1,8 +1,8 @@
fileFormatVersion: 2
guid: 6019f1b4a095b0b4396f5561a51fee89
timeCreated: 1544605028
licenseType: Store
guid: 68de4930eebde9e479eaab7c237d2746
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 7400000
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,8 +1,8 @@
fileFormatVersion: 2
guid: eccbae3cfc77ad245ade46e143aa3200
timeCreated: 1544605040
licenseType: Store
guid: ff79b845bee80594a98ec31de14b5ecd
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 7400000
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,8 +1,8 @@
fileFormatVersion: 2
guid: cf357b5409b4ad54a82c45d7684564e1
timeCreated: 1544607741
licenseType: Store
guid: 5b0776984ffd79842a0465fb8a419441
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 7400000
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,8 +1,8 @@
fileFormatVersion: 2
guid: 5d190d8211c88a64281f7b90c69f3eb3
timeCreated: 1544605073
licenseType: Store
guid: cef708be761542448b42d1f5e4d1d5e6
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 7400000
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

View File

@ -1,8 +1,8 @@
fileFormatVersion: 2
guid: 4a3671dbe6670524b8b6d9ad3664c179
timeCreated: 1544607752
licenseType: Store
guid: 7e5e21c2814211745a93c59b744df10e
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 7400000
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,8 +1,8 @@
fileFormatVersion: 2
guid: 30d4fe7af77240a44b9354aaed8e5beb
timeCreated: 1544607757
licenseType: Store
guid: 6295306c82f8e6b49938378b3666db48
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 7400000
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,8 +1,8 @@
fileFormatVersion: 2
guid: 1588532e68f51a040bda71c68cfab177
timeCreated: 1544605085
licenseType: Store
guid: 2b359afc6c4d41a4eb986dd6103e0f90
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 7400000
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,8 +1,8 @@
fileFormatVersion: 2
guid: b79ff7bb68348be479d3db6b7fe8a569
timeCreated: 1544605090
licenseType: Store
guid: 3ec08e68e04f63f4393c07f4246dce96
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 7400000
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

View File

@ -1,8 +1,8 @@
fileFormatVersion: 2
guid: 9f0e03164414016409d28995a128ba98
timeCreated: 1544605137
licenseType: Store
guid: 6253b377de3be0f4897ab40c9921af28
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 7400000
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,8 +1,8 @@
fileFormatVersion: 2
guid: f0c8c1d913b359a428b42d53947d3e93
timeCreated: 1544607284
licenseType: Store
guid: 82ae7cd6e51ade24b9467d436d2d7482
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 7400000
userData:
assetBundleName:
assetBundleVariant:

View File

@ -1,5 +1,6 @@
{
"dependencies": {
"com.unity.ai.navigation": "1.1.5",
"com.unity.collab-proxy": "2.7.1",
"com.unity.ide.rider": "3.0.34",
"com.unity.ide.visualstudio": "2.0.22",

View File

@ -1,5 +1,14 @@
{
"dependencies": {
"com.unity.ai.navigation": {
"version": "1.1.5",
"depth": 0,
"source": "registry",
"dependencies": {
"com.unity.modules.ai": "1.0.0"
},
"url": "https://packages.unity.com"
},
"com.unity.burst": {
"version": "1.8.19",
"depth": 1,

View File

@ -71,10 +71,10 @@ NavMeshProjectSettings:
cost: 1
m_LastAgentTypeID: -887442657
m_Settings:
- serializedVersion: 2
- serializedVersion: 3
agentTypeID: 0
agentRadius: 0.5
agentHeight: 2
agentHeight: 1.5
agentSlope: 45
agentClimb: 0.75
ledgeDropHeight: 0
@ -84,7 +84,9 @@ NavMeshProjectSettings:
cellSize: 0.16666667
manualTileSize: 0
tileSize: 256
accuratePlacement: 0
buildHeightMesh: 0
maxJobWorkers: 0
preserveTilesOutsideBounds: 0
debug:
m_Flags: 0
m_SettingNames:

View File

@ -3,7 +3,8 @@
--- !u!78 &1
TagManager:
serializedVersion: 2
tags: []
tags:
- FxTemporaire
layers:
- Default
- TransparentFX
@ -36,7 +37,7 @@ TagManager:
-
-
-
-
- Player
m_SortingLayers:
- name: Default
uniqueID: 0