This document is about: QUANTUM 2
SWITCH TO

특성

개요

AttributesSystem은 외부 조건(예: 활성 상태일 때 +50% 속도 또는 특정 지역에 서 있을 때 +100% 대미지를 제공하는 효과)을 기반으로 값을 저장하고 계산할 수 있는 방법을 제공합니다.

설정

특성을 구현하기 위해서는, 2개의 작업이 수행되어야 합니다:

  1. 특성(일반적으로 행위자)을 사용하는 목표 엔티티의 컨트롤러는IAttributesController를 구현해야 합니다. 이렇게 하면 엔티티에 있는 특성을 제어하고 필요할 때 기본 상태로 재설정한 다음 수집된 값을 처리할 수 있습니다.
  2. 특성(예: 효과 또는 영역)을 보유하고 있는 원천 엔티티의 컨트롤러가 IAttributesProvider를 구현해야 합니다. 목표 엔티티에서 수집한 특성 값을 변경하는 데 사용됩니다.

속성 값은 원천 엔티티에 의해 계산되고 목표 엔티티에 수집할 수 있게 됩니다. 목표 엔티티와 원천 엔티티 간의 관계 및 속성 값의 계산을 다음 다이어그램으로 나타낼 수 있습니다.

attributes system
속성 값 계산 흐름.

AttributesSystemAttributes 컴포넌트를 사용하여 각 엔티티에 대해 다음을 실행합니다.

  1. 목표 엔티티의 엔티티 컨트롤러에서 IAttributesController.Reset() 이 호출됩니다. 이 엔티티는 Attributes 컴포넌트가 있는 엔티티입니다. 이때 모든 속성 컴포넌트를 기본값으로 재설정해야 합니다(일반적으로 곱셈의 경우 1.0, 더하기 수정자의 경우 0.0)(그림에서 빨간색 선으로 표시).
  2. 등록된 모든 특성 공급자(예: 원천 엔티티)에서 IAttributeProvider.Collect()가 호출됩니다. 각 제공자는 엔티티에 대한 내부 특성 값을 업데이트합니다(그림에서 녹색 선으로 표시).
  3. 목표 엔티티의 엔티티 컨트롤러에서 IAttributesController.Process()가 호출됩니다. 이 단계에서 모든 제공자의 값은 이미 곱/누적되었으며 최종 값은 추가 계산을 위해 준비되거나 컴포넌트 요구에 전달될 준비가 되었습니다 (그림에서 파란색선으로 표시).

주의: 엔티티의 특성 컬렉션에 참여하려면 Attributes.RegisterProvider() 또는 IAttributesProvider.RegisterOnCreate를 통해 속성을 소유자 엔티티의 컬렉션에 등록해야 합니다. 특성을 등록 취소하려면 Attributes.UnregisterProvider()를 호출해야 합니다.

예제

이 섹션에서는 AttributesSystem이 FPS 템플릿에 포함된 DamageAttributeEffectController 구현과 어떻게 상호 작용하는지를 예시로 보여주고 있습니다.

C#

public unsafe sealed class DamageAttributeEffectController : AttributeEffectController, IAttributesProvider
{
    //========== PUBLIC MEMBERS ===================================================================================

    public FP PercentDamageDoneModifier     = FP._0;
    public FP PercentDamageReceivedModifier = FP._0;

    //========== AttributeEffectController INTERFACE ==============================================================

    protected override bool OnActivate(Frame frame, EntityRef entity, EntityRef target)
    {
        // 1. The effect is activated (returns true) only if the target has Damage attribute
        
        DamageAttribute* damageAttribute = frame.TryGetComponent<DamageAttribute>(target);
        return damageAttribute != null;
    }

    //========== IAttributesProvider INTERFACE ====================================================================

    // 2. This attribute provider is registered to the pipeline when created
    
    bool IAttributesProvider.RegisterOnCreate => true;

    void IAttributesProvider.Collect(Frame frame, EntityRef entity, EntityRef target)
    {
        // 3. Collection phase, called each frame the effect exists
        
        DamageAttribute* damageAttribute          = frame.TryGetComponent<DamageAttribute>(target);
        damageAttribute->DamageDoneMultiplier    += PercentDamageDoneModifier * FP._0_01;
        damageAttribute->DamageReceiveMultiplier += PercentDamageReceivedModifier * FP._0_01;
    }
}
Back to top