AchUtils
사용법

buff-debuff

# 버프 / 디버프 시스템

Duration, Stack, Tick, 우선순위를 설정하는 범용 버프 관리 파이프라인입니다. 독, 빙결, 공속 증가 등 어떤 효과든 BuffEffect를 상속해 추가합니다.

구조

BuffSystem (순수 C# 인스턴스)
  — 등록된 버프의 타이머·틱·만료 자동 처리

BuffDefinition (ScriptableObject)
  — 이름, 아이콘, Duration, Tick, Stack 설정
  [SerializeReference] List<BuffEffect>

BuffInstance (runtime)
  — 타겟에 적용된 버프의 실행 상태

BuffEffect (abstract, [Serializable])
  ├── DamageOverTimeEffect   — 틱마다 피해
  ├── StunEffect             — 이동 불가
  └── StatModifyEffect       — 스탯 모디파이어 자동 추가/제거

빠른 시작

1. BuffDefinition 에셋 만들기

Create → AchUtils/Buff/Buff Definition

BuffId          : "Poison"
DisplayName     : "독"
Duration        : 8
TickInterval    : 1          ← 1초마다 틱
MaxStacks       : 3
RefreshOnReapply: true

Effects:
  [0] DamageOverTimeEffect
        DamagePerTick: 15

2. BuffSystem 인스턴스 만들기

BuffSystemMonoBehaviour가 아니므로 필요한 소유 객체에서 직접 생성합니다. 지속 시간과 틱 처리를 위해 매 프레임 Tick을 호출합니다.

3. 버프 적용 / 제거

using AchUtils.Buff;

private readonly BuffSystem buffSystem = new();

[SerializeField] BuffDefinition poisonDef;
[SerializeField] GameObject target;

void Update()
{
    buffSystem.Tick(Time.deltaTime);
}

// 적용
buffSystem.Apply(poisonDef, target);

// 제거
buffSystem.Remove("Poison", target);

// 확인
bool hasPoisoned = buffSystem.Has("Poison", target);

// 모두 제거
buffSystem.RemoveAll(target);

API

BuffSystem

BuffInstance Apply(BuffDefinition definition, GameObject target)
bool         Remove(string buffId, GameObject target)
void         RemoveAll(GameObject target)
bool         Has(string buffId, GameObject target)
List<BuffInstance> GetBuffs(GameObject target)

void Tick(float deltaTime)

event Action<BuffInstance> OnBuffApplied
event Action<BuffInstance> OnBuffRemoved

BuffDefinition (Inspector)

필드설명
BuffId유일 식별자
Duration지속 시간 (초). -1 = 영구
TickInterval틱 간격 (초). 0 = 틱 없음
MaxStacks최대 중첩 수
RefreshDurationOnReapply재적용 시 Duration 초기화 여부

BuffInstance

BuffDefinition  Definition
GameObject      Target
int             Stacks
float           RemainingDuration
bool            IsPermanent
bool            IsExpired

내장 이펙트

DamageOverTimeEffect

float DamagePerTick   // 틱당 피해량 (스택에 비례)

타겟에 IDamageable 인터페이스가 필요합니다:

public class Player : MonoBehaviour, IDamageable
{
    public void TakeDamage(float amount)
    {
        hp -= amount;
    }
}

StunEffect

타겟에 IStunnable 인터페이스가 필요합니다:

public class PlayerController : MonoBehaviour, IStunnable
{
    private int _stunCount;

    public void ApplyStun()  => _stunCount++;
    public void RemoveStun() => _stunCount--;

    void Update()
    {
        if (_stunCount > 0) return; // 이동 불가
        // 이동 처리 ...
    }
}

StatModifyEffect

버프 적용/제거 시 StatSheetComponent의 스탯을 자동으로 추가/제거합니다.

// Inspector에서 설정
StatKey      : "Attack"
ModifierType : PercentAdd
Value        : 0.3          // 공격력 +30%

커스텀 이펙트 만들기

[Serializable]
public class FreezeEffect : BuffEffect
{
    public float SlowRatio = 0.5f;

    public override void OnApply(BuffInstance buff, GameObject target)
    {
        var rb = target.GetComponent<Rigidbody>();
        if (rb) rb.velocity *= (1f - SlowRatio);
    }

    public override void OnTick(BuffInstance buff, GameObject target)
    {
        // 매 틱 속도 억제
    }
}

활용 예시

독 (Poison)
  Duration: 8s, TickInterval: 1s, MaxStacks: 3
  DamageOverTimeEffect: 15 × 스택

빙결 (Freeze)
  Duration: 2s, MaxStacks: 1
  StunEffect

광전사 (Berserk)
  Duration: 10s, IsPermanent: false
  StatModifyEffect: Attack PercentAdd +0.5

저주 (Curse)
  Duration: -1 (영구), MaxStacks: 1
  StatModifyEffect: Defense Flat -20

스탯 모디파이어 연동

StatModifyEffect스탯 모디파이어 시스템과 자동으로 연동됩니다. 타겟에 StatSheetComponent가 있어야 합니다.

목차