diff --git a/Assets/JYY/Animator/Alien Big Blink.controller b/Assets/JYY/Animator/Alien Big Blink.controller index d9a11b13..f233680e 100644 --- a/Assets/JYY/Animator/Alien Big Blink.controller +++ b/Assets/JYY/Animator/Alien Big Blink.controller @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f224b789ebc993746abd7e94faed8370d442fa520a9935ca57efd0ec4402a8a9 -size 37778 +oid sha256:f0bce31c8017319b731daa8dfb9666036d51f1002b083d730d3897fd7ee1f2e7 +size 41312 diff --git a/Assets/JYY/Scenes/MonsterTest.unity b/Assets/JYY/Scenes/MonsterTest.unity index 9f548756..6c1ddbe6 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:8f04b7cb3c038c2e7ae9e2308a272957be162eeef89deb5fdcab430f447bde41 -size 25384 +oid sha256:3ddd026f66ac7cb1a8dbdc3118964fcd6ac9932fc136d052cff0406fe79ace39 +size 25822 diff --git a/Assets/Plugins/Editor.meta b/Assets/Plugins/Editor.meta new file mode 100644 index 00000000..59842daf --- /dev/null +++ b/Assets/Plugins/Editor.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 0f665d75f6d77274a9371a87e014fd97 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/Character/Debuff/KnockbackEffect.cs b/Assets/Scripts/Character/Debuff/KnockbackEffect.cs new file mode 100644 index 00000000..3a40d5fe --- /dev/null +++ b/Assets/Scripts/Character/Debuff/KnockbackEffect.cs @@ -0,0 +1,43 @@ +using System.Collections; +using UnityEngine; + +public class KnockbackEffect : StatusEffect +{ + private Vector3 _sourcePosition; + private float _knockbackForce; + private float _elapsed = 0f; + + public KnockbackEffect(Vector3 sourcePosition, float knockbackForce,float duration) + { + effectName = "Knockback"; + this.duration = duration; + _sourcePosition = sourcePosition; + _knockbackForce = knockbackForce; + } + + public override void ApplyEffect(CharacterBase target) + { + + Vector3 direction = (target.transform.position - _sourcePosition).normalized; + direction.y = 0f; // 수직 방향 제거 + target.StartCoroutine(KnockbackCoroutine(target, direction)); + } + private IEnumerator KnockbackCoroutine(CharacterBase pc, Vector3 direction) + { + CharacterController controller = pc.GetComponent(); + if (controller == null) yield break; + + _elapsed = 0f; + while (_elapsed < duration) + { + controller.Move(direction * (_knockbackForce * Time.deltaTime)); + _elapsed += Time.deltaTime; + yield return null; + } + } + + public override void RemoveEffect(CharacterBase target) + { + + } +} \ No newline at end of file diff --git a/Assets/Scripts/Character/Debuff/KnockbackEffect.cs.meta b/Assets/Scripts/Character/Debuff/KnockbackEffect.cs.meta new file mode 100644 index 00000000..633feab3 --- /dev/null +++ b/Assets/Scripts/Character/Debuff/KnockbackEffect.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 97861883fd2941e0a40071b12ca13de4 +timeCreated: 1746082842 \ No newline at end of file diff --git a/Assets/Scripts/Character/Debuff/SlowDebuff.cs b/Assets/Scripts/Character/Debuff/SlowDebuff.cs index 94ccbb0b..86a64335 100644 --- a/Assets/Scripts/Character/Debuff/SlowDebuff.cs +++ b/Assets/Scripts/Character/Debuff/SlowDebuff.cs @@ -13,19 +13,14 @@ public class SlowDebuff : StatusEffect public override void ApplyEffect(CharacterBase target) { - if (target is PlayerController pc) - { - pc.moveSpeed *= _slowMultiplier; - Debug.Log($"{target.characterName}에게 이동 속도 감소 적용됨"); - } + target.moveSpeed *= _slowMultiplier; + Debug.Log($"{target.characterName}에게 이동 속도 감소 적용됨"); + } public override void RemoveEffect(CharacterBase target) { - if (target is PlayerController pc) - { - pc.moveSpeed /= _slowMultiplier; - Debug.Log($"{target.characterName}의 이동 속도 회복됨"); - } + target.moveSpeed /= _slowMultiplier; + Debug.Log($"{target.characterName}의 이동 속도 회복됨"); } } \ No newline at end of file diff --git a/Assets/Scripts/Character/Enemy/BossPattern/AoeControllerBase.cs b/Assets/Scripts/Character/Enemy/BossPattern/AoeControllerBase.cs index 61aef323..8717a99b 100644 --- a/Assets/Scripts/Character/Enemy/BossPattern/AoeControllerBase.cs +++ b/Assets/Scripts/Character/Enemy/BossPattern/AoeControllerBase.cs @@ -24,6 +24,7 @@ public abstract class AoeControllerBase : MonoBehaviour protected DamageEffectData _data; private Action _slashAction; private Action _destroyAction; + protected string EffectName; /// /// 범위 공격 이펙트를 설정하고, 딜레이 후 폭발을 실행합니다. @@ -38,6 +39,17 @@ public abstract class AoeControllerBase : MonoBehaviour StartCoroutine(ExplodeAfterDelay()); } + public void SetEffect(DamageEffectData data, Action slashAction, Action destroyAction, string effectName) + { + _data = data; + _slashAction = slashAction; + _destroyAction = destroyAction; + EffectName = effectName; + + ShowWarningEffect(); + StartCoroutine(ExplodeAfterDelay()); + } + protected virtual void ShowWarningEffect() { if (warningEffectInstance != null) diff --git a/Assets/Scripts/Character/Enemy/BossPattern/MagicAoEField.cs b/Assets/Scripts/Character/Enemy/BossPattern/MagicAoEField.cs index 38808295..eb961724 100644 --- a/Assets/Scripts/Character/Enemy/BossPattern/MagicAoEField.cs +++ b/Assets/Scripts/Character/Enemy/BossPattern/MagicAoEField.cs @@ -13,14 +13,33 @@ public class MagicAoEField : AoeControllerBase Debug.Log($"{hit.name}에게 {_data.damage} 데미지 적용"); // TODO: 실제 데미지 처리 로직 호출 // 임시 데이미 처리 로직 - PlayerController playerController = hit.transform.GetComponent(); - if (playerController != null) - { - // playerController.AddStatusEffect(_slowDebuff); - var slow = new SlowDebuff(10f, 0.5f); // 10초간 50% 속도 - playerController.AddStatusEffect(slow); - } + ApplyEffect(hit); } } } + + private void ApplyEffect(Collider hit) + { + PlayerController playerController = hit.transform.GetComponent(); + switch (EffectName) + { + case "Slow": + + if (playerController != null) + { + var slow = new SlowDebuff(10f, 0.5f); // 10초간 50% 속도 + playerController.AddStatusEffect(slow); + } + break; + case "knockback": + if (playerController != null) + { + var knPos = transform.position; + knPos.y += 0.5f; + var knockback = new KnockbackEffect(knPos,10f, 0.5f); // 장판 중심에서 10f만큼 + playerController.AddStatusEffect(knockback); + } + break; + } + } } \ No newline at end of file diff --git a/Assets/Scripts/Character/Enemy/CasterDemonController.cs b/Assets/Scripts/Character/Enemy/CasterDemonController.cs index a2b2cd48..37ed887a 100644 --- a/Assets/Scripts/Character/Enemy/CasterDemonController.cs +++ b/Assets/Scripts/Character/Enemy/CasterDemonController.cs @@ -11,6 +11,9 @@ public class CasterDemonController : EnemyController // Animation public static readonly int Cast = Animator.StringToHash("Cast"); public static readonly int Flee = Animator.StringToHash("Flee"); + public static readonly int MagicMissile = Animator.StringToHash("MagicMissile"); + public static readonly int Telepo = Animator.StringToHash("Telepo"); + public static readonly int Spin = Animator.StringToHash("Spin"); private bool _doneBattleSequence = true; private bool _isFirstNoPath = true; @@ -30,12 +33,16 @@ public class CasterDemonController : EnemyController [SerializeField] private GameObject slowFieldWarning; [SerializeField] private GameObject slowFieldEffect; - private float _teleportDistance = 4f; // 플레이어 뒤로 떨어질 거리 + // private float _teleportDistance = 4f; // 플레이어 뒤로 떨어질 거리 - // 텔레포트 쿨타임 - private float _teleportTimer = 0; + // 텔레포트 쿨타임 처음엔 빨리 사용 가능함 + private float _teleportTimer = 10f; private const float TeleportThresholdTime = 20f; + // 다음 행동 생각 처음엔 즉시 실행 + private float _tinkingTimer = 3f; + private float _tinkingThresholedTime = 3f; + private bool CanTeleport { get { @@ -48,15 +55,29 @@ public class CasterDemonController : EnemyController } } + private bool CanBattleSequence + { + get + { + if (_tinkingTimer >= _tinkingThresholedTime) + { + _tinkingTimer = 0; + return true; + } + return false; + } + } + private void LateUpdate() { _teleportTimer += Time.deltaTime; + _tinkingTimer += Time.deltaTime; } public override void BattleSequence() { // 전투 행동이 이미 진행 중일 경우 실행 막기 - if (_doneBattleSequence) + if (_doneBattleSequence && CanBattleSequence) { // 전투 행동 시작 _doneBattleSequence = false; @@ -74,13 +95,13 @@ public class CasterDemonController : EnemyController switch (selectedPattern) { case 0: - case 1: case 2: case 3: - + SetSequence(ShotMagicMissile()); + break; case 4: case 5: @@ -92,7 +113,6 @@ public class CasterDemonController : EnemyController case 8: case 9: - // SetSequence(ShotMagicMissile()); SetSequence(SlowFieldSpell()); break; } @@ -105,7 +125,9 @@ public class CasterDemonController : EnemyController { action(); Teleport(); + return; } + SetSequence(KnockbackSpell()); } private IEnumerator ShotMagicMissile() @@ -116,6 +138,7 @@ public class CasterDemonController : EnemyController // 플레이어 위치를 바라보고 transform.LookAt(aimPosition); + SetAnimation(MagicMissile); // 미사일 생성 및 초기화 var missile = Instantiate( @@ -177,6 +200,7 @@ public class CasterDemonController : EnemyController // 중앙으로 이동 Agent.Warp(Vector3.zero); + SetAnimation(Telepo); if (teleportEffectPrefab != null) Instantiate(teleportEffectPrefab, Vector3.zero, Quaternion.identity); @@ -210,6 +234,28 @@ public class CasterDemonController : EnemyController _doneBattleSequence = true; } + private IEnumerator KnockbackSpell() + { + // 시전 애니메이션 + SetAnimation(Spin); + + var effectData = new DamageEffectData + { + damage = 0, + radius = 7.5f, + delay = 0.5f, + targetLayer = TargetLayerMask, + explosionEffectPrefab = slowFieldEffect + }; + + // 넉백 발생 + var knockback = Instantiate(chariotWarning, transform).GetComponent(); + knockback.SetEffect(effectData, null, null, "knockback"); + + yield return new WaitForSeconds(1f); + _doneBattleSequence = true; + } + private void SetSequence(IEnumerator newSequence) { if (_currentSequence != null) diff --git a/Assets/Scripts/Character/Enemy/EnemyState/Caster/EnemyStateFlee.cs b/Assets/Scripts/Character/Enemy/EnemyState/Caster/EnemyStateFlee.cs index b88ff8c8..77467655 100644 --- a/Assets/Scripts/Character/Enemy/EnemyState/Caster/EnemyStateFlee.cs +++ b/Assets/Scripts/Character/Enemy/EnemyState/Caster/EnemyStateFlee.cs @@ -7,8 +7,8 @@ public class EnemyStateFlee :IEnemyState { private EnemyController _enemyController; private Transform _playerTransform; - private float _fleeDistance = 5f; // 도망치는 거리 - private float _safeRange = 7f; // 공격 범위 + private float _fleeDistance = 10f; // 도망치는 거리 + private float _attackRange = 7f; // 공격 범위 // 경로 탐색 주기 조절용 private float _fleeSearchTimer = 0; @@ -48,7 +48,7 @@ public class EnemyStateFlee :IEnemyState _enemyController.transform.position, _playerTransform.position ); - if (currentDist >= _safeRange) + if (currentDist >= _attackRange) { // 목적지 리셋 후 전투 시작 _enemyController.Agent.isStopped = true;