[TIL] 50일 차 - 반응형 프로퍼티(ReactiveProperty)

ChangBeom·2025년 4월 11일

TIL

목록 보기
51/53
post-thumbnail

UI작업을 하면서 어떤 값이 바뀌면 UI에 바로 적용되도록 구현하고 싶어서 알아보던 중 "반응형 프로퍼티"의 개념을 알게되어서 정리해보려고 한다.


[반응형 프로퍼티(ReactiveProperty)란?]

반응형 프로퍼티는 간단하게 설명하면 값이 바뀌면 자동으로 등록된 이벤트가 실행되는 구조이다. 데이터가 UI같은 다른 로직에 연결되어 있을 때, 변화를 감지하고 자동으로 동작하도록 구성할 수 있다.

이런 개념을 통해 몬스터를 소환할 때 사용하는 게이지를 만들고, 게이지를 소모할 시 바로 Fill Type Image의 Fill Amount값을 변경해보려고 한다.

<반응형 프로퍼티 스크립트>

using System;

[Serializable]
public class ReactiveProperty<T> where T : struct
{
    private T value;

    private Action<T> actions;

    public T Value
    {
        get
        {
            return value;
        }
        set
        {
            if(Equals(this.value,value))
            {
                return;
            }
            this.value = value;
            actions?.Invoke(this.value);   
        }
    }

    public void AddAction(Action<T> action)
    {
        this.actions += action;
    }

    public void RemoveAction(Action<T> action)
    {
        this.actions -= action;
    }

    private void OnDestroy()
    {
        actions = null;
    }
}

해당 코드가 반응형 프로퍼티이다. 프로퍼티의 설정자 부분을 보면 값이 동일할 때는 리턴하고, 값이 변경되었을 때 등록된 이벤트를 호출하는 방식이다. 그래서 반응형 프로퍼티를 초기화할 때 AddAction을 통해 함수를 등록해두면 자동으로 프로퍼티의 값이 변경될 때 이벤트 함수를 호출하는 것이다.

아래 코드는 반응형 프로퍼티로 만든 게이지 값을 Image에 바로 적용하는 코드이다.

using UnityEngine;
using UnityEngine.UI;

public class GaugeUI : MonoBehaviour
{
    private Image fillImage;

    private ReactiveProperty<float> cur;
    private ReactiveProperty<float> max;

    private void Awake()
    {
        fillImage = GetComponent<Image>();
    }

    // 반응형 프로퍼티로 현재 게이지와 최대 게이지를 바인딩
    public void Bind(ReactiveProperty<float> curGauge, ReactiveProperty<float> maxGauge)
    {
        cur = curGauge;
        max = maxGauge;

        cur.AddAction(UpdateFill);
        max.AddAction(UpdateFill);

        UpdateFill(cur.Value);
    }

    // 반응형 프로퍼티의 값이 변경되면 실행할 함수. 값에 따라 이미지의 fillAmount가 바뀜
    private void UpdateFill(float useless)
    {
        if (max == null || max.Value <= 0f)
        {
            return;
        }

        fillImage.fillAmount = Mathf.Clamp01(cur.Value / max.Value);
    }

    // 메모리 누수 방지용 자산해제
    private void OnDestroy()
    {
        if (cur != null)
        {
            cur.RemoveAction(UpdateFill);
        }

        if (max != null)
        {
            max.RemoveAction(UpdateFill);
        }
    }
}

이런식으로 반응형 프로퍼티를 사용해서 프로퍼티를 UI에 바인딩해두면 프로퍼티의 값이 변경될 때 UI에 자동으로 적용된다.
아래 영상은 몬스터를 소환하면 반응형 프로퍼티로 설정된 게이지 value가 감소하고, 감소될 때 자동으로 게이지UI에 적용되는 모습이다.

  • 위 영상에서 잘 보이진 않지만 12시 방향의 타이머도 반응형 프로퍼티를 이용해서 제작했다.

0개의 댓글