12.16 - TIL

김혁·2025년 12월 16일

TIL

목록 보기
75/84

오늘의 코드카타

  • 아방가르드 타일링
    • 특정한 모양의 타일이 있을 때, 이를 배치하는 경우의 수를 찾는 문제
    • 가로 길이를 x라고 했을 때, x일 때 새로 나올 수 있는 경우의 수를 세고, 그 이전의 값들을 통해 경우의 수를 계산하는 문제
    • 중복되는 경우의 수로 인해 예를 들어 f(4)를 구할 때, (x=1일 때의 새로운 경우의 수)*(x=3일 때의 모든 경우의 수)와 같은 방식으로 문제를 해결해야함
    • x가 7일 때까지는 직접 그려보면서 새로 나올 수 있는 경우의 수를 확인해야 하고, 점화식도 매우 복잡함. 반면 구현은 매우 쉬움. 수학적으로 경우의 수를 찾는 문제.
    • https://school.programmers.co.kr/learn/courses/30/lessons/181186

팀 프로젝트 진행 내용

1. 리팩토링

  • 사용하지 않는 데미지 및 파쿠르 컴포넌트 코드를 삭제
  • 코딩 컨벤션에 맞춰서 continue 구문에도 중괄호를 추가했고, if(!Statement)return; 부분을 check()로 변환을 했다.
  • 주의할 점으로 AnimInstance 부분에서 NativeThreadSafeUpdateAnimation() 함수에서 Proxy.Owner, Proxy.Character, Proxy.Movement에 대해 유효성 검사를 실시하는데, 프록시를 기반으로 동작하기 때문에 에디터를 키게 되면 null 값을 반환하게 된다. 로딩 과정에서도 null 값을 반환할 수 있기 때문에 해당 부분은 assertion으로 처리하면 안 된다.
  • 또한 노티파이의 경우에는 World가 에디터인 상황에서는 넘어가는 코드를 추가해줘야 한다.

2. 캐릭터에 속도 속성 추가

  • 캐릭터가 3개의 상태로 이동속도가 관리되기 때문에 각 속도를 Attribute Set에 추가했다.
  • 이 Attribute Set의 속성을 통해서 패시브 아이템으로 속도를 증가시키거나 할 예정이다.
// AO_PlayerCharacter_AttributeSet.h

UCLASS()
class AO_API UAO_PlayerCharacter_AttributeSet : public UAttributeSet
{
	GENERATED_BODY()
    
    ...
    
	// 걷기(Walk) 이동속도
	UPROPERTY(BlueprintReadOnly, ReplicatedUsing = OnRep_WalkSpeed, Category = "Speed|Walk")
	FGameplayAttributeData WalkSpeed;
	ATTRIBUTE_ACCESSORS_BASIC(UAO_PlayerCharacter_AttributeSet, WalkSpeed)
	
	// 뛰기(Run) 이동속도
	UPROPERTY(BlueprintReadOnly, ReplicatedUsing = OnRep_RunSpeed, Category = "Speed|Run")
	FGameplayAttributeData RunSpeed;
	ATTRIBUTE_ACCESSORS_BASIC(UAO_PlayerCharacter_AttributeSet, RunSpeed)
	
	// 스프린트(Sprint) 이동속도
	UPROPERTY(BlueprintReadOnly, ReplicatedUsing = OnRep_SprintSpeed, Category = "Speed|Sprint")
	FGameplayAttributeData SprintSpeed;
	ATTRIBUTE_ACCESSORS_BASIC(UAO_PlayerCharacter_AttributeSet, SprintSpeed)
}
  • 캐릭터에서 이동 속도 관련된 속성이 변경되면 캐릭터의 이동속도를 변경시켜야 하기 때문에 해당 속성이 변경될 때의 델리게이트를 연결했다.
  • 기존의 이동 속도를 변경하는 코드를 추가해서 실시간으로 변경할 수 있게끔 코드를 구현했다.
// AAO_PlayerCharacter.cpp

void AAO_PlayerCharacter::BindSpeedAttributeDelegates()
{
	checkf(AttributeSet, TEXT("AttributeSet is null"));
	
	// 이동속도 변경 시 발생할 델리게이트 연결
	AbilitySystemComponent->GetGameplayAttributeValueChangeDelegate(AttributeSet->GetWalkSpeedAttribute())
		.AddUObject(this, &AAO_PlayerCharacter::OnSpeedChanged);
	AbilitySystemComponent->GetGameplayAttributeValueChangeDelegate(AttributeSet->GetRunSpeedAttribute())
		.AddUObject(this, &AAO_PlayerCharacter::OnSpeedChanged);
	AbilitySystemComponent->GetGameplayAttributeValueChangeDelegate(AttributeSet->GetSprintSpeedAttribute())
		.AddUObject(this, &AAO_PlayerCharacter::OnSpeedChanged);
}

void AAO_PlayerCharacter::OnSpeedChanged(const FOnAttributeChangeData& Data)
{
	SetCurrentGait();
	
	if (!HasAuthority())
	{
		ServerRPC_SetInputState(CharacterInputState.bWantsToSprint, CharacterInputState.bWantsToWalk);
	}
}

void AAO_PlayerCharacter::OnRep_Gait()
{
	switch (Gait)
	{
	case EGait::Walk:
		GetCharacterMovement()->MaxWalkSpeed = AttributeSet->GetWalkSpeed();
		break;
	case EGait::Run:
		GetCharacterMovement()->MaxWalkSpeed = AttributeSet->GetRunSpeed();
		break;
	case EGait::Sprint:
		GetCharacterMovement()->MaxWalkSpeed = AttributeSet->GetSprintSpeed();
		break;
	}
}

3. Attribute Set 초기화 부분 데이터 에셋으로 수정

  • 이후에 레벨 디자인 시에 캐릭터의 속성의 초기 값을 지정하는 것을 코드에서 직접 하는 것은 번거로울 것으로 느껴져 별도의 데이터 에셋 파일을 두고 수정하는 방식으로 변경하고자 했다.
  • 먼저 초기 값을 가지고 있을 데이터 에셋 클래스를 선언해서 초기값을 할당했다.
// UAO_PlayerCharacter_AttributeDefaults.h

UCLASS()
class AO_API UAO_PlayerCharacter_AttributeDefaults : public UDataAsset
{
	GENERATED_BODY()

public:
	// 체력
	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Health")
	float Health = 100.0f;
	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Health")
	float MaxHealth = 100.0f;

	// 스태미나
	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Stamina")
	float Stamina = 100.0f;
	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Stamina")
	float MaxStamina = 100.0f;

	// 이동속도
	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Speed")
	float WalkSpeed = 200.0f;
	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Speed")
	float RunSpeed = 500.0f;
	UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "Speed")
	float SprintSpeed = 800.0f;
};
  • 캐릭터에서 해당 데이터 에셋을 받아서 속성을 초기화하는 코드를 PossessedBy()에서 ASC를 초기화한 이후에 추가했다.
// AAO_PlayerCharacter.h

UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, Category = "PlayerCharacter|GAS")
TObjectPtr<UAO_PlayerCharacter_AttributeDefaults> AttributeDefaults;


// AAO_PlayerCharacter.cpp

void AAO_PlayerCharacter::PossessedBy(AController* NewController)
{
	Super::PossessedBy(NewController);

	AbilitySystemComponent->InitAbilityActorInfo(this, this);
	
	if (HasAuthority())
	{
		InitializeAttributes();
		
        ...
	}
}

void AAO_PlayerCharacter::InitializeAttributes()
{
	if (!HasAuthority())
	{
		return;
	}

	AttributeSet->InitHealth(AttributeDefaults->Health);
	AttributeSet->InitMaxHealth(AttributeDefaults->MaxHealth);

	AttributeSet->InitStamina(AttributeDefaults->Stamina);
	AttributeSet->InitMaxStamina(AttributeDefaults->MaxStamina);

	AttributeSet->InitWalkSpeed(AttributeDefaults->WalkSpeed);
	AttributeSet->InitRunSpeed(AttributeDefaults->RunSpeed);
	AttributeSet->InitSprintSpeed(AttributeDefaults->SprintSpeed);
}
profile
게임 개발자를 향해..

0개의 댓글