TIL

2024 10 31 TIL

noc777 2024. 10. 31. 21:16

이번 팀 프로젝트에서 선택한 과제 유형은 서바이벌 게임이다.  선택한 사유는 별이 세개긴 하지만 필수구현 같은 경우

강의에서 배운 내용을 토대로 하면 문제가 없을 것 같고 또한 4명 모두 서바이벌 게임에 대한 공부를 희망하기에

만장일치로 택하게 되었다.

 

오늘 내가 맡은 것은 체력 , 스테미나 등등 플레이어의 상태요소를 구현하는 것이다. 

우선 이러한 상태들을 Condition이라 명명하고 플레이어의 상태를 나타내는 것이기 때문에 Player 폴더에 새로 폴더를 추가하였다.   오늘 작성한 스크립트들을 테스트하기 위해선 UI를 작업해야하는데 아직 UI가 없어 일단 스크립트만 나열해놓고 작동이 되는지는 뒤에 확인하기로 한다.

public class Condition : MonoBehaviour 
{
    public float maxValue;
    private float curValue;
    public float passiveValue;

    private void Start()
    {
        curValue = maxValue;
    }

    public void SetValue(float valueData)
    {
        maxValue= valueData;
        curValue = maxValue; 
    }

    public void Add(float value)
    {
        curValue = Mathf.Min(curValue + value,maxValue);
    }

    public void Substract(float value)
    {
        curValue = Mathf.Max(curValue - value,0);
    }

    public float GetValue()
    {
        return curValue;
    }

    public float GetPercentage()
    {
        return curValue / maxValue;
    }
}

먼저 건강상태를 나타내는 Condition UI는 인스턴스로 활용하여 4개의 상태 모두 이것으로 나타낼 예정이다.  상태라고 하니 Enum을 따로 활용해보는 것이 어땠었나 싶긴한데 리팩토링에서 한번 다뤄보고싶다.

public class PlayerCoditions : MonoBehaviour
{
    //PlayerData playerdata

    public Condition health;
    public Condition stamina;
    public Condition hunger;
    public Condition thirst;

    private void Awake()
    {
        //playerdata = ChrarcterManager.instance.player.playerdata
        //health.SetValue(playerdata.hp)
        //stamina.SetValue(playerdata.st)
        //hunger.SetValue(playerdata.hg)
        //thirst.SetValue(playerdata.th)
    }

    private void Update()
    {
        hunger.Substract(hunger.passiveValue * Time.deltaTime);
        thirst.Substract(thirst.passiveValue * Time.deltaTime);
        if (thirst.GetValue() > 0.0f)
        {
            stamina.Add(stamina.passiveValue * Time.deltaTime);
        }

        Starve();
        Thirsty();

        if(health.GetValue() <= 0.0f)
        {
            Die();
        }
    }

    private void Starve()
    {
        if(hunger.GetValue() <= 0.0f)
        {
            health.Substract(health.passiveValue);
        }
    }
    private void Thirsty()
    {
        if (thirst.GetValue() <= 0.0f)
        {
            stamina.Substract(stamina.passiveValue);
        }
    }

    private void Die()
    {
        //추후 구현 논의
    }

    public void Heal(float value)
    {
        health.Add(value);
    }

    public void Eat(float value)
    {
        hunger.Add(value);
    }

    public void Drink(float value)
    {
        thirst.Add(value);
    }

    public bool StaminaConsumption(float value)
    {
        if (stamina.GetValue() - value < 0.0f)
        {
            return false; 
            //지침 패널티 부여 고민중
        }

        stamina.Substract(value);
        return true;
    }
}

PlayerCondition에선 나중에 PlayerData라는 스크립트를 만들었을 때  연결하기 위해 주석처리를 해놓았고 좀 더 세부적으로 상태들의 상태(?) 에 따라 어떤 메서드를 호출할지 정의해놓았다.

 

public class UIConditionData : MonoBehaviour
{
    private PlayerCoditions playerConditions;

    public Condition health { get { return playerConditions.health; } }
    public Condition stamina { get { return playerConditions.stamina; } }   
    public Condition hunger { get { return playerConditions.hunger; } }
    public Condition thirst { get { return playerConditions.thirst; } }

    private void Awake()
    {
        //playerCoditions = CharacterManager.instance.player.playerconditions;
    }

}

UIConditionData 는 Player의 Condition 들의 정보를 앞의 스크립트에서 받아와서 UI에 사용하기위해 미리 빼놓은 것이다.  이것도 나중에 연결을 위해 주석처리하였다.

 

public class ConditionUI : MonoBehaviour
{
    [SerializeField]
    protected UIConditionData data;

    protected float filledUIValue = 1.0f;
    protected Image valueBar;

    protected virtual void Start()
    {
        data = GetComponentInParent<UIConditionData>();
    }

    protected virtual void Update()
    {
        valueBar.fillAmount = filledUIValue;
    }
}

UI 게이지바를 구현하기 위해 총 4개의 스크립트가 게이지바가 달려있는 곳에 있어야하는데 기능이 전부 같기에 상속 개념을 사용하여 적용시켜보았다. UIConditionData 에서 값을 받아와서 자식 클래스들에 상속시키고 공통된 메서드들은 virtual 처리하였다.  게이지의 기본값을 1로 해놓은 이유는 혹시나 null상태라면 오류가 발생할 수 있기 때문이다.

public class HealthUI : ConditionUI
{
    protected override void Start()
    {
        base.Start();
    }

    protected override void Update()
    {
        base.Update();
    }

    private void SetHealthFilled()
    {
        filledUIValue = data.health.GetPercentage();
    }
}

 4개의 스크립트 전부 다른 데이터를 불러와야하기에 이렇게 작업하였다. 적어보고 나니 아직 SetHealthFillde 메서드를 호출 안해놨는데 내일 수정해야겠다.

 

강의 내용을 토대로 살짝 변형한 것이지만 아직 실험을 안해봐서 잘 작동하였으면 좋겠다는 바램이다.  일단 내일은 UI를 간단하게 만들어서 실험해봐야겠다.  

 

오늘 안 단축키 커맨드

ctrl +f (이름 찾기)

'TIL' 카테고리의 다른 글

2024 11 04 TIL  (0) 2024.11.04
2024 11 01 TIL  (0) 2024.11.01
2024 10 30 TIL  (0) 2024.10.30
2024 10 29 TIL  (0) 2024.10.29
2024 10 28 TIL  (0) 2024.10.28