11.24 - TIL

김혁·2025년 11월 24일

TIL

목록 보기
63/84

오늘의 코드카타

오늘의 공부

팀 프로젝트 진행 내용

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, 레지스터는 독립적임
    • 통신 방법 : 스레드 간 통신은 공유 메모리를 통해 이루어지므로, 공유 변수에 직접 접근하여 데이터를 주고 받을 수 있음
    • 오버헤드 : 컨텍스트 스위칭을 할 때 페이지 테이블 교체가 필요 없으므로 비용이 저렴함
    • 적합 분야 : 데이터 공유 및 빠른 통신이 필요할 때
profile
게임 개발자를 향해..

0개의 댓글