Unreal GAS (5) - AttributeSet

wnsduf0000·2025년 12월 1일

Unreal_GAS

목록 보기
5/34
post-thumbnail
  • 프로젝트 컴파일 오류

    • Visual Studio Integration Tool을 설치하려다가 뭔가 잘못된건지 컴파일 에러가 발생함.

    • CoreMinimal.h와 같은 가장 기본적인 언리얼 헤더 파일들을 E1696 에러코드가 발생.
      (헤더 파일들을 파악하지 못함)

    • 여러 방법을 시도해 보았으나, 결국 프로젝트 소스코드와 컨텐츠 브라우저 에셋들을 탐색기에서 백업해두고 커밋 버전을 이전으로 돌려봄.

      • 그런데 커밋 버전을 돌려봐도 동일한 문제가 발생하는 것으로 보였음.
        아마 언리얼 엔진이나 프로젝트보다는 Visual Studio 자체에서 뭔가 설정이 잘못된건지…
      • 결국 Visual Studio 재설치 후, 롤백했던 버전의 프로젝트에 백업해둔 파일들을 넣고,
        C++ 클래스를 추가 후 솔루션 파일을 빌드해서 원래 상태로 돌리려 하는데 문제가 또 발생.
        - 보다 정확히 하자면, 롤백했던 버전은 아직 C++ 클래스가 없이 필요 에셋만 임포트한 거의 백지 상태의 프로젝트였기 때문에, C++ 클래스를 추가해서 솔루션 파일을 생성하려는데, 이 과정에서 라이브 코딩 에러가 발생함.
        - 라이브 코딩을 비활성화 후 솔루션 파일을 빌드하면 빌드는 되지만, 컨텐츠 브라우저에 C++ 클래스가 표시되지 않는 문제가 있었음.
        (컨텐츠 브라우저의 C++ 클래스 표시는 이미 체크된 상태)
        - 라이브 코딩 버튼 사라짐 + missing LinkerPath field 에러 :: 다양한 컴퓨터 지식
    • 위와 같은 방식으로, 프로젝트 파일에 Modules 항목을 추가해서 해결할 수 있었음.

      "Modules": [
              {
                  "Name" : "Aura",
                  "Type": "Runtime",
                  "LoadingPhase": "Default",
                  "AdditionalDependencies": [
                      "Engine"
                  ]
              }
          ],
      
          // 단 한 글자라도 오타가 나면 솔루션 파일이 제대로 생성되지 않으므로
          // 오탈자에 항상 유의할 것!
  • Attribute Set (AS)

    • Attribute들의 집합임.
    • ASC의 OwnerActor 클래스의 생성자에 ASC와 함께 초기화 해주면,
      알아서 ASC에 등록되도록 설계되어 있음.
      • 하나의 ASC가 여러 개의 AS를 가질 수 있음.
        (단, 이 때 각각의 AS들은 모두 서로 다른 클래스여야만 함.)
    • AS는 여러 개의 Attribute를 지닐 수 있음.
      각각의 Attribute들은 FGameplayAttributeData라는 구조체 내부에 float형태로 존재함.
      - FGameplayAttributeData는 두 개의 float 변수로 이루어진 구조체임.
      - 기본값을 나타내는 BaseValue, 현재값을 나타내는 CurrentValue가 존재함.
      CurrentValue는 BaseValue에 각종 GameplayEffect로 인해 변경된 값이 반영된 값임.
    • AttributeSet은 자신이 지닌 Attribute들이 변경되는 시점 등을 파악할 수 있음.
    • 각각의 Attribute들은 AttributeSet을 통해 직접 변경하는 것도 가능하지만,
      그보다는 GameplayEffect를 통해서 변경하는 것이 가장 이상적인 방법임.
      GameplayEffect를 통하면 각 Attribute들의 변화를 예측(Predict)하는 것이 가능함.
      - Prediction (예측): 클라이언트가 서버의 허가 없이 독자적으로 값을 변경하여 즉각적인 변경이 가능하며, 값을 변경했음을 서버 측에 통보하는 것을 의미함. 서버는 이 값을 확인하여, 문제가 있다고 판단되는 경우는 해당 값의 변경을 롤백할 수 있음.
      - 예측 기능이 구현되지 않은 상태에서는, 클라이언트측에서 값을 변경해야 한다는 요청을 서버로 보내고, 서버 측에선 이 변경이 옳은 지 확인 후 옳은 경우 값을 변경하여 이를 클라이언트 측에 전파하는데, 네트워크 전송에 따른 시간 소모가 있어 플레이 경험이 저해될 수 있음.
      - 예측 기능이 구현되었다면, 클라이언트는 서버를 거치지 않고 즉시 값을 변경 후, 이 변경 사항을 서버에 전파하여 서버는 해당 변경 사항이 옳은 지를 판단하여 옳은 경우 이를 다른 클라이언트들에게 전파할 수 있고, 그렇지 않은 경우 이를 롤백할 수 있음.
      서버 측이 여전히 변경 권한을 갖지만, 그와 동시에 클라이언트는 네트워크 전송으로 인한 지연 문제에서 비교적 자유로워지는 이점이 있음.
  • Replication / RepNotify

    • 변수를 Replicated로 지정하려면 UPROPERTY 매크로에 Replicated 선언을 해주면 된다.
      UPROPERTY(Replicated)
      FGameplayAttributeData Health;
    • 추가적으로, 아래의 함수를 오버라이드 해야 한다.
      Replicated 될 변수를 등록하는 함수이다.
      ```cpp
      // 함수 선언
      virtual void GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const override;
      
      // 함수 구현
      void UAuraAttributeSet::GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const
      {
      	Super::GetLifetimeReplicatedProps(OutLifetimeProps);
      	
      	// DOREPLIFETIME 매크로에는 여러 종류가 있는데, 여기서는 DOREPLIFETIME_CONDITION_NOTIFY를 사용.
      	// 매개변수는 '현재 클래스 이름, Replicated 되는 변수, Replicate가 발생하는 조건(ELifetimeCondition), RepNotify가 발생하는 조건'임.
      	DOREPLIFETIME_CONDITION_NOTIFY(UAuraAttributeSet, Health, COND_None, REPNOTIFY_Always);
      }
      ```
    • RepNotify를 이용하여 변수가 서버에 의해 Replicated될 때 특정한 처리를 할 수 있다.
      이를 위해선 UPROPERTY 매크로에 ReplicatedUsing 을 사용하며 아래와 같이 하면 된다.
      ```cpp
      // ReplicatedUsing을 사용하고, 트리거 될 함수의 이름을 'OnRep_변수이름'으로 지정.
      UPROPERTY(ReplicatedUsing = OnRep_Health)
      FGameplayAttributeData Health;
      
      // RepNotify 함수는 매개변수를 0개 또는 1개만 받을 수 있다.
      // 매개변수는 반드시 Replicated된 변수와 동일한 타입이어야 한다.
      // 매개변수는 Replicated되기 *이전* 의 값이 전달된다.
      UFUNCTION()
      void OnRep_Health(const FGameplayAttributeData& OldHealth);
      ```
    • AS에서 Replicated된 변수가 변경되어 RepNotify 함수가 호출될 경우,
      AS측에서 이 변경 사항을 ASC에 알려야 함.
      이를 위한 매크로를 GameplayAbilitySystem에서 제공하고 있음.
      ```cpp
      void UAuraAttributeSet::OnRep_Health(const FGameplayAttributeData& OldHealth)
      {
      	// GAMEPLAYATTRIBUTE_REPNOTIFY 매크로를 이용하여 ASC에 변경 사항을 전달.
      	// 매개변수는 '현재 클래스(AS)의 이름, Replicated된 변수, 이전 값'임.
      	GAMEPLAYATTRIBUTE_REPNOTIFY(UAuraAttributeSet, Health, OldHealth);
      }
      ```
profile
저는 게임 개발자로 일하고 싶어요

0개의 댓글