Effect에 기능 확장에 대해서 질문이 있습니다.
149
작성한 질문수 10
강사님 Effect 에 추가적인 기능 구현에 대해 궁금한 점이 있어서 질문드립니다.
현재 강의의 Effect는 Start, Apply, Release의 세 가지 타이밍을 이용해서 여러 부가 효과를 주는 것으로 이해했습니다.(stat을 증가시키기, damage주기)
그런데 만약 죽음 저항, 마법 시전시 추가 피해,
,받는 화속성 피해 무효화, 특정 종족에게 가하는 피해 증가 등 다른 논리적인 코드 안에서 이 Effect의 여부를 따져야 하는 경우에는 어떤 식으로 처리할 수 있을까요?
예를 들어 죽음 저항의 Effect가 있다면
캐릭터의 TakeDamage의 코드 안에서
이 Effect의 여부를 따지는 부분이 필요할텐데
단순히 하드코딩으로 짜기엔 나중에 여러 효과들이 추가 되면 될 수록 감당할 수 없어질 것 같고 코드를 어떻게 확장 해야할지도 감이 잘 잡히지 않습니다.
제가 보기에도 질문이 조금 난해 하지만
결론은 이렇습니다.
effect가 다른 많은 코드들에 영향을 주어야 할 경우 어떻게 안전하게 확장 할 수 있을까요?
답변 2
1
수강해주셔서 감사합니다.
Effect를 다양한 상황에 적용시키기 위해서는 EffectAction의 Callback 함수를 연결할 수 있는 다양한 event들을 촘촘히 만들고, 때에 따라서는 특정 Damage 유형을 Stat으로 만드는 등 적절한 처리 방법을 고민해야합니다.
예를 들어, 죽으면 즉시 부활하는 효과라고 가정하면 아래와 같이 EffectAction을 만들 수 있을겁니다.
EffectAction.cs
public override Start(Effect effect)
{
effect.Owner.Owner.onTakeDamage += OnTakeDamage;
}
public override bool Apply(Effect effect)
{
// event를 통해 효과를 적용했다면, 상태를 리셋하고 true를 return
if (isApplied)
{
isApplied = false;
return true;
}
return isApplied;
}
public override Release(Effect effect)
{
effect.Owner.Owner.onTakeDamage -= OnTakeDamage;
}
public void OnTakeDamage(Entity target, float damage);
{
// 대상이 이번에 Damage를 받고 죽었다면 HP가 1인 상태로 부활시킴
if (target.IsDead)
{
target.HPStat.Value = 1f;
isApplied = true;
}
}
Effect가 실행될 때 Owner Entity의 onTakeDamage Event에 Callback 함수를 연결해두고, Entity가 죽으면 효과가 발동하는 형식입니다.
특정 종족에게 가하는 피해 증가는 종족 피해 배율을 Stat으로 만들 수 있을겁니다.
예를 들어, Elf 종족에 대한 Damage 증가를 담당하는 INCREASED_DAMAGE_TO_ELF Stat을 만들고, Effect는 Stat의 수치를 증가시키면 됩니다.
EffectAction.cs
public override Start(Effect effect)
{
}
public override bool Apply(Effect effect)
{
effect.Owner.Owner.Stats.SetBonusValue("STAT_INCREASED_DAMAGE_TO_ELF", this, 0.2f);
}
public override Release(Effect effect)
{
effect.Owner.Owner.Stats.RemoveBonusValue("STAT_INCREASED_DAMAGE_TO_ELF", this);
}// Entity.cs
public void GiveDamage(Entity target)
{
float damage = Stats.GetValue("DAMAGE");
if (target.Race == Race.Elf)
damage *= Stats.GetValue(STAT_INCREASED_DAMAGE_TO_ELF);
target.TakeDamage(damage)
}
위는 예시라서 if문으로 하드 코딩했지만, 제대로 만들 때는 Entity가 제대로된 종족 값을 가지도록 확장을 해야겠죠.
Damage 감소 같은건 Damage를 계산할 때 사용할 Action Callback들을 받아서
Invocation을 통해서 연결된 Action들을 순회하면서 최종 값을 구할 수 있습니다
EffectAction.cs
public override Start(Effect effect)
{
effect.Owner.Owner.CalcDamage += CalcDamage;
}
public override bool Apply(Effect effect)
{
// event를 통해 효과를 적용했다면, 상태를 리셋하고 true를 return
if (isApplied)
{
isApplied = false;
return true;
}
return isApplied;
}
public override Release(Effect effect)
{
effect.Owner.Owner.CalcDamage -= CalcDamage;
}
private float CalcDamage(Entity instigator, DamageType damageType, float damage)
{
// 공격한 적의 Damage Type이 화속성이면 Damage를 무묘화시킴.
if (damage > 0f && damageType == DamageType.Fire)
{
isApplied = true;
return 0f;
}
// 적의 Damage Type이 화속성이 아니라면 Effect가 작동하지않음
else
return damage;
}// TakeDamage 함수 안
// 연결된 Callback 함수들을 순회하며 최종 Damage 계산을 함.
// 위 Effect가 발동할 경우 최종 Damage는 0이 됨.
foreach (var calc in CalcDamage.GetInvocationList().Cast<CalcDamageHandler>())
damage = calc.Invoke(this, damageType, damage);
보시듯 복잡한 체계를 가진 전투 시스템은 복합적인 방식을 사용하여 구현하여야하기 때문에 모든 프로그래밍적 역량을 끌어올릴 필요가 있습니다. 그래서 RPG 게임 개발이 어렵다고 많이들 얘기하는 것입니다.
감사합니다.
0
아 코드 중간중간에 다른 복합적인 방식을 고려해야하는 곳에 콜백함수를 두어 Effect뿐 아니라 여러 다른 코드들에서도 추가적인 계산을 더할 수 있게 한다라는 규칙을 정하고,
Effect의 경우는 Start와 Release에서 이벤트의 등록과 해제를 통해 이 규칙을 이용해서 복합적인 기능을 구현한다. 라고 이해했는데 맞을까요?
1
네, 맞습니다.
효과를 만들 때는
"내가 만들려는 Effect가 Apply 함수를 구현하는 것만으로 충분할까?"
"안된다면 event에 Callback을 연결하는 방식으로 효과를 구현할 수 있을까?"
"구현할 수 있다면 어느 곳에 어떤 event를 만들어서 Callback을 연결해야할까?"
"이건 event로 구현하지말고 Stat으로 처리하는게 낫지 않을까?"
와 같이 다양한 고민이 필요합니다.
0
감사합니다.
추가로 질문이 하나 더 있습니다.
장비같은 아이템에도 특수 기능들이 필요할 경우
기존 Effect의 시스템을 이용해서 구현해도 괜찮을까요?
아니면 장비의 특수 기능은 Effect를 이용하지 않고 독립적으로 구현해야만 하나요?
0
안녕하세요, 인프런 AI 인턴입니다. 최성호님.
Effect가 여러 코드에 영향을 미칠 때 이를 안전하게 확장하기 위한 방법에 대한 질문을 주셨군요. 다양한 게임 메커니즘에서 발생할 수 있는 문제로, 확장을 고려한 설계가 필요합니다. 이에 대해 가능한 접근 방법을 소개드리겠습니다.
1. 이벤트 기반 시스템:
게임 로직에서 발생하는 주요 액션(예: 데미지, 마법 시전 등)은 이벤트로 처리하여 특정 Effect가 활성 상태인 경우 추가적인 로직을 실행할 수 있도록 합니다. 이렇게 하면 이러한 이벤트에 대해 여러 Effect가 순차적으로 반응할 수 있습니다.
예시 코드:
”`csharp
public class Entity : MonoBehaviour
{
public delegate void DamageTakenHandler(float damage);
public event DamageTakenHandler OnDamageTaken;public void TakeDamage(float damage)
{
OnDamageTaken?.Invoke(damage); // 데미지 계산 전에 모든 구독된 핸들러에 알림
// 데미지 처리 로직
}
}
public class DeathResistanceEffect : Effect
{
public DeathResistanceEffect(Entity entity)
{
entity.OnDamageTaken += CheckDeathResistance;
}
private void CheckDeathResistance(float damage)
{
// 죽음 저항 로직 구현
}
}
### 2. **효과 관리 시스템**:
- 각 Entity가 자신에게 활성화된 Effect 목록을 관리하게 하고, 특정 조건(예: 마법 시전, 피해 입음 등)이 만족될 때 이 목록을 조회하여 적용할 효과를 찾고 처리합니다.
- 예시 접근 방법:
```csharp
public class EffectManager
{
private List<Effect> activeEffects = new List<Effect>();
public void AddEffect(Effect effect)
{
activeEffects.Add(effect);
effect.Apply();
}
public bool CheckEffect<T>() where T : Effect
{
foreach (var effect in activeEffects)
{
if (effect is T)
{
return true;
}
}
return false;
}
}
// 사용 예시
if (effectManager.CheckEffect<DeathResistanceEffect>())
{
// 죽음 저항 효과가 있을 경우 처리 로직
}
3. 설계 패턴 활용:
- 컴포지트 패턴 또는 체인오브리스폰서빌리티 패턴을 활용하여, 각 Effect가 자기의 역할을 캡슐화하고 필요에 따라 다른 Effect와 조합할 수 있도록 합니다.
이와 같은 방법들은 코드의 확장성을 높이고, 다양한 효과를 추가하거나 조절할 때 강력한 유연성을 제공합니다. 특히 이벤트 기반 시스템은 단일 책임 원칙을 잘 지키면서 다양한 효과를 처리하는 데 유리합니다.
첨고로 관련된 질문에 대한 정보는 아래 링크들에서 보실 수 있습니다:
- 적 스킬 관련 질문
- 공격할 때마다 일정 확률로 추가 투사체 발사
저는 질문자님의 이해를 돕고자 지식공유자님의 기존 답변을 참고하여 유사한 답변 링크를 추천해드리고 있습니다.
현재 베타 기능으로 답변이 만족스럽지 않을 수 있는 점 양해 부탁드립니다. 🙏
추가적으로 궁금한 점이 있으시면, 이어서 질문해 주세요. 곧 지식공유자께서 답변해 주실 것입니다.
Indicator와 SelectionAction 및 SearchAction 간의 관계에 대해 질문있습니다.
0
70
2
ChargingState에서 질문이 있습니다.
0
49
1
Effect.GetData 함수 질문있습니다.
0
45
2
CanTransitionToSelf 질문 있습니다.
0
53
2
Stat의 MaxValue에 관하여 질문이 있습니다.
0
42
1
Stat vs StatScaleFloat
0
75
4
애니매이션 버그가 있는것 같습니다.
0
65
2
StatsOverride질문이 있습니다.
0
50
2
SetBonusValue함수 질문있습니다.
0
46
2
오늘 수강시작한 취준생입니다.
0
49
1
사소하지만 에디터 관련 질문있습니다
0
69
1
스킬시스템을 데이터 테이블화 하는 법에 대해 감이안잡혀서 질문드립니다.
0
144
2
TargetSearcher에 대해서 질문이 있습니다
0
52
1
돌진해서 몸박을하면 피격자를 날리면서 데미지를 입히는 스킬은 이 시스템에서 어떻게 만들 수 있을까요??
0
116
2
스킬 관련 질문입니다
0
110
2
통일된 Stat을 사용하지 않고 모듈화 방식으로 Stats를 만드신 이유가 궁금합니다.
0
152
1
SkillData 구조체 질문
0
122
1
스킬트리 저장 질문입니다
0
135
2
BT와 FSM을 활용해 몬스터 AI 구현
0
349
2
MonoStateMachine을 만든 이유가 잘 이해가 가지 않습니다.
0
128
1
근접 콤보 공격을 만들고 싶습니다.
0
153
1
하나의 스킬 내에서 타겟, 이펙트가 여러번 바뀌게 하는 방법이 궁금합니다.
0
190
1
올해에 예정된 새로운 강의가 있으신지요?
0
115
2
스킬트리 질문입니다
0
153
3





