부트캠프/Unity [ 스파르타 ]
[스파르타 ][TIL] 유니티 스파르타 7기 59일차 - Condition분리
맏난거
2025. 5. 2. 22:09
public class ExplosiveCondition<T> : UniTaskHandler, IConditionable where T : EntityController
{
private Coroutine dotCor;
private EnemyController enemyCtrl;
private MyUnitController myunitCtrl;
private float attackerDamage;
private float victimDefence;
private bool canHit = true;
private float coolDown = 0.0f;
private float time = 0.0f;
public ExplosiveCondition(T ctrl)
{
if (typeof(T) == typeof(EnemyController))
this.enemyCtrl = ctrl as EnemyController;
else
this.myunitCtrl = ctrl as MyUnitController;
}
/// <summary>
/// 나중에 저장을 추가하면, 참조 값이라 값타입이나 타워에서 디폴트 참조타입이 아닌 변하는 타입을 가져와야됨
/// </summary>
/// <param name="attackerDamage"></param>
/// <param name="values"></param>
public void Execute(float attackerDamage, AbilityDefaultValue values)
{
TokenDisable();
TokenEnable();
time = values.AbilityDuration;
coolDown = 0f;
if (typeof(T) == typeof(EnemyController))
victimDefence = enemyCtrl.Status.Defence.GetValue();
else
victimDefence = myunitCtrl.MyUnitStatus.Defence.GetValue();
OnDotDamage(values.AbilityValue, values.AbilityDuration, values.AbilityCooldown).Forget();
}
public void Init()
{
Init();
}
async UniTaskVoid OnDotDamage(float abilityValue, float abilityDuration, float abilityCooldown)
{
while (time > 0)
{
time -= Time.deltaTime;
if (canHit)
{
AddHealth(-abilityValue);
// 0초라서 수정해야됨 최소한 0.2초가 적당한듯?
coolDown = 0.2f;
canHit = false;
}
else if (coolDown <= 0.0f)
{
canHit = true;
}
coolDown -= Time.deltaTime;
await UniTask.NextFrame(disableCancellation.Token);
}
}
private void AddHealth(float damage)
{
if (typeof(T) == typeof(EnemyController))
{
enemyCtrl.Status.AddHealth(damage, enemyCtrl.ConditionHandlers[(int)AbilityType.Explosive].Attacker.gameObject);
enemyCtrl.Fx.StartBlinkRed();
}
/* else
myunitCtrl.MyUnitStatus.AddHealth(damage, enemyCtrl.ConditionHandlers[(int)AbilityType.Explosive].Attacker.gameObject);*/
}
// 나중에 공통적인건 묶어줄 필요가 있음
// 공통적으로 묶어주면 기본 베이스에만 접근해두 되기때문에 if체크할 필요가 없어진다
private Coroutine StartCoroutine(IEnumerator coroutine)
{
if (typeof(T) == typeof(EnemyController))
{
return enemyCtrl.StartCoroutine(coroutine);
}
return myunitCtrl.StartCoroutine(coroutine);
}
}
int iCondition = (int)condition; // Enum타입을 int형으로
if(Times.ContainsKey(iCondition)) // 현재 컨디션이 있는지 체크
{
if (Times[iCondition] <= 0f) // 현재 컨디션 적용 시킬 수 있는지 체크
{
Times[iCondition] = ConditionHandlers[iCondition].CoolDown;
ConditionHandlers[iCondition].Attacker = go.transform;
if (Conditions.ContainsKey(iCondition)) // 컨디션이 있는지 체크
Conditions[iCondition].Execute(incomingDamage, values);
else // 없으면 추가 하라는 경고문구
Util.LogWarning($"{enemyName}에 현재 키로된 Conditions가 없습니다.");
}
}
else
{
// 실수 방지 경고로그
if (Conditions.ContainsKey(iCondition))
Util.LogWarning($"{enemyName} 바디에 {condition}키를 추가해주세요");
}
자주 코루틴스타트를 호출해야되니 부담이 될꺼같아
UniTask를 이용했습니다. 현재 만드는 프로젝트에 새로운 컨디션을 추가할때마다 if else문이 아닌 클래스로 추가를 할 수 있게 만들어보았습니다.