몬스터 스킬 제거

This commit is contained in:
Mingu Kim
2025-03-03 01:39:46 +09:00
parent 8c00971304
commit 5880c7b932
12 changed files with 24 additions and 392 deletions

View File

@@ -1,7 +0,0 @@
fileFormatVersion: 2
guid: d92f0de2a85e2ad43b438f0291dd2a01
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,17 +0,0 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace TON
{
[System.Serializable]
public class MonsterSkillData
{
public int skillId; // 스킬 ID
public string skillName; // 스킬 이름
public float damage; // 스킬 데미지
public float cooldown; // 스킬 쿨다운
public float range; // 스킬 범위
public string prefabName; // 스킬 프리팹 이름
}
}

View File

@@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: e7674986391c77044bbc330f14711e86
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -7,10 +7,7 @@ namespace TON
{ {
public partial class MonsterBase : MonoBehaviour, IDamage public partial class MonsterBase : MonoBehaviour, IDamage
{ {
[SerializeField] private GameObject _target; // 몬스터의 타겟
[SerializeField] private Collider2D _collider; // 몬스터의 콜라이더
[SerializeField] private SpriteRenderer _spriteRenderer; // 몬스터의 스프라이트 렌더러 [SerializeField] private SpriteRenderer _spriteRenderer; // 몬스터의 스프라이트 렌더러
// [SerializeField] private TextMeshProUGUI _textState;
[SerializeField] public int id; // 몬스터의 ID [SerializeField] public int id; // 몬스터의 ID
public float defencePower; public float defencePower;
public float defenceIntention = 30; // 몬스터 방어력 변수 public float defenceIntention = 30; // 몬스터 방어력 변수
@@ -27,7 +24,6 @@ namespace TON
private float moveSpeed = 2f; private float moveSpeed = 2f;
StateMachine _stateMachine; StateMachine _stateMachine;
private SkillPattern _skillPattern;
private Vector3 _direction; // 몬스터의 이동 방향 private Vector3 _direction; // 몬스터의 이동 방향
public bool IsDetect { get; set; } // 몬스터가 대상을 인식했는지 여부 public bool IsDetect { get; set; } // 몬스터가 대상을 인식했는지 여부
@@ -48,24 +44,14 @@ namespace TON
private void Start() private void Start()
{ {
_animator = GetComponent<Animator>(); // 애니메이터 컴포넌트 초기화 _animator = GetComponent<Animator>(); // 애니메이터 컴포넌트 초기화
// TODO : 추후 제거 예정
// _stateMachine = new StateMachine(new IdleState(), this, _textState);
_stateMachine = new StateMachine(new IdleState(), this); _stateMachine = new StateMachine(new IdleState(), this);
InitializeMonsterData(); // 몬스터 데이터 로드 및 적용 InitializeMonsterData(); // 몬스터 데이터 로드 및 적용
if (_monsterData.monsterSkillID != 0)
{
_skillPattern = new MonsterSkillPattern(_monsterData, this);
IsSkillAttackable = _skillPattern.IsAttackable;
}
_direction = new Vector3(1, 0, 0); // 초기 이동 방향 (x 축 양의 방향) _direction = new Vector3(1, 0, 0); // 초기 이동 방향 (x 축 양의 방향)
_spriteRenderer.flipX = !(_direction.x > 0); // 이동 방향에 따라 스프라이트 플립 _spriteRenderer.flipX = !(_direction.x > 0); // 이동 방향에 따라 스프라이트 플립
_collider = GetComponent<Collider2D>(); // 콜라이더 컴포넌트 초기화
// CharacterBase 참조 설정 // CharacterBase 참조 설정
_characterBase = GameObject.Find("TON.Player").GetComponentInChildren<CharacterBase>(); _characterBase = GameObject.Find("TON.Player").GetComponentInChildren<CharacterBase>();
@@ -116,11 +102,6 @@ namespace TON
private void Update() private void Update()
{ {
_stateMachine.Update(); _stateMachine.Update();
if (_monsterData.monsterSkillID != 0)
{
_skillPattern.Update();
}
} }
public void FinishAttack() public void FinishAttack()
@@ -207,31 +188,19 @@ namespace TON
if (target != null) if (target != null)
{ {
Vector2 direction = target.transform.position - transform.position; // 타겟과의 방향 계산 Vector2 direction = target.transform.position - transform.position; // 타겟과의 방향 계산
_spriteRenderer.flipX = target.transform.position.x < transform.position.x; // 타겟이 왼쪽에 있으면 스프라이트를 왼쪽으로, 오른쪽에 있으면 오른쪽으로 바라보도록 설정 _spriteRenderer.flipX =
target.transform.position.x <
transform.position.x; // 타겟이 왼쪽에 있으면 스프라이트를 왼쪽으로, 오른쪽에 있으면 오른쪽으로 바라보도록 설정
transform.Translate(direction.normalized * moveSpeed * Time.deltaTime); // 타겟 방향으로 이동 transform.Translate(direction.normalized * moveSpeed * Time.deltaTime); // 타겟 방향으로 이동
} }
} }
public void MonsterSkillLaunch()
{
if (_monsterData.monsterSkillID != 0)
{
var target = GameObject.FindGameObjectWithTag("Player");
_skillPattern.Attack(target);
}
}
public void DestroyMonster() public void DestroyMonster()
{ {
RewardData(); RewardData();
SoundManager.instance.SFXPlay("Death", _deathSound); SoundManager.instance.SFXPlay("Death", _deathSound);
Destroy(gameObject); // 몬스터 파괴 Destroy(gameObject); // 몬스터 파괴
} }
public SkillPattern GetSkillPattern()
{
return _skillPattern;
}
} }
} }

View File

@@ -1,84 +0,0 @@
using UnityEngine;
namespace TON
{
public class MonsterSkill : MonoBehaviour
{
public float speed = 5f;
public float damage = 0f;
Vector2 direction;
Transform playerTransform; // 플레이어의 Transform을 저장할 변수
[SerializeField] private SpriteRenderer _spriteRenderer; // 스킬의 스프라이트 렌더러
private MonsterBase _monsterBase;
private CharacterBase _characterBase;
public Vector2 Direction
{
set { direction = value.normalized; }
}
void Start()
{
_spriteRenderer = GetComponent<SpriteRenderer>();
_characterBase = GameObject.Find("TON.Player").GetComponentInChildren<CharacterBase>();
if (_characterBase != null)
{
playerTransform = _characterBase.transform;
}
else
{
Debug.LogError("Player 오브젝트를 찾을 수 없습니다. 태그를 확인하세요.");
return; // 플레이어 없으면 이후 로직 실행 중지
}
SetDirection(); // 발사 방향 설정
}
void Update()
{
transform.Translate(direction * speed * Time.deltaTime);
}
private void OnTriggerEnter2D(Collider2D collision)
{
if (collision.CompareTag("Player"))
{
// 플레이어에게 직접 데미지 적용
_characterBase?.ApplyDamage(damage);
Destroy(gameObject);
}
else if (collision.CompareTag("Ground"))
{
// 지형에 부딪히면 스킬 오브젝트만 파괴
Destroy(gameObject);
}
}
public void SetSkillDamage(float skillDamage)
{
damage += skillDamage;
}
void SetDirection()
{
if (playerTransform == null) return; // 플레이어가 없으면 방향 설정 불가
Vector2 toPlayer = playerTransform.position - transform.position; // MonsterSkill과 Player의 위치 차이 계산
// 플레이어의 왼쪽/오른쪽 판별
if (toPlayer.x < 0)
{
direction = new Vector2(-1, 0); // 플레이어가 왼쪽에 있으면 왼쪽 방향으로 발사
}
else
{
direction = new Vector2(1, 0); // 플레이어가 오른쪽에 있으면 오른쪽 방향으로 발사
_spriteRenderer.flipX = true; // 왼쪽 방향일 때 좌우 반전
}
}
}
}

View File

@@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: 190405d8d5d2c0e4683121e913af8457
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -1,49 +0,0 @@
using System.Collections.Generic;
using UnityEngine;
namespace TON
{
public class MonsterSkillDataManager : SingletonBase<MonsterSkillDataManager>
{
// 전체 몬스터 스킬 데이터 리스트
public List<MonsterSkillData> monstersSkillData { get; private set; }
// 현재 선택된 몬스터 스킬 데이터
public MonsterSkillData currentMonsterSkill { get; private set; }
protected override void Awake()
{
base.Awake();
LoadMonsterSkillData();
}
private void LoadMonsterSkillData()
{
monstersSkillData = JSONLoader.LoadFromResources<List<MonsterSkillData>>("MonsterSkills");
if (monstersSkillData == null)
{
monstersSkillData = new List<MonsterSkillData>();
Debug.LogError("몬스터 스킬 데이터 로드 실패");
}
}
public MonsterSkillData GetMonsterSkillData(int monsterSkillId)
{
if (monsterSkillId >= 0 && monsterSkillId < monstersSkillData.Count)
{
currentMonsterSkill = monstersSkillData[monsterSkillId];
return currentMonsterSkill;
}
else
{
Debug.LogError($"유효하지 않은 몬스터 SkillID입니다: {monsterSkillId}");
return null;
}
}
public List<MonsterSkillData> GetAllMonsterSkillData()
{
return monstersSkillData;
}
}
}

View File

@@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: 517b06d480f28194b830fa1520a0a395
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -103,24 +103,23 @@ namespace TON
SoundManager.instance.BgSoundPlay(null); SoundManager.instance.BgSoundPlay(null);
// 필요하다면 gameStarted = false; 등을 설정하여 한 번만 실행되게 함 // 필요하다면 gameStarted = false; 등을 설정하여 한 번만 실행되게 함
} }
} }
private void SpawnBossMonster() private void SpawnBossMonster()
{ {
GameObject bossPrefab = GetBossPrefabForWave(currentWave); GameObject bossPrefab = GetBossPrefabForWave(currentWave);
// 스폰 포인트 배열의 처음과 마지막 위치에 보스 몬스터 생성
if (spawnPoints.Length >= 2) if (spawnPoints.Length >= 2)
{ {
// 왼쪽 스폰 포인트 // 왼쪽 스폰 포인트
GameObject leftBoss = Instantiate(bossPrefab, spawnPoints[0].position, Quaternion.identity); GameObject leftBoss = Instantiate(bossPrefab, spawnPoints[0].position, Quaternion.identity);
monsterPool.Add(leftBoss); SetupBossComponents(leftBoss);
activeMonsters.Add(leftBoss);
// 오른쪽 스폰 포인트 // 오른쪽 스폰 포인트
GameObject rightBoss = Instantiate(bossPrefab, spawnPoints[spawnPoints.Length - 1].position, Quaternion.identity); GameObject rightBoss = Instantiate(bossPrefab, spawnPoints[spawnPoints.Length - 1].position, Quaternion.identity);
monsterPool.Add(rightBoss); SetupBossComponents(rightBoss);
activeMonsters.Add(rightBoss);
} }
else else
{ {
@@ -139,6 +138,22 @@ namespace TON
// 보스가 죽으면 Update에서 체크하여 다음 웨이브로 넘어감 // 보스가 죽으면 Update에서 체크하여 다음 웨이브로 넘어감
} }
private void SetupBossComponents(GameObject boss)
{
MonsterBase monsterBase = boss.GetComponent<MonsterBase>();
Attack attackComponent = boss.GetComponentInChildren<Attack>();
Eyesight eyesightComponent = boss.GetComponentInChildren<Eyesight>();
if (attackComponent != null)
attackComponent.SetMonsterBase(monsterBase);
if (eyesightComponent != null)
eyesightComponent.SetMonsterBase(monsterBase);
monsterPool.Add(boss);
activeMonsters.Add(boss);
}
private void StartNextWave() private void StartNextWave()
{ {
StageManager.Singleton.SetWaveData(currentWave); // 웨이브 정보 전달. StageManager.Singleton.SetWaveData(currentWave); // 웨이브 정보 전달.

View File

@@ -1,94 +0,0 @@
using UnityEngine;
namespace TON
{
public abstract class SkillPattern
{
protected MonsterData _monsterData;
protected MonsterBase _monsterBase;
protected SkillPattern(MonsterData monsterData, MonsterBase monsterBase)
{
_monsterData = monsterData;
_monsterBase = monsterBase;
}
public bool IsAttackable { get; set; }
public abstract bool IsSkillInCooldown();
public abstract void Attack(GameObject target);
public abstract void Update();
}
public class MonsterSkillPattern : SkillPattern
{
private float _lastSkillTime;
private MonsterSkillData _monsterSkillData;
private MonsterSkill _skill;
private Vector3 _skillOffset = new Vector3(0, -0.5f, 0);
public MonsterSkillPattern(MonsterData monsterData, MonsterBase monsterBase) : base(monsterData, monsterBase)
{
_monsterSkillData = MonsterSkillDataManager.Singleton.GetMonsterSkillData(_monsterData.monsterSkillID);
_lastSkillTime = -_monsterSkillData.cooldown; // 시작시 스킬 사용 가능하도록
IsAttackable = true;
if (_monsterSkillData != null)
{
// Debug.Log($"몬스터 {_monsterSkillData.skillName} 데이터 로드 완료");
_skill = Resources.Load<MonsterSkill>($"MonsterSkillPrefabs/{_monsterSkillData.skillName}");
}
}
public override void Attack(GameObject target)
{
if (target == null) return;
_monsterBase.GetComponent<SpriteRenderer>().flipX = target.transform.position.x < _monsterBase.transform.position.x;
Vector3 spawnPosition = _monsterBase.transform.position - _skillOffset;
Object.Instantiate(_skill, spawnPosition, Quaternion.identity);
SkillAttack(_monsterSkillData.damage);
// 스킬 사용 후 쿨다운 시작
_lastSkillTime = Time.time;
IsAttackable = false;
// Debug.Log($"스킬 사용, 쿨다운 시작: {_monsterSkillData.cooldown}초");
}
public void SkillAttack(float skillDamage)
{
// 데미지 계산 (현재 임시 값)
DamageCalculator damageCalculator = new DamageCalculator();
float baseAttack = _monsterData.attackPower * skillDamage; // 기본 공격력 * 스킬 데미지
float equipmentAttack = 0; // 장비 공격력
float defense = PlayerDataManager.Singleton.player.defensivePower / (PlayerDataManager.Singleton.player.defensivePower + PlayerDataManager.Singleton.defensiveIntention); // 캐릭터 방어력
// 기본 데미지 계산 (치명타 없음)
float damage = damageCalculator.CalculateBaseDamage(baseAttack, equipmentAttack, defense);
_skill.SetSkillDamage(damage);
// Debug.Log($" 몬스터 스킬 공격! 최종 데미지: {damage}"); // 데미지 출력
}
public override void Update()
{
// 스킬 쿨다운 체크
if (!IsAttackable && Time.time - _lastSkillTime >= _monsterSkillData.cooldown)
{
IsAttackable = true;
// Debug.Log("스킬 쿨다운 완료");
}
}
public override bool IsSkillInCooldown()
{
return !IsAttackable;
}
}
}

View File

@@ -1,11 +0,0 @@
fileFormatVersion: 2
guid: 55724230a1ec9b5418a40829c72b81fa
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -171,9 +171,6 @@ namespace TON
// Idle로 변경 // Idle로 변경
if(_monsterBase.IsDetect== false) if(_monsterBase.IsDetect== false)
return new IdleState(); return new IdleState();
if (_monsterBase.IsSkillAttackable)
return new MonsterSkillState();
// Attack으로 변경 // Attack으로 변경
if (_monsterBase.IsAttacking) if (_monsterBase.IsAttacking)
@@ -240,60 +237,6 @@ namespace TON
return this; return this;
} }
} }
public class MonsterSkillState : IState
{
private const string AniAttack = "Attack"; // 공격 애니메이션
private MonsterBase _monsterBase;
private float _skillAttackAnimationDuration = 0.5f; // 공격 애니메이션 지속 시간
private float _skillAttackDelayTime = 10f; // 공격 딜레이 시간
private float _lastSkillAttackTime; // 마지막 공격 시간
private bool _isSkillAttacking;
public void Enter(MonsterBase monsterBase)
{
_monsterBase = monsterBase;
_lastSkillAttackTime = -_skillAttackDelayTime; // 처음 진입시 바로 공격하도록 설정
SkillAttack();
}
public void Update()
{
// 현재 공격 중이 아니고, 쿨다운이 지났다면 공격
if (!_isSkillAttacking && Time.time >= _lastSkillAttackTime + _skillAttackDelayTime)
{
SkillAttack();
}
// 공격 애니메이션 종료 체크
if (_isSkillAttacking && Time.time >= _lastSkillAttackTime + _skillAttackAnimationDuration)
{
_isSkillAttacking = false;
}
}
private void SkillAttack()
{
_monsterBase.ChangeAnimationState(AniAttack);
_monsterBase.MonsterSkillLaunch();
_lastSkillAttackTime = Time.time;
_isSkillAttacking = true;
}
public void Exit()
{
_isSkillAttacking = false;
}
public IState CheckTransition()
{
if(_isSkillAttacking == false)
return new IdleState();
return this;
}
}
public class HitState : IState public class HitState : IState
{ {