본문으로 건너뛰기

버프 / 디버프 시스템

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

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