[내일배움캠프 본 캠프]코드카타, GAS(2025/06/04)

김세훈·2025년 6월 4일
0

1) 코드카타

문제(하샤드 수)
https://school.programmers.co.kr/learn/courses/30/lessons/12947

제출한 답안

#include <string>
#include <vector>
#include <iostream>

using namespace std;

bool solution(int x) {
    bool answer = false;
    int temp = x;
    int sum = 0;
    
    while (x != 0)
    {
        sum += x % 10;
        x /= 10;
    }
    
    if (temp % sum == 0)
    {
        answer = true;
    }
    return answer;
}

문제(두 정수 사이의 합)
https://school.programmers.co.kr/learn/courses/30/lessons/12912

제출한 답안

#include <string>
#include <vector>

using namespace std;

long long solution(int a, int b) {
    long long answer = 0;
    int minNumber = a;
    int maxNumber = b;
    if (a > b)
    {
        minNumber = b;
        maxNumber = a;
    }
    else if (a == b)
    {
        answer = a;
        return answer;
    }
    
    for (int i = minNumber; i <= maxNumber; i++)
    {
        answer += i;
    }
    return answer;
}

문제(콜라츠 추측)
https://school.programmers.co.kr/learn/courses/30/lessons/12943

제출한 답안

#include <string>
#include <vector>
#include <iostream>

using namespace std;

int solution(int num) {
    int answer = 0;
    long long temp = num;
    
    while (temp > 1 && answer < 500)
    {
        if (temp % 2 == 0)
        {
            temp = temp / 2;
        }
        else if (temp % 2 != 0)
        {
            temp = temp * 3 + 1;
        }
        answer++;
    }
    if (answer >= 500)
    {
        return -1;
    }
    return answer;
}

이 문제의 입출력 예시에서도 그랬지만 동작 중에 너무 큰 수가 되어서 int형으로 담을 수 없어 문제가 생기는 경우가 있다. 그래서 들어온 숫자를 long long형으로 만들어줘야 한다.

문제(서울에서 김서방 찾기)
https://school.programmers.co.kr/learn/courses/30/lessons/12919

제출한 답안

#include <string>
#include <vector>

using namespace std;

string solution(vector<string> seoul) {
    string answer = "김서방은 ";
    string location = "";
    string end = "에 있다";
    
    for (int i = 0; i < seoul.size(); i++)
    {
        if (seoul[i] == "Kim")
        {
            location = to_string(i);
            i = seoul.size();
        }
    }
    answer = answer + location + end;
    return answer;
}

for문을 벡터의 처음부터 끝까지 돌게 만들 때 iterator를 써서 begin부터 end까지라고 해도 되지만, int i = 0에서 벡터의 사이즈까지라고 해도 좋다.(인덱스가 필요해서 이렇게 만들었다.)
정수를 문자열로 바꿀 때 C스타일보다는 C++스타일의 to_string을 사용하는게 좋을 듯 하다.(string 헤더파일에 포함)


숙제 수정하다가 알아낸 것
ctime 헤더파일에 time에 관련된 함수들이 있다. 랜덤값을 생성하는데 사용 했다. ctime에 관해 인터넷에 검색하면 관련 내용이 잘 나온다. srand는 main에서 한번만 사용하자.(createRandomAnimal함수 안에서 사용했다가 전부 같은 동물만 추가 됐었다.)


2) 취업 교육 라이브 강의

이력서에 관한 내용 강의, 스파르타 커리어 사이트에서 회원가입 후 이력서 작성 숙제
(아직 프로젝트를 진행하지는 않았으니 프로젝트 부분은 제외하고 다른 부분들 채우기)


3) Game Abilities System(GAS)

저번 시간에 공부를 하려고 했으나 뭔가 잘 안돼서 삽질하다가 해결하고 다시 처음부터 시작

  • 3인칭 프로젝트를 만들고 Gameplay Abilities 플러그인 활성화(재시작)

  • build.cs 파일에 "GameplayAbilities", "GameplayTags", "GameplayTasks" 추가

    ASC(Ability System Component)는 블루프린트에서도 사용할 수 있지만 C++에서 접근하면 더 이점이 있다.(C++에서만 접근할 수 있는 기능이 있다는 듯 하다.)

  • AbilitySystemComponent을 상속받는 LabAbilitySystemComponent를 만든다.

    ASC에 있는 가상 함수를 오버라이드하거나, ASC에 기능을 추가할 가능성이 높아서 ASC의 서브 클래스를 미리 만들어 둔다.

// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "CoreMinimal.h"
#include "AbilitySystemComponent.h"
#include "LabAbilitySystemComponent.generated.h"

/**
 * 
 */
UCLASS()
class ABILITIESLAB_API ULabAbilitySystemComponent : public UAbilitySystemComponent
{
	GENERATED_BODY()
	
};
  • 캐릭터 클래스도 ASC를 추가해 준다.(만든 서브 클래스를 추가 한다.)
// 헤더 파일
UCLASS()
class AAbilitiesLabCharacter : public ACharacter
{
	GENERATED_BODY()

public:
	AAbilitiesLabCharacter();
	
	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Abilities)
	TObjectPtr<class ULabAbilitySystemComponent> LabAbilitySystemComp;
};
// cpp 파일
AAbilitiesLabCharacter::AAbilitiesLabCharacter()
{
	...
	LabAbilitySystemComp = CreateDefaultSubobject<ULabAbilitySystemComponent>(TEXT("AbilitySystem"));
}
  • ASC를 사용하는 모든 액터는 IAbilitySystemInterface를 받아서 구현하도록 하는게 좋다.
    (성능 문제에서 이점이 있는 듯 하다.)
#include "AbilitySystemInterface.h"

UCLASS(config=Game)
class AAbilitiesLabCharacter : public ACharacter, public IAbilitySystemInterface
{
	...
	virtual UAbilitySystemComponent* GetAbilitySystemComponent() const override;
};
UAbilitySystemComponent* AAbilitiesLabCharacter::GetAbilitySystemComponent() const
{
	return LabAbilitySystemComp;
}

헤더나 cpp에 #include "LabAbilitySystemComponent.h"를 해야 한다.

  • beginplay에서 init함수를 사용하는데 오너와 아바타를 알려준다.(여기서는 캐릭터가 오너이자 아바타이다.)
void AAbilitiesLabCharacter::BeginPlay()
{
	Super::BeginPlay();

	// Provide this character as owner and avatar
	LabAbilitySystemComp->InitAbilityActorInfo(this, this);
	...
}

owner(첫 번째 인수)는 플레이어 컨트롤러를 확인할 수 있어야 한다. 그래서 컨트롤러 자체나 컨트롤러를 확인할 수 있는 폰/캐릭터가 들어 간다.
플레이어 컨트롤러를 아직 확인할 수 없는 경우에는 나중에 확인할 수 있게 됐을 때 RefreshAbilityActorInfo 함수를 사용해야 한다.

  • 체력, 피해, 이동 속도 같은 값의 집합 클래스를 만든다. 수치 값을 GAS 속성으로 관리하면 장점이 있다.
    1) 드롭다운에서 속성 선택
    2) GameplayEffects에서 속성 사용
    3) ASC를 통해 속성 값 변경 사항 수신
    4) GAS 디버깅 도구에 등장
    5) 네트워크 프로젝트에서 복제, 예측 및 롤백의 용이성

속성 집합은 현재 블루프린트로 만들 수 없으므로 C++에서 생성 한다.(체력만 생성)

// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "CoreMinimal.h"
#include "AttributeSet.h"
#include "GameplayEffect.h" // 추가: FGameplayAttributeData 정의
#include "Net/UnrealNetwork.h" // 추가: Replication 관련
#include "LabHealthAttributeSet.generated.h"

/**
 * 
 */
UCLASS()
class ABILITIESLAB_API ULabHealthAttributeSet : public UAttributeSet
{
	GENERATED_BODY()

public:
	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Replicated)
	FGameplayAttributeData Health;

	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Replicated)
	FGameplayAttributeData MaxHealth;
	
	// Replication을 위해 함수 선언 필요
	virtual void GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const override;
};
// Fill out your copyright notice in the Description page of Project Settings.


#include "LabHealthAttributeSet.h"

void ULabHealthAttributeSet::GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const
{
	Super::GetLifetimeReplicatedProps(OutLifetimeProps);

	DOREPLIFETIME(ULabHealthAttributeSet, Health);
	DOREPLIFETIME(ULabHealthAttributeSet, MaxHealth);
}

GameplayEffect.h, Net/UnrealNetwork.h를 포함시켜야 한다. 또한, GetLifetimeReplicatedProps를 구현해야 한다. 만약 싱글 게임이면 이 함수는 넘겨도 된다.

  • 다양한 매크로를 헤더파일에 추가하고 클래스에서 사용 한다. 생성자도 만들어서 cpp파일에서 생성자 구현하고 100으로 설정
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once

#include "CoreMinimal.h"
#include "AttributeSet.h"
#include "GameplayEffect.h" // 추가: FGameplayAttributeData 정의
#include "Net/UnrealNetwork.h" // 추가: Replication 관련
#include "AbilitySystemComponent.h"
#include "LabHealthAttributeSet.generated.h"

#define ATTRIBUTE_ACCESSORS(ClassName, PropertyName) \
	GAMEPLAYATTRIBUTE_PROPERTY_GETTER(ClassName, PropertyName) \
	GAMEPLAYATTRIBUTE_VALUE_GETTER(PropertyName) \
	GAMEPLAYATTRIBUTE_VALUE_SETTER(PropertyName) \
	GAMEPLAYATTRIBUTE_VALUE_INITTER(PropertyName)
/**
 * 
 */
UCLASS()
class ABILITIESLAB_API ULabHealthAttributeSet : public UAttributeSet
{
	GENERATED_BODY()

public:
	ULabHealthAttributeSet();

	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Replicated)
	FGameplayAttributeData Health;

	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Replicated)
	FGameplayAttributeData MaxHealth;
	
	ATTRIBUTE_ACCESSORS(ULabHealthAttributeSet, Health);
	ATTRIBUTE_ACCESSORS(ULabHealthAttributeSet, MaxHealth);

	// Replication을 위해 함수 선언 필요
	virtual void GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const override;
};
// Fill out your copyright notice in the Description page of Project Settings.


#include "LabHealthAttributeSet.h"

ULabHealthAttributeSet::ULabHealthAttributeSet()
{
	InitHealth(100.0f);
	InitMaxHealth(100.0f);
}

void ULabHealthAttributeSet::GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const
{
	Super::GetLifetimeReplicatedProps(OutLifetimeProps);

	DOREPLIFETIME(ULabHealthAttributeSet, Health);
	DOREPLIFETIME(ULabHealthAttributeSet, MaxHealth);
}
  • 캐릭터 헤더파일과 cpp파일을 수정 한다.
UPROPERTY()
TObjectPtr<class ULabHealthAttributeSet> HealthSet;
// 클래스에 변수 추가
HealthSet = CreateDefaultSubobject<ULabHealthAttributeSet>(TEXT("HealthSet"));
// cpp파일의 생성자 부분에 추가

언리얼 엔진에서 실행하고 디버깅을 해보면 체력과 맥스체력이 100씩 찍혀있는게 보인다.(shift + ')

내일 게임플레이 이펙트 부분부터 시작

profile
내일배움캠프 언리얼 과정 열심히 듣기 화이팅!

0개의 댓글