commit
ceb721bebc
@ -70,6 +70,8 @@ public class PlayerController : CharacterBase, IObserver<GameObject>
|
|||||||
_actionDash = new PlayerActionDash();
|
_actionDash = new PlayerActionDash();
|
||||||
|
|
||||||
PlayerInit();
|
PlayerInit();
|
||||||
|
|
||||||
|
SwitchBattleMode();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Update()
|
private void Update()
|
||||||
@ -87,7 +89,9 @@ public class PlayerController : CharacterBase, IObserver<GameObject>
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 공격 입력 처리
|
// 공격 입력 처리
|
||||||
if (Input.GetKeyDown(KeyCode.X) && (_currentAction == null || !_currentAction.IsActive)) {
|
if (Input.GetKeyDown(KeyCode.X) && (_currentAction == null || !_currentAction.IsActive)
|
||||||
|
&& (CurrentState != PlayerState.Win && CurrentState != PlayerState.Dead)) {
|
||||||
|
Debug.Log("X 버튼 Down 됨");
|
||||||
StartAttackAction();
|
StartAttackAction();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -171,6 +175,7 @@ public class PlayerController : CharacterBase, IObserver<GameObject>
|
|||||||
if (_weaponController.IsAttacking) return; // 이미 공격 중이면 실행 안함
|
if (_weaponController.IsAttacking) return; // 이미 공격 중이면 실행 안함
|
||||||
|
|
||||||
if (_currentAction == _attackAction) {
|
if (_currentAction == _attackAction) {
|
||||||
|
Debug.Log($"Attack True");
|
||||||
_attackAction.EnableCombo();
|
_attackAction.EnableCombo();
|
||||||
_weaponController.AttackStart();
|
_weaponController.AttackStart();
|
||||||
}
|
}
|
||||||
@ -178,8 +183,10 @@ public class PlayerController : CharacterBase, IObserver<GameObject>
|
|||||||
|
|
||||||
public void SetAttackComboFalse() {
|
public void SetAttackComboFalse() {
|
||||||
if (_currentAction == _attackAction) {
|
if (_currentAction == _attackAction) {
|
||||||
|
Debug.Log($"Attack False");
|
||||||
|
// 이벤트 중복 호출? 공격 종료 시 SetAttackComboFalse가 아니라 ~True로 끝나서 오류 발생. (공격 안하는 상태여도 공격으로 판정됨)
|
||||||
_attackAction.DisableCombo();
|
_attackAction.DisableCombo();
|
||||||
_weaponController.AttackEnd();
|
_weaponController.AttackEnd(); // IsAttacking = false로 변경
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -207,6 +214,16 @@ public class PlayerController : CharacterBase, IObserver<GameObject>
|
|||||||
|
|
||||||
public void OnNext(GameObject value)
|
public void OnNext(GameObject value)
|
||||||
{
|
{
|
||||||
|
float playerAttackPower = _weaponController.AttackPower * attackPower;
|
||||||
|
|
||||||
|
if (value.CompareTag("Enemy")) // 적이 Enemy일 때만 공격 처리
|
||||||
|
{
|
||||||
|
var enemyController = value.transform.GetComponent<EnemyController>();
|
||||||
|
if (enemyController != null)
|
||||||
|
{
|
||||||
|
enemyController.TakeDamage(playerAttackPower);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void OnError(Exception error)
|
public void OnError(Exception error)
|
||||||
|
@ -49,7 +49,11 @@ public class WeaponController : MonoBehaviour, IObservable<GameObject>
|
|||||||
_playerController = GetComponent<PlayerController>();
|
_playerController = GetComponent<PlayerController>();
|
||||||
if (_playerController == null)
|
if (_playerController == null)
|
||||||
{
|
{
|
||||||
_playerController = GameObject.FindGameObjectWithTag("Player").GetComponent<PlayerController>();
|
var player = GameObject.FindGameObjectWithTag("Player");
|
||||||
|
if (player != null)
|
||||||
|
{
|
||||||
|
_playerController = player.GetComponent<PlayerController>();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_previousPositions = new Vector3[_triggerZones.Length];
|
_previousPositions = new Vector3[_triggerZones.Length];
|
||||||
@ -66,12 +70,26 @@ public class WeaponController : MonoBehaviour, IObservable<GameObject>
|
|||||||
_isAttacking = true;
|
_isAttacking = true;
|
||||||
_hitColliders.Clear();
|
_hitColliders.Clear();
|
||||||
|
|
||||||
|
StopAllCoroutines();
|
||||||
|
StartCoroutine(AutoEndAttack()); // 자동 공격 종료
|
||||||
|
|
||||||
for (int i = 0; i < _triggerZones.Length; i++)
|
for (int i = 0; i < _triggerZones.Length; i++)
|
||||||
{
|
{
|
||||||
_previousPositions[i] = transform.position + transform.TransformVector(_triggerZones[i].position);
|
_previousPositions[i] = transform.position + transform.TransformVector(_triggerZones[i].position);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private IEnumerator AutoEndAttack()
|
||||||
|
{
|
||||||
|
yield return new WaitForSeconds(0.6f); // 0.6초 가량 대기
|
||||||
|
|
||||||
|
if (_isAttacking) // 아직 공격 중이면
|
||||||
|
{
|
||||||
|
Debug.Log("공격 자동 종료 - 타임아웃");
|
||||||
|
AttackEnd();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void AttackEnd()
|
public void AttackEnd()
|
||||||
{
|
{
|
||||||
_isAttacking = false;
|
_isAttacking = false;
|
||||||
@ -101,17 +119,6 @@ public class WeaponController : MonoBehaviour, IObservable<GameObject>
|
|||||||
if (!_hitColliders.Contains(hit.collider))
|
if (!_hitColliders.Contains(hit.collider))
|
||||||
{
|
{
|
||||||
_hitColliders.Add(hit.collider);
|
_hitColliders.Add(hit.collider);
|
||||||
|
|
||||||
Debug.Log("hit.collider.name: " + hit.collider.name);
|
|
||||||
if (hit.collider.gameObject.CompareTag("Enemy"))
|
|
||||||
{
|
|
||||||
var enemyController = hit.transform.GetComponent<EnemyController>();
|
|
||||||
if (enemyController != null)
|
|
||||||
{
|
|
||||||
enemyController.TakeDamage(AttackPower * _playerController.attackPower);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Notify(hit.collider.gameObject);
|
Notify(hit.collider.gameObject);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,8 @@ using UnityEngine;
|
|||||||
|
|
||||||
public class DungeonLogic : MonoBehaviour
|
public class DungeonLogic : MonoBehaviour
|
||||||
{
|
{
|
||||||
|
[SerializeField] private DungeonPanelController _dungeonPanelController;
|
||||||
|
|
||||||
[NonSerialized] public bool isCompleted = false; // 던전 클리어 여부
|
[NonSerialized] public bool isCompleted = false; // 던전 클리어 여부
|
||||||
[NonSerialized] public bool isFailed = false; // 던전 실패 여부
|
[NonSerialized] public bool isFailed = false; // 던전 실패 여부
|
||||||
|
|
||||||
@ -24,19 +26,42 @@ public class DungeonLogic : MonoBehaviour
|
|||||||
// 죽음 이벤트 구독
|
// 죽음 이벤트 구독
|
||||||
if (_player != null)
|
if (_player != null)
|
||||||
{
|
{
|
||||||
|
_player.OnGetHit += OnPlayerGetHit;
|
||||||
_player.OnDeath += OnPlayerDeath;
|
_player.OnDeath += OnPlayerDeath;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_enemy != null)
|
if (_enemy != null)
|
||||||
{
|
{
|
||||||
|
_enemy.OnGetHit += OnEnemyGetHit;
|
||||||
_enemy.OnDeath += OnEnemyDeath;
|
_enemy.OnDeath += OnEnemyDeath;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 플레이어 사망 처리
|
private void OnPlayerGetHit(CharacterBase player)
|
||||||
private void OnPlayerDeath(CharacterBase player)
|
{
|
||||||
|
if (isFailed || isCompleted) return; // 어느 한 쪽 사망시 더이상 피격 X
|
||||||
|
|
||||||
|
// TODO: 플레이어 피격 효과음
|
||||||
|
|
||||||
|
var result = _dungeonPanelController.SetPlayerHealth();
|
||||||
|
if (!result) // 하트 모두 소모
|
||||||
|
{
|
||||||
|
player.Die();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnEnemyGetHit(CharacterBase enemy)
|
||||||
|
{
|
||||||
|
if (isFailed || isCompleted) return;
|
||||||
|
|
||||||
|
// TODO: 에너미 피격 효과음
|
||||||
|
|
||||||
|
_dungeonPanelController.SetBossHealthBar(enemy.currentHP);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 플레이어 사망 처리
|
||||||
|
private void OnPlayerDeath()
|
||||||
{
|
{
|
||||||
Debug.Log("player name:" + player.characterName);
|
|
||||||
if (!isFailed) // 중복 실행 방지
|
if (!isFailed) // 중복 실행 방지
|
||||||
{
|
{
|
||||||
FailDungeon();
|
FailDungeon();
|
||||||
@ -44,9 +69,8 @@ public class DungeonLogic : MonoBehaviour
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 적 사망 처리
|
// 적 사망 처리
|
||||||
private void OnEnemyDeath(CharacterBase enemy)
|
private void OnEnemyDeath()
|
||||||
{
|
{
|
||||||
Debug.Log("enemy name:" + enemy.characterName);
|
|
||||||
if (!isCompleted) // 중복 실행 방지
|
if (!isCompleted) // 중복 실행 방지
|
||||||
{
|
{
|
||||||
CompleteDungeon();
|
CompleteDungeon();
|
||||||
@ -62,7 +86,9 @@ public class DungeonLogic : MonoBehaviour
|
|||||||
isCompleted = true;
|
isCompleted = true;
|
||||||
OnDungeonSuccess?.Invoke();
|
OnDungeonSuccess?.Invoke();
|
||||||
|
|
||||||
// 성공 UI 표시 ?? 강화 표기
|
_dungeonPanelController.SetBossHealthBar(0.0f); // 보스 체력 0 재설정
|
||||||
|
|
||||||
|
_player.SetState(PlayerState.Win);
|
||||||
// TODO: 강화 시스템으로 넘어가고 일상 맵으로 이동
|
// TODO: 강화 시스템으로 넘어가고 일상 맵으로 이동
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -76,10 +102,13 @@ public class DungeonLogic : MonoBehaviour
|
|||||||
isFailed = true;
|
isFailed = true;
|
||||||
OnDungeonFailure?.Invoke();
|
OnDungeonFailure?.Invoke();
|
||||||
|
|
||||||
// 죽음 애니메이션 + 실패 UI 표시 ?
|
_player.SetState(PlayerState.Dead);
|
||||||
// GameManager.Instance.ChangeToHomeScene();
|
|
||||||
|
|
||||||
StartCoroutine(DelayedSceneChange()); // 테스트를 위해 3초 대기 후 전환
|
// enemy가 더이상 Trace 하지 않도록 처리
|
||||||
|
_player.gameObject.layer = LayerMask.NameToLayer("Ignore Raycast");
|
||||||
|
_enemy.SetState(EnemyState.Idle);
|
||||||
|
|
||||||
|
StartCoroutine(DelayedSceneChange()); // 3초 대기 후 전환
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
35
Assets/KSH/DungeonPanelController.cs
Normal file
35
Assets/KSH/DungeonPanelController.cs
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using UnityEngine;
|
||||||
|
using UnityEngine.UI;
|
||||||
|
|
||||||
|
public class DungeonPanelController : MonoBehaviour
|
||||||
|
{
|
||||||
|
[SerializeField] private Slider _bossHealthBar; // 0~1 value
|
||||||
|
[SerializeField] private Image[] _playerHealthImages; // color 값 white / black 로 조정
|
||||||
|
private int _countHealth = 0;
|
||||||
|
|
||||||
|
public void SetBossHealthBar(float hp) // hp: 0~100
|
||||||
|
{
|
||||||
|
float normalizedHp = hp / 100f; // 0~1 사이 값으로 조정
|
||||||
|
_bossHealthBar.value = normalizedHp;
|
||||||
|
}
|
||||||
|
|
||||||
|
// false 반환 시 사망 처리
|
||||||
|
public bool SetPlayerHealth()
|
||||||
|
{
|
||||||
|
StartCoroutine(WaitForOneSecond());
|
||||||
|
// out of index error 방지
|
||||||
|
if (_countHealth > _playerHealthImages.Length - 1) return false;
|
||||||
|
|
||||||
|
_playerHealthImages[_countHealth].color = Color.black;
|
||||||
|
_countHealth++;
|
||||||
|
return _countHealth <= _playerHealthImages.Length - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
IEnumerator WaitForOneSecond()
|
||||||
|
{
|
||||||
|
yield return new WaitForSeconds(1.0f);
|
||||||
|
}
|
||||||
|
}
|
11
Assets/KSH/DungeonPanelController.cs.meta
Normal file
11
Assets/KSH/DungeonPanelController.cs.meta
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 75caf6a3958eb0745a00749003e12d73
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
BIN
Assets/KSH/DungeonTestScene.unity
(Stored with Git LFS)
BIN
Assets/KSH/DungeonTestScene.unity
(Stored with Git LFS)
Binary file not shown.
@ -1,3 +1,4 @@
|
|||||||
|
using System;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
@ -17,7 +18,8 @@ public abstract class CharacterBase : MonoBehaviour
|
|||||||
[Header("상태 이상")]
|
[Header("상태 이상")]
|
||||||
public List<StatusEffect> statusEffects = new List<StatusEffect>();
|
public List<StatusEffect> statusEffects = new List<StatusEffect>();
|
||||||
|
|
||||||
public event System.Action<CharacterBase> OnDeath; // 사망 이벤트
|
public event Action OnDeath; // 사망 이벤트
|
||||||
|
public event Action<CharacterBase> OnGetHit; // 피격 이벤트
|
||||||
|
|
||||||
protected virtual void Start()
|
protected virtual void Start()
|
||||||
{
|
{
|
||||||
@ -26,6 +28,8 @@ public abstract class CharacterBase : MonoBehaviour
|
|||||||
|
|
||||||
public virtual void TakeDamage(float damage)
|
public virtual void TakeDamage(float damage)
|
||||||
{
|
{
|
||||||
|
if (currentHP <= 0) return;
|
||||||
|
|
||||||
float actualDamage = Mathf.Max(0, damage - defensePower);
|
float actualDamage = Mathf.Max(0, damage - defensePower);
|
||||||
currentHP -= Mathf.RoundToInt(actualDamage);
|
currentHP -= Mathf.RoundToInt(actualDamage);
|
||||||
Debug.Log($"{characterName}이 {actualDamage}의 피해를 입었습니다. 현재 체력: {currentHP}");
|
Debug.Log($"{characterName}이 {actualDamage}의 피해를 입었습니다. 현재 체력: {currentHP}");
|
||||||
@ -33,14 +37,17 @@ public abstract class CharacterBase : MonoBehaviour
|
|||||||
if (currentHP <= 0)
|
if (currentHP <= 0)
|
||||||
{
|
{
|
||||||
Die();
|
Die();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
OnGetHit?.Invoke(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual void Die()
|
public virtual void Die()
|
||||||
{
|
{
|
||||||
Debug.Log($"{characterName}이 사망했습니다.");
|
Debug.Log($"{characterName}이 사망했습니다.");
|
||||||
// TODO: 사망 처리
|
// TODO: 사망 처리
|
||||||
OnDeath?.Invoke(this);
|
OnDeath?.Invoke();
|
||||||
}
|
}
|
||||||
|
|
||||||
// 상태이상 추가 메서드
|
// 상태이상 추가 메서드
|
||||||
|
Loading…
x
Reference in New Issue
Block a user