[Unity3D] UI 및 상태 업데이트

김소연·2025년 3월 4일

1. Condition.cs - 체력, 허기, 스태미나 등의 상태를 관리하는 클래스 (플레이어뿐만 아니라 몬스터, NPC에도 적용 가능)
2. UIConditions.cs - UI와 상태를 연결하는 클래스 (UI를 따로 관리해서 재사용 가능)
3. PlayerCondition.cs - 플레이어의 상태와 관련된 로직을 담당 (플레이어의 상태를 별도로 관리)
4. Player.cs - 플레이어의 기본 속성
수정 시 다른 코드에 영향을 덜 주고 유지보수가 쉬워지도록 모듈화
-> 컴포넌트 기반 설계 (Component-Based Design)

  • 재사용성 (Reusability)
    condition 클래스는 범용적(Generalized) 으로 설계되어 있어 나중에 새로운 상태를 추가하려고 하면 그냥 하나 더 선언하면 됨
public Condition mana;
  • 유지보수 & 확장성 (Maintainability & Scalability)
    PlayerCondition에서 health, hunger, stamina를 uiCondition을 통해 가져오도록 설계한 이유는 UI와 로직을 분리하기 위함

    UI를 수정하고 싶을 때, UIConditions.cs만 수정
    게임 로직을 수정하고 싶을 때, Condition.cs나 PlayerCondition.cs만 수정

MVC 패턴(Model-View-Controller) 과도 비슷하다

1)Model (데이터, 상태)
Condition.cs → 체력, 허기, 스태미나 데이터를 관리하는 모델 역할
2)View (UI)
UIConditions.cs → UI 상태바를 업데이트하는 역할
3)Controller (로직)
PlayerCondition.cs → 상태 변화를 관리하는 역할


1. Condition.cs

캡슐화(Encapsulation) → Condition 클래스가 자신의 데이터(curValue, maxValue)를 보호하고, Add()나 Substract() 메서드를 통해서만 수정 가능

a. 필요한 변수 : 현재 value, 최대 value, 시작 value, 패시브 value, UIBAR 이미지

public float curValue; 
public float maxValue;

public float startValue;
public float passiveValue; // 계속 차오르는

public Image uiBar; // 상태바

b. 초기화

public void Start()
{
    curValue = startValue;
}

c. 현재 value에서 증가/감소

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


private void Substract(float amount)
{
    curValue = Mathf.Max(curValue - amount, 0f);
}
  • Mathf.Min을 쓰는 이유는, 증가된 curValue가 maxValue을 초과하지 않아야 하기 때문에
    둘 중에 더 낮은 값을 선택하도록 함
  • 마찬가지로 Mathf.Max를 쓰는 이유는, 감소된 curValue가 0 밑으로 내려가면 안되기 때문

d. ui의 상태바에 반영

public float GetPercentage()
    {
        return curValue / maxValue;
    }
 private void Update()
 {
     uiBar.fillAmount = GetPercentage();
 }

2. UIConditions.cs

a. 나타낼 상태 선언

public Condition health;
public Condition hunger;
public Condition Stamina;

b.

private void Start()
{
   CharacterManager.Instance.Player.condition.uiCondition = this;
}

3. Player.cs 수정

public PlayerCondition condition;

private void Awake()
{
condition = GetComponent<PlayerCondition>();
}

4. PlayerCondition.cs

a. 선언

  public UIConditions uiCondition;

  Condition health { get { return uiCondition.health; } }
  Condition hunger { get { return uiCondition.hunger; } }
  Condition stamina { get { return uiCondition.stamina; } }
  
  public float noHungerHealthDecay; // 허기가 0일 때 사용할 값

b. 조건 추가

private void Update()
{
    // 시간이 흐르면서 허기가 감소 (패시브)
    hunger.Substract(hunger.passiveValue * Time.deltaTime);

    // 시간이 흐르면서 스태미나 증가 (패시브)
    stamina.Add(stamina.passiveValue * Time.deltaTime);

    // 허기가 0이면 시간이 지나면서 체력 감소 
    if (hunger.curValue <= 0f)
    {
        health.Substract(noHungerHealthDecay * Time.deltaTime);
    }
    // 체력이 0이면 사망
    if (health.curValue <= 0f) { Die(); }
}

❓ 여기서 health.curvalue < 0인 이유
부동소수점 연산을 거치면서 0을 딱 맞추기 어렵다.
예를 들어 체력이 0.1이 남은 상태에서 0.2의 데미지를 입으면 -0.1이 되고, 죽어야 한다.
그러나 health.curvalue == 0이라고 조건을 달면, 죽어야 함에도 죽지 않는다.
체력이 0 이하가 되는 순간을 감지하는 것이 목적이라면, health.curValue <= 0이 더 안전하며
앞서 curValue = Mathf.Max(curValue - amount, 0f);가 있기 때문에, 어차피 0 밑으로 안 내려간다.

c. 회복

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

d. 섭취

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

e. 죽음

public void Die()
    {
        Debug.Log("플레이어가 죽었다.");
    }
  1. 스크립트 연결
    Conditions의 canvas

    player에 playerConditions 컴포넌트 추가

0개의 댓글