오늘의 코드카타
오늘의 공부
팀 프로젝트 진행 내용
1. 파쿠르 동작 함수 리팩토링
- 기존의 파쿠르 컴포넌트의
TryTraversal() 함수가 너무 길고 여러 동작을 해서 해당 함수를 여러 함수로 분리했다.
- 기존에는 250줄 정도 되는 함수를 기능별로 구분을 해서 가시성과 디버깅 편의성을 늘렸다.
// AO_TraversalComponent.cpp
bool UAO_TraversalComponent::TryTraversal()
{
if (bDoingTraversal)
{
AO_LOG(LogKH, Warning, TEXT("Traversal is already in progress"));
return false;
}
FTraversalCheckResult TraversalCheckResult;
// Detect Traversable Objects and acquire Information for Traversal
if (!DetectTraversal(TraversalCheckResult))
{
return false;
}
// Evaluate Traversal Conditions by Chooser Table
TArray<UObject*> EvaluateObjects;
if (!EvaluateTraversal(TraversalCheckResult, EvaluateObjects))
{
return false;
}
// Select the best Traversal Action by Motion Matching
if (!SelectTraversal(TraversalCheckResult, EvaluateObjects))
{
return false;
}
TraversalResult = TraversalCheckResult;
RequestTraversalNetworking(TraversalCheckResult);
return true;
}
2. Foley 오디오 시스템 추가
- Game Animation Sample Project의 애니메이션 에셋을 사용했다보니, 오디오를 재생해주는 노티파이가 추가로 배치되어 있었다.
- 해당 노티파이를 활용하여 플레이어 캐릭터의 로코모션 및 파쿠르 동작 시에 자연스러운 사운드 출력을 할 수 있게끔 했다.
- 먼저
GameplayTag 기반으로 TMap을 활용하여 재생할 사운드 파일을 저장해놓는 PrimaryDataAsset을 생성했다.
// AO_FoleyAudioBank.h
UCLASS()
class AO_API UAO_FoleyAudioBank : public UPrimaryDataAsset
{
GENERATED_BODY()
public:
UFUNCTION(BlueprintCallable, Category = "Foley")
USoundBase* GetSoundFromFoleyEvent(const FGameplayTag& Event);
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Foley")
TMap<FGameplayTag, TObjectPtr<USoundBase>> Assets;
};
// AO_FoleyAudioBank.cpp
USoundBase* UAO_FoleyAudioBank::GetSoundFromFoleyEvent(const FGameplayTag& Event)
{
TObjectPtr<USoundBase> FoleySound = Assets.FindRef(Event);
if (!FoleySound)
{
return nullptr;
}
return FoleySound;
}
- 다음으로 해당
PrimaryDataAsset을 관리하고, 현재 캐릭터의 상태 기반으로 사운드를 출력할 수 있는 상황인지 확인하는 Interface를 생성했다.
// AO_FoleyAudioBankInterface.h
UINTERFACE(MinimalAPI, BlueprintType)
class UAO_FoleyAudioBankInterface : public UInterface
{
GENERATED_BODY()
};
class AO_API IAO_FoleyAudioBankInterface
{
GENERATED_BODY()
public:
UFUNCTION(BlueprintNativeEvent, BlueprintCallable, Category = "Foley")
UAO_FoleyAudioBank* GetFoleyAudioBank() const;
virtual UAO_FoleyAudioBank* GetFoleyAudioBank_Implementation() const = 0;
UFUNCTION(BlueprintNativeEvent, BlueprintCallable, Category = "Foley")
bool CanPlayFootstepSounds() const;
virtual bool CanPlayFootstepSounds_Implementation() const = 0;
};
- 플레이어 캐릭터에 해당 인터페이스를 상속받고, 내용을 구현했다.
// AO_PlayerCharacter.cpp
UAO_FoleyAudioBank* AAO_PlayerCharacter::GetFoleyAudioBank_Implementation() const
{
if (!DefaultFoleyAudioBank)
{
return nullptr;
}
return DefaultFoleyAudioBank;
}
bool AAO_PlayerCharacter::CanPlayFootstepSounds_Implementation() const
{
if (GetCharacterMovement()->IsMovingOnGround() || TraversalComponent->GetDoingTraversal())
{
return true;
}
return false;
}
- 모든 애니메이션의 노티파이를 수정하기는 시간이 너무 소요될 것으로 보여서 해당 부분은 그대로 사용하고자 했다.
- 해당 파일은
BP_AnimNotify_FoleyEvent로 해당 클래스에서 사운드를 재생해주게 된다.
- 위의
PrimaryDataAsset을 받아서 데이터의 Map을 통해 사운드 파일을 찾고, 사운드를 재생해주는 로직으로 구현되어 있다.
- 위의 동작은
FGameplayTag 기반으로 동작은 한다. 아래는 이를 위해 선언한 부분이다.
// DefaultGameplayTags.ini
+GameplayTagList=(Tag="Foley.Event.Handplant",DevComment="")
+GameplayTagList=(Tag="Foley.Event.Jump",DevComment="")
+GameplayTagList=(Tag="Foley.Event.Land",DevComment="")
+GameplayTagList=(Tag="Foley.Event.Run",DevComment="")
+GameplayTagList=(Tag="Foley.Event.RunBackwds",DevComment="")
+GameplayTagList=(Tag="Foley.Event.RunStrafe",DevComment="")
+GameplayTagList=(Tag="Foley.Event.Scuff",DevComment="")
+GameplayTagList=(Tag="Foley.Event.ScuffPivot",DevComment="")
+GameplayTagList=(Tag="Foley.Event.ScuffWall",DevComment="")
+GameplayTagList=(Tag="Foley.Event.Tumble",DevComment="")
+GameplayTagList=(Tag="Foley.Event.Walk",DevComment="")
+GameplayTagList=(Tag="Foley.Event.WalkBackwds",DevComment="")
오늘의 CS
TCP vs UDP
- IP 위에서 동작하는 전송 계층 프로토콜이며, 데이터를 어떻게 전달할지 결정하는 역할
- TCP(Transmission Control Protocol)
- 신뢰성 있는, 연결 지향적인 프로토콜로, 데이터가 손실되지 않고 순서대로 목적지에 도착하는 것을 보장함
- 특징
- 연결 지향 : 데이터를 전송하기 전에 3-Way Handshake를 통해 연결 설정, 종료 시에는 4-Way Handshake를 통해 연결을 해제함
- 신뢰성 보장 : 흐름 제어, 혼잡 제어, 재전송 기능을 통해 신뢰성을 보장함
- 순서 보장 : 데이터 패킷에 번호를 부여하여, 순서가 바뀌어도 재조립하여 원래 순서대로 전달함
- 예: 웹 브라우징, 이메일, 파일 전송 등 데이터의 정확성이 중요한 서비스
- UDP(User Datagram Protocol)
- 비연결형, 비신뢰성 프로토콜로, 데이터를 빠르게 전송하는 데 초점을 맞춤
- 특징
- 비연결형 : 연결 설정 과정 없이 데이터를 즉시 보냄
- 비신뢰성 : 순서 보장과 제어 기능이 없어 누락되거나 받을 준비가 되지 않아도 계속 전송함
- 오버헤드 최소화 : 헤더의 크기가 TCP보다 훨씬 작은 8바이트로, 오버헤드가 적어 속도가 빠름
- 예: 실시간 스트리밍, 게임, 음성 통화 등 약간의 손실이 있어도 지연 없이 빠른 전달이 중요한 서비스
멀티프로세싱 vs 멀티스레딩
- 컴퓨터 시스템에서 병렬성을 구현하여 성능을 향상시키는 주요한 방법
멀티프로세싱
- 하나의 컴퓨터 시스템에서 여러 개의 독립적인 프로세스를 동시에 실행하는 것
- 특징
- 독립된 메모리 공간 : 각 프로세스는 독립적인 메모리 공간을 가지고 있음
- 자원 보호 : 메모리가 분리되어 있기 떄문에 한 프로세스가 오류를 일으켜도 다른 프로세스에 영향을 주지 않아 안정성이 높음
- 통신 방법 : 프로세스 간 통신(IPC)이 필요하며, 이는 커널의 도움을 받아 통신하게 됨
- 오버헤드 : 컨텍스트 스위칭을 할 때 PCB 정보를 저장/복원하고 페이지 테이블을 교체해야 하므로 비용이 큼
- 적합 분야 : 오류 격리가 필요하거나, 계산 집약적이고 서로 독립적인 작업을 처리할 때
멀티스레딩
- 하나의 프로세스 내에서 여러 개의 스레드를 동시에 실행하는 것을 의미함
- 특징
- 자원 공유 : 스레드들은 코드, 데이터, 힙 영역을 공유함. 하지만 스택, PC, 레지스터는 독립적임
- 통신 방법 : 스레드 간 통신은 공유 메모리를 통해 이루어지므로, 공유 변수에 직접 접근하여 데이터를 주고 받을 수 있음
- 오버헤드 : 컨텍스트 스위칭을 할 때 페이지 테이블 교체가 필요 없으므로 비용이 저렴함
- 적합 분야 : 데이터 공유 및 빠른 통신이 필요할 때