버프 / 디버프 시스템
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 인스턴스 만들기
BuffSystem은 MonoBehaviour가 아니므로 필요한 소유 객체에서 직접 생성합니다. 지속 시간과 틱 처리를 위해 매 프레임 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가 있어야 합니다.
:::