AchUtils
사용법

ach

# Ach — 공유 변수 & 이벤트

값과 신호를 ScriptableObject 에셋으로 만들어, 컴포넌트끼리 서로를 직접 참조하지 않고도 데이터를 공유하고 신호를 주고받는 시스템입니다.

플레이어 체력을 PlayerHP 라는 에셋 파일로 만들어 두면, 체력바 UI·피격 사운드·게임오버 매니저가 모두 같은 에셋을 바라봅니다. 누가 누구를 참조하는지 인스펙터 선을 그릴 필요 없이, 값이 바뀌면 알아서 동기화됩니다.

왜 쓰나요?

일반적인 방식                         Ach 방식
─────────────────────────            ─────────────────────────
UI 가 Player 를 직접 참조             UI 와 Player 가 PlayerHP 에셋을 공유
씬이 바뀌면 참조가 끊김                에셋이라 씬과 무관하게 유지
매 프레임 player.Hp 폴링               값이 바뀔 때만 콜백
누가 값을 바꾸는지 추적 어려움          이벤트로 흐름이 명확

5가지 구성 요소

요소한 줄 설명예시 클래스
Variable값 하나를 담는 에셋IntVariable, FloatVariable
Event값을 실어 보내는 신호 에셋IntEvent, VoidEvent
Listener이벤트 → UnityEvent 로 반응하는 컴포넌트IntEventListener
Reference상수 ↔ 변수 에셋을 인스펙터에서 토글IntReference
Collection런타임에 공유되는 목록 에셋GameObjectCollection

기본 제공 타입: Int / Float / Bool / String / Vector2 / Vector3 / Color / GameObject (+ 신호 전용 Void).

우클릭으로 에셋 만들기

Project 뷰에서 우클릭 → Create → AchUtils → Ach 아래에서 바로 생성합니다.

Create ▸ AchUtils ▸ Ach ▸ Variables    ▸ Int / Float / Bool / String / Vector2 / Vector3 / Color / GameObject Variable
                        ▸ Events       ▸ Void / Int / Float / ... Event
                        ▸ Collections  ▸ GameObject Collection

리스너는 컴포넌트입니다 — Add Component → AchUtils → Ach → Int Event Listener.

빠른 시작

1. Variable — 값을 에셋으로 공유

Create → AchUtils/Ach/Variables/Int VariablePlayerHP 에셋을 만듭니다.

using AchUtils.Ach;
using UnityEngine;

public class Player : MonoBehaviour
{
    [SerializeField] IntVariable hp;     // PlayerHP 에셋을 드래그

    public void TakeDamage(int amount)
    {
        hp.Value -= amount;              // 값이 바뀌면 구독자에게 자동 통지
    }
}

public class HealthBar : MonoBehaviour
{
    [SerializeField] IntVariable hp;     // Player 와 같은 PlayerHP 에셋
    [SerializeField] UnityEngine.UI.Slider slider;

    void OnEnable()  => hp.OnChanged += Refresh;   // 값이 바뀔 때만 호출
    void OnDisable() => hp.OnChanged -= Refresh;

    void Refresh(int value) => slider.value = value;
}

PlayerHealthBar 는 서로를 전혀 모르지만 PlayerHP 에셋을 통해 연결됩니다.

2. Event — 신호 보내기

값이 필요 없는 알림은 Void Event, 값을 함께 보내려면 타입 이벤트를 씁니다.

[SerializeField] VoidEvent onPlayerDied;
[SerializeField] IntEvent  onGoldChanged;

void Die()            => onPlayerDied.Raise();
void AddGold(int now) => onGoldChanged.Raise(now);

3. Listener — 코드 없이 반응 연결

반응할 오브젝트에 Add Component → AchUtils/Ach/Int Event Listener 를 붙이고, 인스펙터에서 Event 칸에 onGoldChanged, Response 칸에 호출할 메서드를 드래그합니다. 디자이너가 코드 없이 사운드·이펙트를 연결할 수 있습니다.

4. Reference — 상수와 변수 사이 전환

값을 상수로 박을지, 공유 변수 에셋으로 뺄지 인스펙터에서 체크박스로 고릅니다.

[SerializeField] FloatReference moveSpeed;   // Use Constant 켜면 상수, 끄면 변수 에셋

void Update()
{
    transform.position += dir * moveSpeed.Value * Time.deltaTime;
}

프로토타입은 상수로 빠르게, 밸런싱 단계엔 같은 변수 에셋을 여러 곳에서 공유하도록 코드 수정 없이 전환합니다.

5. Collection — 런타임 목록 공유

Create → AchUtils/Ach/Collections/GameObject CollectionAliveEnemies 를 만듭니다.

[SerializeField] GameObjectCollection aliveEnemies;

void OnEnable()  => aliveEnemies.Add(gameObject);
void OnDisable() => aliveEnemies.Remove(gameObject);

// 다른 시스템에서: 남은 적이 0이면 웨이브 클리어
if (aliveEnemies.Count == 0) WaveCleared();

API

AchVariable<T>

T    Value                          // 대입 시 값이 바뀌면 OnChanged 발생
T    InitialValue                   // 플레이 시작 시 적용되는 초기값
void SetValue(T value)              // 같으면 무시
void SetValueAndForceRaise(T value) // 같아도 강제 통지
void ResetToInitialValue()

event Action<T>    OnChanged             // (새 값)
event Action<T, T> OnChangedWithHistory  // (이전 값, 새 값)

AchEvent<T> / VoidEvent

void Raise(T value)                 // VoidEvent 는 Raise()
void Register(Action<T> handler)
void Unregister(Action<T> handler)
T    LastValue                      // 마지막으로 보낸 값 (디버그)

AchReference<T, TVariable>

T          Value                    // UseConstant 면 상수, 아니면 변수 값
bool       UseConstant
T          ConstantValue
TVariable  Variable
// implicit operator T — 그냥 값처럼 바로 사용 가능

AchCollection<T>

int  Count
T    this[int index]
void Add(T item)
bool AddIfMissing(T item)
bool Remove(T item)
bool Contains(T item)
void Clear()

event Action<T> OnAdded
event Action<T> OnRemoved
event Action    OnCleared

에디터 편의 기능

  • 변수 인스펙터 — 플레이 중 현재 값이 실시간 표시되고, Reset To Initial Value 버튼으로 즉시 초기화합니다.
  • VoidEvent 인스펙터 — 플레이 중 Raise 버튼으로 이벤트를 수동 발생시켜 리스너 연결을 바로 테스트합니다.
  • 자동 리셋 — 변수·컬렉션은 플레이에 들어갈 때 초기값/빈 상태로 되돌아가, 도메인 리로드를 꺼도 매 실행이 깨끗하게 시작합니다.

새 타입 추가하기

기본 타입 외의 값(예: Quaternion)이 필요하면 한 줄짜리 서브클래스만 만들면 됩니다.

using UnityEngine;
using AchUtils.Ach;

[CreateAssetMenu(menuName = "AchUtils/Ach/Variables/Quaternion Variable")]
public class QuaternionVariable : AchVariable<Quaternion> { }

[CreateAssetMenu(menuName = "AchUtils/Ach/Events/Quaternion Event")]
public class QuaternionEvent : AchEvent<Quaternion> { }

[System.Serializable]
public class QuaternionUnityEvent : UnityEngine.Events.UnityEvent<Quaternion> { }

public class QuaternionEventListener
    : AchEventListener<Quaternion, QuaternionEvent, QuaternionUnityEvent> { }

언제 쓰면 좋은가

씬·프리팹 경계를 넘어 값/신호를 공유해야 할 때 가장 빛납니다. 한 GameObject 안에서만 쓰는 값이라면 일반 필드가 더 간단합니다.

목차