09.25 - TIL

김혁·2025년 9월 25일

TIL

목록 보기
26/84

오늘의 코드카타

고고학 최고의 발견

  • 종속적인 관계 + 시뮬레이션
  • DFS
  • LV3 - 14%
    -> 문제 풀이

오늘의 공부

팀 프로젝트 진행 상황

1. 문 액터에 멀티플레이 추가

  • 인터랙션 컴포넌트에서 상호작용을 시도하면 클라이언트에서만 함수가 실행되게 됨
    -> 클라이언트의 입력(플레이어 컨트롤러)을 통해서 해당 함수가 실행되기 때문에 클라에서만 실행
  • 상호작용하고 싶은 액터의 인터랙트 함수를 실행시키는 것은 서버에서만 실행
// EGInteractionComponent.cpp

void UEGInteractionComponent::PerformInteraction()
{
	...

	if (GetWorld()->LineTraceSingleByChannel(Hit, StartLoc, EndLoc, ECC_Visibility, Params))
	{
		if (AActor* HitActor = Hit.GetActor())
		{
			if (HitActor->GetClass()->ImplementsInterface(UEGInteractInterface::StaticClass()))
			{
				if (!GetOwner()->HasAuthority())
				{
					ServerRPC_Interact(HitActor);
				}
			}
		}
	}
}

void UEGInteractionComponent::ServerRPC_Interact_Implementation(AActor* Target)
{
	if (Target && Target->GetClass()->ImplementsInterface(UEGInteractInterface::StaticClass()))
	{
		IEGInteractInterface::Execute_Interact(Target);
	}
}
  • 문의 열고 닫힘 상태를 관리하는 변수를 추가
  • 서버에서만 해당 변수를 수정해서, ReplicatedUsing 속성을 활용해서 서버, 클라에서도 같이 TimelineComponent를 활용해서 문을 열고 닫음
// EGDoor.h

UFUNCTION()
void OnRep_DoorState();

UPROPERTY(ReplicatedUsing = OnRep_DoorState)
bool bIsOpen;


// EGDoor.cpp

void AEGDoor::Interact_Implementation()
{
	if (HasAuthority())
	{
		bIsOpen = !bIsOpen;
	}
}

void AEGDoor::OnRep_DoorState()
{
	if (bIsOpen)
	{
		DoorTimeline->PlayFromStart();
	}
	else
	{
		DoorTimeline->ReverseFromEnd();
	}
}

2. 타임라인 컴포넌트 오류 수정

  • 문 인터랙트를 광클할 시에, 타임라인 오류인지 처음이나 끝 부분으로 텔포하는 에러 발생
    -> 타임라인 재생 중에는 문 인터랙트 막기
void AEGDoor::Interact_Implementation()
{
	if (HasAuthority())
	{
		if (!DoorTimeline->IsPlaying())
		{
			bIsOpen = !bIsOpen;
			OnRep_DoorState();
		}
	}
}
  • 문 열고 닫힘은 동기화가 잘 됨
  • 다만, 문 열고 닫을 때, 물리 계산이 이상하게 다르게 되는 경우가 있음

3. NavMesh 동적 생성 R&D


오늘의 CS

가상 메모리

  • 개념
    • 프로세스의 일부만 메모리에 로드하고, 나머지는 디스크에 둔 상태로 프로세스를 실행하는 방식
    • 실제 물리 메모리(RAM)보다 더 큰 메모리 공간이 있는 것처럼 제공하는 기술
    • SSD/HDD 일부를 RAM처럼 사용
  • 장점
    • 물리 메모리 부족 문제 완화
    • 동시에 많은 프로그램을 실행하므로 CPU 이용률과 처리율을 높일 수 있음
    • 필요한 영역만 메모리에 로드해 스와핑 횟수를 줄여서 프로그램 실행 속도를 높일 수 있음
  • MMU(Memory Management Unit)가 두 주소 사이의 변환을 담당해서, CPU가 가상 주소를 요청하면, 이를 물리 주소로 변환하여 실제 메모리에 접근함
  • 프로세스는 처음에 메모리 영역을 할당받을 때, 할당받은 모든 영역을 PTE(Page Table Entry)에 등록이 되고, 이를 기반으로 가상 메모리 주소를 만들어서 관리함

페이징

  • 가상 메모리 시스템은 메모리를 일정한 크기로 나눈 블록 단위로 관리함
  • 페이지
    • 가상 메모리 공간을 나눈 고정된 크기의 블록
  • 프레임
    • 물리 메모리 공간을 나눈 고정된 크기의 블록
  • 페이징
    • 가상 주소 공간의 페이지를 물리 메모리의 프레임에 매핑하는 기법
    • 동작 과정
      - 각 프로세스는 자신의 페이지 테이블을 가짐
      - 페이지 테이블은 가상 메모리의 페이지 번호와 물리 메모리의 프레임 번호를 연결해줌
      - CPU가 가상 주소를 생성하면, MMU는 페이지 테이블을 참조하여 해당하는 물리 주소를 찾음


CPU가 메모리 접근할 때의 동작 과정

1. CPU -> 캐시 확인

  • CPU는 항상 가상 주소로 메모리에 접근
  • 가상 주소를 변환해서 실제 물리 주소를 알아낸 뒤, 해당 주소가 L1 -> L2 -> L3 캐시에 있는지 확인

2. 주소 변환

  • CPU는 물리 주소를 모름 -> MMU가 변환
  • TLB 확인 (페이지 테이블의 캐시)
    • TLB에 가상 주소 -> 물리 주소 매핑이 있으면 변환
    • 없으면 TLB 미스 -> 페이지 테이블 조회
  • 페이지 테이블에서 해당 가상 주소가 어느 물리 프레임에 매핑되어 있는지 확인
    • 있으면 변환 성공, 그 결과를 TLB에 캐싱해둠
    • 없으면 페이지 폴트 발생

3. 페이지 폴트 처리

  • 페이지 폴트 발생 : 해당 가상 페이지가 현재 RAM에 없음
    -> 즉 페이지 테이블에 프레임과 매핑이 되어있지 않음
  • OS가 디스크에서 해당 페이지를 읽어서 RAM에 올림
  • RAM에 새로 올라간 페이지의 매핑 정보를 페이지 테이블에 기록, TLB에도 캐싱

4. 데이터 로드

  • RAM -> 캐시에 데이터를 올리고, CPU가 해당 데이터를 읽음

32비트 운영체제 vs 64비트 운영체제

1. 주소 공간

  • 32비트 OS
    • CPU 레지스터가 32비트 -> 주소 공간은 2^32 = 4GB
    • 하나의 프로세스가 최대 4GB 가상 메모리만 접근 가능
  • 64비트 OS
    • 주소 공간은 2^64 -> 이론상 16EB(엑사바이트)
    • 훨씬 많은 메모리를 직접 주소 지정 가능

2. 레지스터 크기 & 연산 단위

  • 32비트 OS
    • 범용 레지스터 크기 : 32비트
    • 한 번에 처리 가능한 정수 크기 : 4바이트
    • 포인터 크기 : 4바이트
  • 64비트 OS
    • 범용 레지스터 크기 : 64비트
    • 한 번에 처리 가능한 정수 크기 : 8바이트
    • 포인터 크기 : 8바이트

3. 메모리 활용 & 소프트웨어 호환성

  • 32비트 OS
    • 4GB 이상 RAM을 인식 불가
    • 32비트 프로그램만 실행 가능
  • 64비트 OS
    • 수십 GB 이상 RAM 자유롭게 사용 가능
    • 단, 포인터가 커서 -> 같은 프로그램도 메모리를 조금 더 많이 사용
    • 64비트 프로그램 실행 가능, 대부분의 32비트 프로그램도 호환해서 실행 가능
profile
게임 개발자를 향해..

0개의 댓글