유니티 Stat ModifierUnity/Study2023. 12. 11. 21:14
Table of Contents
기능 소개
- 단순 Stat 값을 더하고 빼는게 아닌 Stat Modifier를 통한 관리
- 더티플래그(Dirty Flag) 디자인 패턴 사용
기능 구현
StatModifier
public enum StatModType
{
Flat,
PercentAdd,
PercentMult,
}
public class StatModifier
{
public readonly float Value;
public readonly StatModType Type;
public readonly int Order;
public readonly object Source;
public StatModifier(float value, StatModType type, int order, object source)
{
Value = value;
Type = type;
Order = order;
Source = source;
}
public StatModifier(float value, StatModType type) : this(value, type, (int)type, null) { }
public StatModifier(float value, StatModType type, int order) : this(value, type, order, null) { }
public StatModifier(float value, StatModType type, object source) : this(value, type, (int)type, source) { }
}
StatUnit
[Serializable]
public class StatUnit
{
public float BaseValue;
public virtual float Value
{
get
{
if (isDirty || BaseValue != lastBaseValue)
{
lastBaseValue = BaseValue;
_value = CalculateFinalValue();
isDirty = false;
}
return _value;
}
}
protected bool isDirty = true;
protected float _value;
protected float lastBaseValue = float.MinValue;
protected readonly List<StatModifier> statModifiers;
public readonly ReadOnlyCollection<StatModifier> StatModifiers;
public StatUnit()
{
statModifiers = new List<StatModifier>();
StatModifiers = statModifiers.AsReadOnly();
}
public StatUnit(float baseValue) : this()
{
BaseValue = baseValue;
}
public virtual void AddModifier(StatModifier mod)
{
isDirty = true;
statModifiers.Add(mod);
statModifiers.Sort(CompareModifierOrder);
}
public virtual bool RemoveModifier(StatModifier mod)
{
if (statModifiers.Remove(mod))
{
isDirty = true;
return true;
}
else
return false;
}
public virtual bool RemoveAllModifiersFromSource(object source)
{
bool didRemove = false;
for (int i = statModifiers.Count - 1; i >= 0; i--)
{
if (statModifiers[i].Source == source)
{
isDirty = true;
didRemove = true;
statModifiers.RemoveAt(i);
}
}
return didRemove;
}
protected virtual int CompareModifierOrder(StatModifier a, StatModifier b)
{
if (a.Order < b.Order)
return -1;
else if (a.Order > b.Order)
return 1;
else
return 0;
}
protected virtual float CalculateFinalValue()
{
float finalValue = BaseValue;
float sumPercentAdd = 0;
for (int i = 0; i < statModifiers.Count; i++)
{
StatModifier mod = statModifiers[i];
if (mod.Type == StatModType.Flat)
{
finalValue += mod.Value;
}
else if (mod.Type == StatModType.PercentAdd)
{
sumPercentAdd += mod.Value;
if (i + 1 >= statModifiers.Count || statModifiers[i + 1].Type != StatModType.PercentAdd)
{
finalValue *= 1 + sumPercentAdd;
sumPercentAdd = 0;
}
}
else if (mod.Type == StatModType.PercentMult)
{
finalValue *= 1 + mod.Value;
}
}
return (float)Math.Round(finalValue, 1); // 소수 첫째자리까지 반올림
}
}
'Unity > Study' 카테고리의 다른 글
유니티 로그라이크 방 생성 (0) | 2023.12.15 |
---|---|
유니티 Json 데이터 관리 (0) | 2023.12.12 |
유니티 Manager System (0) | 2023.12.05 |
유니티 2D 공 충돌 물리엔진 (0) | 2023.11.30 |
유니티 NPC 간단 대화 시스템 (0) | 2023.11.28 |