SkillBase / SkillSpec / SkillActorInfo 소스 코드
SkillControlComponent 소스 코드
SkillActorInfo를 통해 스킬 소유자/캐릭터/컨트롤러 자동 연결Tick 기능 지원 (bCanTick 설정)EndSkill 호출 (bHasSkillDuration 설정)| 클래스 및 구조체 | 설명 |
|---|---|
UDSSkillBase | 모든 스킬의 최상위 클래스. 스킬 생명주기와 실행 흐름 정의 |
FDSSkillSpec | 스킬의 데이터(Handle, Tag, Type, Instancing 등)와 상태 보관 |
FDSSkillSpecContainer | SkillSpec 배열을 관리하고 복제 최적화를 담당 |
UDSSkillControlComponent | 스킬 소유자(Actor)에 붙어 스킬 추가, 활성화, 취소, 종료를 관리 |
FDSSkillActorInfo | 스킬 실행 주체(Owner, Avatar, Controller 등)에 대한 정보 저장 |
UDSSkillControlComponent → FDSSkillSpecContainer
스킬 스펙 배열(컨테이너)을 관리
FDSSkillSpecContainer → FDSSkillSpec
각 스킬의 데이터/상태를 관리
FDSSkillSpec → UDSSkillBase
실제 스킬 로직 인스턴스를 참조
FDSSkillSpec → FDSSkillActorInfo
스킬 실행 주체 정보(Owner, Avatar 등)를 참조
UDSSkillControlComponent → UDSSkillBase
FDSSkillSpec을 통해 UDSSkillBase 인스턴스를 간접 관리하여 스킬 실행 흐름을 제어
AddSkill : 새로운 스킬을 SkillSpecContainer에 등록하고 초기화한다.TryActivateSkill : 조건을 검사하고 스킬을 활성화하려고 시도한다.RemoteEndOrCancelSkill : 외부 요청에 따라 스킬을 강제 종료하거나 취소한다.ReplicateEndOrCancelSkill : 스킬 종료/취소 이벤트를 네트워크로 동기화한다.OnRemoveSkill : 스킬을 컨트롤러에서 제거하고 인스턴스를 정리한다.MarkSkillSpecDirty : SkillSpec이 변경되었음을 엔진에 알리고 복제를 트리거한다.AddReplicatedInstancedSkill : 복제 대상 스킬 인스턴스를 등록한다.CreateNewInstanceOfSkill : Skill CDO를 기반으로 새로운 스킬 인스턴스를 생성한다.ScheduleSkillEnd : 설정한 Duration 이후 스킬을 자동으로 종료(EndSkill)하도록 예약한다.InternalTryActivateSkill : 스킬 활성화 조건을 검사하고, 조건이 맞으면 스킬을 실제로 실행 및 인스턴싱을 처리한다.TickComponent : 현재 활성 상태인 스킬 인스턴스들을 순회하면서, 각 스킬의 InternalTick(DeltaTime)을 호출해 업데이트한다.GetPrimaryInstance : 가장 우선순위 높은 스킬 인스턴스를 반환한다.ShouldReplicateSkillSpec : 이 스킬 스펙이 네트워크 복제 대상인지 판단한다.GetSkillInstances : 현재 가지고 있는 모든 스킬 인스턴스(복제/비복제)를 반환한다.IsActive : 스킬이 현재 활성 상태인지 확인한다.PreReplicatedRemove : 복제된 스킬이 제거될 때 처리(컨트롤 컴포넌트에 알림).PostReplicatedAdd : 복제된 스킬이 추가될 때 처리(컨트롤 컴포넌트에 알림).GetDebugString : 스킬에 대한 디버깅용 문자열을 반환한다.RegisterWithOwner : 스킬 스펙 컨테이너를 소유 컴포넌트와 연결하고 복제 시스템에 등록한다.ShouldWriteFastArrayItem : 스킬 스펙 개별 항목의 복제 여부를 판단한다 (Dirty 여부 체크).Items : 스킬 상태 전체를 담고 네트워크 복제를 최적화하는 핵심 데이터 배열.CanActivateSkill : 스킬이 발동 가능한지 조건(쿨다운, 리소스 등)을 검사한다.PreActivate : 스킬 활성화 직전 상태 초기화 및 사전 처리를 수행한다.ActivateSkill : 스킬의 실제 동작을 구현하는 함수(자식 클래스가 오버라이드).CommitSkill : 쿨다운 시작, 리소스 소모 등을 확정(commit) 처리한다.CancelSkill : 외부 요인에 의해 스킬을 강제 취소하고 정리한다.EndSkill : 스킬이 스스로 종료될 때 호출되어 종료 처리를 수행한다.ApplyCooldown : 스킬에 쿨다운을 적용하여 재사용 대기 시간을 설정한다.OnSkillInitialized : 스킬이 SkillControlComponent에 추가되었을 때 초기화 처리를 한다.Tick : SkillControlComponent가 매 프레임 수동 호출하여 스킬 상태를 갱신한다.void UDSSkillBase::Tick(float DeltaTime)
{
ElapsedTime += DeltaTime;
if (ElapsedTime >= TickInterval)
{
InternalTick(DeltaTime);
ElapsedTime = 0.0f;
}
}
InternalTick에서 TickInterval마다 호출해야 하는 코드를 구현한다.void UDSSkillControlComponent::TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction)
{
Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
for (const FDSSkillSpec& ActiveSpec : ActivatableSkills.Items)
{
UDSSkillBase* SkillInstance = ActiveSpec.GetPrimaryInstance();
UDSSkillBase* SkillSource = ActiveSpec.Skill;
if (false == IsValid(SkillSource))
{
continue;
}
if (SkillSource->bCanTick && ShouldTick(SkillSource))
{
if (IsValid(SkillInstance))
{
if(SkillInstance->IsActive())
{
SkillInstance->Tick(DeltaTime);
}
}
else if (SkillSource->IsActive())
{
SkillSource->Tick(DeltaTime);
}
}
}
}
SkillControlComponent에서는 실행 중이고, bCanTick이 true이고, 네트워크 정책에 따라 Tick이 실행될 수 있는 스킬 인스턴스가 Tick 함수를 호출한다.InternalTryActivateSkill 함수에서, bSkillHasDuration 플래그가 true면 ScheduleSkillEnd 함수를 호출한다.ScheduleSkillEnd 함수는 SkillDuration 이후에 EndSkill 호출한다. if(Skill->bSkillHasDuration)
{
ScheduleSkillEnd(Handle, Skill->SkillDuration, true);
}
PreActivate 함수에서 처리CancelIfActiveTags에 해당하는 Tag가 활성화돼 있다면,for (const FGameplayTag& ActiveTag : ActiveTags)
{
if (Spec->CancelIfActiveTags.HasTag(ActiveTag))
{
FDSSkillSpec* CancelSpec = SkillControlComponent->FindSkillSpecFromTag(ActiveTag);
if (nullptr != CancelSpec)
{
SkillControlComponent->CancelSkillHandle(CancelSpec->Handle);
}
}
}
// 함께 실행되면 안되는 스킬이 실행중이라면 실행 취소
FGameplayTagContainer ActiveTags = SkillControlComponent->GetActiveSkillTags();
for (const FGameplayTag& ActiveTag : ActiveTags)
{
if (Spec->BlockIfActiveTags.HasTag(ActiveTag))
{
return false;
}
}