본문 바로가기
개발일지/게임개발

[Unity]Project_DT - 상태이상 구현

by 라이티아 2025. 11. 5.
public class Enemy : Character
{
    private bool _acting = false;
    private int? _pendingNext = null;
    [SerializeField]
    private List<EnemyState> _states = new List<EnemyState>();

    [Header("현재 상태")]
    [SerializeField]
    private EnemyState _currentState = null;

    // 콜백 묶음
    private Action<int> _requestChange;
    private Action _reportDone;
    void Awake()
    {
        _states = GetComponentsInChildren<EnemyState>(true).ToList();
        foreach (var state in _states)
        {
            state.gameObject.SetActive(false);
        }
        _requestChange = ChangeState;
        _reportDone = OnActionDone;
        // 모든 상태에 주입
        foreach (var state in _states)
            state.BindCallbacks(_requestChange, _reportDone);
    }​
    public void ApplyBleeding()
    {
        
    }

현재 상태이상을 구현하려 한다

 

대충 생각은 string, int, int값을 가진 구조체를 미리 세팅하고, 해당 구조체에 여러 값을 확인, 연산하여 처리하려 한다

using UnityEngine;

[System.Serializable]
public class StatusAbnormality
{
    [Header("상태이상 이름")]
    public string Name;
    [Header("가중치")]
    public int Amount;
    [Header("지속 턴")]
    public int HoldingTime;
    
    public StatusAbnormality(string Name, int Amount, int HoldingTime)
    {
        this.Name = Name;
        this.Amount = Amount;
        this.HoldingTime = HoldingTime;
    }
}

해당 클레스가 상태이상 데이터들을 저장한다

public class Character : MonoBehaviour
{
	[Header("상태이상 리스트")]
    [SerializeField]
    private List<StatusAbnormality> _statusAbnormalitys = new List<StatusAbnormality>();
    
    public void ApplyBleeding(int amount, int HoldingTime)
    {
        _statusAbnormalitys[(int)StatusAbnormalityNumber.bleeding].Amount += amount;
        _statusAbnormalitys[(int)StatusAbnormalityNumber.bleeding].HoldingTime += HoldingTime;
    }
}

이를 리스트로 가지고 있으면서 값을 핸들링해 준다

    /// <summary>
    /// target에게 출혈 효과 부여
    /// </summary>
    /// <returns></returns>
    public void ApplyBleeding(Character target, int amount, int holdingTime)
    {
        target.ApplyBleeding(amount, holdingTime);
    }
using UnityEngine;

public class BleedingEffect : CardEffect
{
    public void Execute(Character target, int amount, int holdingTime)
    {
        BattleManager.Instance.ApplyBleeding(target, amount, holdingTime);
    }
}

해당 함수를 호출하기 위해 effect와 battlemanager를 연결해 준다

 

이제 해당 기능을 CardDataBase에 연결한다

 

    public enum EffectNum
    {
        Damage,
        Defence,
        Bleeding
    }
    
        Effects.Add(new DamageEffect());
        Effects.Add(new DefenceEffect());
        Effects.Add(new BleedingEffect());
   
       [SerializeField]
    private List<CardEffect> Effects;
        
    public CardEffect GetCardEffect(string effectName)
    {
        if (effectName == "Damage")
        {
            return Effects[(int)EffectNum.Damage];
        }
        else if (effectName == "Defence")
        {
            return Effects[(int)EffectNum.Defence];
        }
        else if (effectName == "Bleeding")
        {
            return Effects[(int)EffectNum.Bleeding];
        }
        Debug.Log("없는 개념에 대한 것을 가져오려함");
        return null;
    }

하는 김에 list를 통해 좀 더 가독성 좋게 정리한다

 

테스트 결과, 에러가 나온다

없는 list 위치를 지정하고 있다

 

    [Header("상태이상 리스트")]
    [SerializeField]
    private List<StatusAbnormality> _statusAbnormalitys = new List<StatusAbnormality>();

    [Header("상태 표시줄")]
    [SerializeField]
    private StatusBar _statusBar;

    void Awake()
    {
        _stats = new Stats();
        TurnManager.Instance.OnTurnChanged += ResetShield;

        InitStatusAbnormality();
    }
    private void InitStatusAbnormality()
    {
        _statusAbnormalitys.Add(new StatusAbnormality("출혈", 0, 0));
    }

지금 해당 코드에서 상태이상을 추가해주지 못하고 있다

 

확인해보니 플레이어는 정상적으로 들어가는데, 적 객체가 효과 클레스를 만들지 못하고 있다

public class Character : MonoBehaviour
{
    public enum StatusAbnormalityNumber
    {
        bleeding
    }
    [SerializeField]
    private Stats _stats;

    [SerializeField]
    private TurnManager.TurnOwner _identity = TurnManager.TurnOwner.Player;

    public Stats Stats
    {
        get => _stats;
    }

    [Header("상태이상 리스트")]
    [SerializeField]
    private List<StatusAbnormality> _statusAbnormalitys = new List<StatusAbnormality>();

    [Header("상태 표시줄")]
    [SerializeField]
    private StatusBar _statusBar;

    void Awake()
    {
        _stats = new Stats();
        TurnManager.Instance.OnTurnChanged += ResetShield;

        if (_statusAbnormalitys == null)
            _statusAbnormalitys = new List<StatusAbnormality>();

        InitStatusAbnormality();
    }

현재 적 객체쪽에서 awake를 덮어쓰고 있어서 제대로 된 처리를 못하고 있다

 

    protected override void Awake()
    {
        base.Awake();
        _states = GetComponentsInChildren<EnemyState>(true).ToList();
        foreach (var state in _states)
        {
            state.gameObject.SetActive(false);
        }
        _requestChange = ChangeState;
        _reportDone = OnActionDone;
        // 모든 상태에 주입
        foreach (var state in _states)
            state.BindCallbacks(_requestChange, _reportDone);
    }

오버라이드를 하는 것으로 처리를 해준다

 

정상적으로 잘 들어가는 것을 확인할 수 있다

 

가중치도 잘 반영된다

 

이제 양자택일의 출혈 기능이 있다

 

가중치와 지속턴을 계속해서 누적하는 형식으로 갈 것인가 vs 각각 개별의 처리로 남길것인가