Online Subsystem

Unreal 이론|2024. 11. 25. 20:12

IP Address

  • Local IP Address는 로컬 네트워크 라우터에서 컴퓨터에 할당한 주소 (192, 168등으로 시작함)
  • 로컬 네트워크 내의 다른 컴퓨터만이 볼 수 있음. 외부의 컴퓨터는 로컬 IP를 이용해 컴퓨터에 연결할 수 없음
  • 컴퓨터는 이더넷이나 와이파이로 ISP(Internet Service Provider) 와 연결되있음
  • 외부와의 연결을 위해 ISP는 라우터에 공용 IP주소를 할당함
  • 따라서 네트워크 흐름은 공개or외부IP주소 -> 로컬or내부IP주소로 이동함
  • 그렇다면 로컬 네트워크 외부의 다른 컴퓨터와 연결되어 게임을 하려면?
    • 다른 유저의 외부 IP주소를 알고있다면 연결할 수 있다. -> 하지만 비현실적, 비효율적
    • Dedicated Server는 연결 가능한 IP주소 중 하나를 할당하고, 해당 IP주소를 다른 플레이어들에게 공유해 서로 연결이 가능하게 함 -> 게임에 플레이어가 많아질수록 더 많은 서버, 더 많은 저장공간, 더 많은 자원이 필요
    • Listen Server는 플레이어중 하나가 Listen Server로 참여, 다른 플레이어들이 여기에 붙는다 -> 서버는 Listen Server 플레이어의 호스팅만 담당한다면 Dedicated Server에 비해 코스트가 줄어든다.

Online Subsystem이란?

  • 유저들이 IP Address 없이도 게임에 접속할 수 있도록 만들어진 Code Base
  • 플랫폼의 라이브 서비스에 맞춘 코드를 작성할 필요 없도록 크로스플랫폼의 세부사항을 언리얼의 Abstraction layer에서 자체적으로 처리했음
  • 즉 Onlinesubsystem은 다양한 온라인 서비스에 연결되도록 설계된 네트워킹 추상화 계층
  • 이러한 온라인 서브시스템을 사용한 플러그인을 패키징해 IP 주소의 입력 없이 간단히 Play 버튼 하나만으로 멀티플레이 세션에 접속할 수 있도록 디자인해보자.

Online Subsystem

  • 온라인 플랫폼 서비스에 접근하는 기능 제공
  • Xbox, Steam과 같은 온라인 플랫폼 서비스는 친구, 업적, 세션 등의 기능을 제공하는 자체 서비스셋이 있고, 온라인 서브시스템은 이런 다양한 서비스를 처리하도록 설계된 일련의 인터페이스가 있음
  • 그래서 온라인 서브시스템을 사용하려면 타겟 플랫폼을 설정하고 프로젝트를 구성해야함
  • Engine.ini 파일에서 다음과 같은 블럭을 추가해 기본 플랫폼 서비스를 지정한다.
[OnlineSubsystem]
DefaultPlatformService=<Platform>
  • I 타입 클래스로, IOnlineSubsystem::Get() static 함수를 통해 클래스를 얻어 사용할 수 있다.

Session Interface

  • 게임 세션의 생성, 관리, 파괴 로직을 담당하는 인터페이스
  • 세션 검색과 매치메이킹 기능 또한 담당
  • 세션 = 게임 서버에서 돌아가는 인스턴스
    • Lifetime of Session
      • Create Session -> 유저 대기 -> 유저 등록 -> 세션 시작 -> 게임 플레이
      • 게임 종료 후 세션 종료 -> 등록된 유저 해제 -> (필요시) 세션 업데이트 or 매치 설정 변경 or 세션 Destory
    • Session Interface Functions
      • CreateSession()
      • FindSessions()
      • JoinSession()
      • StartSession()
      • DestroySession()
      • 이 함수들만 기억해도 작동하는 게임을 만들 수 있다.

세션 생성 및 참가 로직

  • 이렇게 소개했을 땐 내가 짠 로직과 다를게 없다.. 뭐가 잘못됬는지 알아보자.
  • 이러한 로직을 다루는 Class를 생성

'Unreal 이론' 카테고리의 다른 글

Multiplayer Games Network model  (0) 2024.11.24
게임의 완성  (0) 2024.11.23
게임 플로우 다듬기  (1) 2024.11.21
헤드업디스플레이의 구현  (0) 2024.11.14
인공지능 - 행동트리 모델의 구현  (0) 2024.11.11

댓글()

Multiplayer Games Network model

Unreal 이론|2024. 11. 24. 17:29

Single Games

  • 싱글 게임은 단일 컴퓨터에서 단일 게임 세션으로 구성됨
  • 네트워크를 통해 다른 컴퓨터에서 실행되는 게임의 다른 인스턴스로 정보를 전송할 필요 없음

Multiplayer Games

  • 두개 이상의 인스턴스가 서로 다른 컴퓨터에서 실행되는 형태
  • 서로 다른 인스턴스에서의 변경사항 (ex: 캐릭터 입력)은 게임의 다른 인스턴스로 전송되야함
  • 그러한 정보를 어떻게 옮기는가? 
    • Peer to Peer
      • 정보 전송의 가장 간단한 방법
      • 변경사항이 다른 플레이어의 캐릭터로 "직접" 전송된다
      • 플레이어가 많아질수록 많은 양의 데이터가 네트워크를 통해 전송되야 하므로 부하 증가
      • Authoritative 버전의 게임이 없다 -> 로컬 게임의 정보가 변경될 때 마다 인스턴스가 변경되므로 어떤 플레이어의 게임 인스턴스가 올바른가? -> 어떤것도 올바른 버전의 게임이 아님 -> 클라이언트 변조 문제로도 연결 가능
    • Client-Server model
      • 단일 시스템이 서버로 지정되고, 다른 모든 시스템은 클라이언트로 지정
      • 모든 클라이언트는 서버하고만 연결되어 통신하며, 다른 클라이언트에게 정보를 전송하지 않는다.
      • 서버와 정보를 송수신하기 위한 대역폭 요구사항만 충족하면 된다
      • 서버가 올바른 버전으로 정립된 게임 버전을 실행한다는게 핵심
      • 각 클라이언트가 서버에 요청을 보낼 때 마다(ex: 캐릭터를 움직이는 요청) 서버는 적절한 요청인지 확인
      • 서버가 적절한 요청인지 확인 후 다른 클라이언트들에게 정보를 전달 -> 이 과정을 복제(replication)라고 함

클라이언트-서버 모델의 종류

  •  Listen Server
    • 한명의 플레이어가 서버를 맡고, 나머지 플레이어가 클라이언트
    • 서버를 맡은 플레이어가 게임을 플레이하며 그래픽을 렌더링함
    • 서버를 맡은 플레이어가 응답속도에서 좀 더 유리함
  • Dedicated Server
    • 게임을 플레이 하지 않는 서버컴퓨터 존재
    • 그래픽을 서버컴퓨터가 렌더링하진 않는다
    • 서버가 Authoritative 버전 게임의 시뮬레이션만 담당하며 클라이언트들에게 데이터를 복제해 전송한다
    • 특히 대규모 MMO나 많은 유저가 빠른 응답속도를 필요로 하는 게임에 적합

What Unreal Engine uses?

  • Authoritative Client-Server model
  • 한 컴퓨터는 항상 서버, 다른컴퓨터는 클라이언트로 서버에 연결된다.
  • 서버 버전만이 항상 Authoritative 버전
  • 싱글 플레이어 게임도 클라이언트-서버 모델(클라이언트와 서버가 같은 컴퓨터)

Testing Multiplayer - Lan & PIE

  • 멀티플레이 테스트 -> PIE의 Multiplayer Options 확인
    • Play As Listen Server -> 에디터 인스턴스가 Server와 Client 권한을 동시에 가짐. 다른 인스턴스는 Client로 에디터 인스턴스에 연결된것.
    • Standalone이나 Listen Server는 쉽게 생각할 수 있지만, Play as Client는 좀 다르다
    • 백그라운드에 Dedicated Server가 올라가고, 서로 다른 클라이언트가 설정한 수 만큼 인스턴스로 생성되어 윈도우에 표시된다.
    • 3rd person 템플릿에 배치된 기본 캐릭터에 possess 되지 않고, 클라이언트 수만큼 캐릭터가 스폰된다.

Setting up LAN Connection

  • 하나의 라우터에 여러 플레이어가 붙어서 플레이하는 게임 형태
  • 각각의 플레이어는 고유한 local IP 주소를 가지고 있다.
  • 동일한 네트워크 환경에 Local IP로 접속하는것

Open Level(), ClientTravel()

  • Open Level 함수도 그냥 썻었는데, 짚고 넘어갈 부분이 있는것 같다.
  • 첫번째 파라미터가 월드 컨텍스트 오브젝트. 간단하게 this 라는 키워드를 사용했는데, 월드에 존재하여 해당 월드의 컨텍스트를 전달할 수 있는 오브젝트이다.
  • ClientTravel은 APlayerController 클래스의 함수.
  • GetGameInstance()->Get***PlayerController() 함수를 통해 PlayerController를 가져와 ClientTravel을 호출

'Unreal 이론' 카테고리의 다른 글

Online Subsystem  (0) 2024.11.25
게임의 완성  (0) 2024.11.23
게임 플로우 다듬기  (1) 2024.11.21
헤드업디스플레이의 구현  (0) 2024.11.14
인공지능 - 행동트리 모델의 구현  (0) 2024.11.11

댓글()

게임의 완성

Unreal 이론|2024. 11. 23. 23:02

[이득우의 언리얼 프로그래밍 Part2 수업의 정리]

 

게임 모드

  • 멀티플레이를 포함해 게임에서 유일하게 존재하는 게임의 심판 오브젝트
  • 최상단에서 게임의 진행을 관리하며, 게임 판정에 관련된 중요한 행동을 주관하는데 적합
  • 다양한 게임 규칙을 적용할 수 있도록 핵심 기능과 분리해 설계하는것이 바람직
  • 게임의 상태와 플레이어의 상태를 별도로 저장할 수 있는 프레임웍 제공
  • 지금의 프로젝트는 싱글 게임이기 때문에 GameState와 PlayerState는 사용하지 않음

 

구현을 위해 GameMode 클래스에 코드 작성

  • 현재 진행되고 있는 게임의 점수와 게임 클리어를 위한 점수 두가지 설정
  • CurrentScore 같은 경우는 개별 플레이어의 점수이므로, 게임의 규모가 커진다면 PlayerState에 보관하는것이 좋다
  • StageGimmick 클래스의 OnOpponentDestroyed 함수가 적을 처치했을 때 호출되므로, 여기서 점수를 추가하도록 구성하는게 좋다
  • 클리어했을 땐 보상상자가 나오는 로직 대신 return시켜 게임이 그대로 끝나도록 구성
  • 플레이어가 죽는 경우엔 ABCharacterPlayer 클래스의 SetDead 함수에 로직 작성
  • 이렇게 중요한 정보를 GameMode를 호출해 전달하면 GameMode 클래스에선 사용자가 어떠한 액션을 취하도록 유도
  • 가장 적합한 방법은 UI를 띄워주는것. 하지만 GameMode는 UI 컨트롤에 적합하지 않으므로 UI를 띄워달라고 별도로 명령을 내린다
  • PlayerController에 GameScoreChanged, GameClear, GameOver 세 함수를 선언하고 GameMode에 불러온다.
void AABGameMode::OnPlayerScoreChanged(int32 NewPlayerScore)
{
	CurrentScore = NewPlayerScore;

	AABPlayerController* ABPlayerController = Cast<AABPlayerController>(GetWorld()->GetFirstPlayerController());
	if (ABPlayerController) {
		ABPlayerController->GameScoreChanged(CurrentScore);
	}

	if (CurrentScore >= ClearScore) {
		bIsCleared = true;
		if (ABPlayerController) {
			ABPlayerController->GameClear();
		}
	}
}

void AABGameMode::OnPlayerDead()
{
	AABPlayerController* ABPlayerController = Cast<AABPlayerController>(GetWorld()->GetFirstPlayerController());
	if (ABPlayerController) {
		ABPlayerController->GameOver();
	}
}
  • 이후 같은 기능을 하는 K2_OnGameState 함수들을 선언해주고 블루프린트에서 구현

게임의 저장 기능

  • 언리얼의 SaveGame 클래스를 상속받아 ABGameSave 클래스를 Player 폴더에 생성
  • RetryCount라는 간단한 변수 추가 후 PlayerController에 SaveGame 객체 가져옴
  • 게임이 시작되면 저장된 세이브 데이터가 있는지 확인 후 이것을 로딩하는 코드 작성
  • UGameplayStatics에서 제공하는 LoadGameFromSlot(TEXT("Player0"), 0) 함수 활용해 저장
    • Player0 -> 세이브 파일명, 0-> 플레이어 아이디. 싱글플레이의 경우 항상 0번 지정

게임 패키징

  • 에디터 상단 툴바의 Platforms->Windows->Shipping(디버깅에 관련된 모든 부분 제외된 가장 가벼운 선택지)
  • Project Setting->Package->Additional builds for this Project 아래의 advanced 항목-> Additional Asset Directories to Cook : 우리가 사용한 에셋들을 플랫폼에 맞춰서 변환하는 작업
  • 기본적으로 추가된 항목 외에도 아이템 등 코드에서 불러들이는 에셋들을 수동으로 추가해줘야함

'Unreal 이론' 카테고리의 다른 글

Online Subsystem  (0) 2024.11.25
Multiplayer Games Network model  (0) 2024.11.24
게임 플로우 다듬기  (1) 2024.11.21
헤드업디스플레이의 구현  (0) 2024.11.14
인공지능 - 행동트리 모델의 구현  (0) 2024.11.11

댓글()

계속되는 세션 오류

개발 일지|2024. 11. 22. 23:06

세션 참가가 계속 안된다.

도대체 무슨 차이인거지?

 

서버를 클라우드에 옮겨서 테스트를 해봐야하나..

 

생성되있는 세션을 검색하지 못하는 문제를 해결해야하는데..

'개발 일지' 카테고리의 다른 글

OnlineSubsystem Steam 연결 및 Create Session  (0) 2024.11.27
Listen Server와 Dedicated Server  (0) 2024.11.26
세션 관리 이동  (0) 2024.11.20
세션 생성 시도시 Fatal Error  (0) 2024.11.19
이번엔 월드스폰  (0) 2024.11.18

댓글()

게임 플로우 다듬기

Unreal 이론|2024. 11. 21. 14:55

[이득우의 언리얼 프로그래밍 Part2 수업의 정리]

 

게임 구성 요소의 분류

  • 세개의 레이어를 기준으로 게임을 구성하는 다양한 기능의 구현

 

게임플로우를 위해 보강할 내용

  • 죽었을 때의 NPC와 플레이어의 처리
  • 이동속도의 적용
  • 포션/스크롤 아이템의 추가 구현과 캐릭터의 적용
  • 스탯 기능 및 UI의 기능의 보강

죽었을 때 NPC의 인공지능 로직이 더이상 작동하지 않도록 처리

  • NonPlayer 클래스의 SetDead 함수에 StopAI 실행되도록 추가

죽었을 때 플레이어가 더이상 입력을 할 수 없도록 처리

  • SetDead 구현을 하지 않았기 때문에, 플레이어 클래스에 SetDead 구현
  • SetDead 함수에서 PlayerController를 가져오고, DisableInput으로 입력 끄기
  • 이렇게 구현했다면 BeginPlay 함수에서 Enable 함수 추가
void AABCharacterPlayer::BeginPlay()
{
	Super::BeginPlay();

	APlayerController* PlayerController = Cast<APlayerController>(GetController());
	if (PlayerController) {
		EnableInput(PlayerController);
	}

	SetCharacterControl(CurrentCharacterControlType);

}

void AABCharacterPlayer::SetDead()
{
	Super::SetDead();

	// Stop Input
	APlayerController* PlayerController = Cast<APlayerController>(GetController());
	if (PlayerController) {
		DisableInput(PlayerController);
	}
}

 

스탯이 변경됐을 때 이동속도의 변화 적용

  • MovementSpeed 참고해서 적용
  • CharacterBase 클래스에 스탯 변경시 반영 함수 추가해 델리게이트에 연결
  • 초기화 단계에서 수행되는 PostInitializeComponents 함수에서 등록

 

아이템 추가로 HP회복 및 스탯 변경 구현

  • ABItemData를 상속받은 Potion 및 Scroll 클래스 Item 폴더에 생성
  • ItemData의 생성자 코드와 GetPrimaryAsset코드를 의무적으로 모든 아이템들이 구현하도록 설정
UCLASS()
class ARENABATTLE_API UABPotionItemData : public UABItemData
{
	GENERATED_BODY()
	
public:
	UABPotionItemData();

	FPrimaryAssetId GetPrimaryAssetId() const override {
		// 생성될 에셋의 아이디 직접 지정
		return FPrimaryAssetId("ABItemData", GetFName());
	}
	
public:
	UPROPERTY(EditAnywhere, Category = Hp)
	float HealAmount;
};
  • 빌드 후 에디터에서 포션의 회복량에 따른 DataAsset 추가

  • 위와 비슷하게 스크롤, 무기도 여러 종류를 스탯을 달리해 추가
  • ABCharacterStatComponent 클래스에 아이템 습득에 따른 스탯과 HP의 변화를 반영할 수 있도록 인라인 함수 추가, 값이 변경됬으니 BroadCast로 델리게이트 연결
  • CharacterBase 클래스에 포션과 스크롤 습득 기능 구현

HpBar 기능 확장

  • Hp바가 직관적이지 않으니 Hp바 위의 레이어에 숫자 표기 추가
  • Vertical Box에 overlay 블록 추가, hierarchy 수정
  • 텍스트 블록을 가져와서 Hp값에 따른 변화 적용

기본적인 게임 플로우를 다듬다 보면 기본 데이터들의 지속적인 수정이 불가피

  • 아이템은 Data Asset 우클릭->Bulk Edit Via Property Maxtrix
    • Grid 기능을 사용해 엑셀 셀 단위로 전체 아이템 값들을 바꿀수 있도록 인터페이스 제공
  • GameData의 엑셀 데이터
    • 엑셀에서 수정 후 Reimport하면 변경된 값 바로 적용가능

'Unreal 이론' 카테고리의 다른 글

Multiplayer Games Network model  (0) 2024.11.24
게임의 완성  (0) 2024.11.23
헤드업디스플레이의 구현  (0) 2024.11.14
인공지능 - 행동트리 모델의 구현  (0) 2024.11.11
인공지능 - 행동트리 모델의 이해  (2) 2024.11.10

댓글()

세션 관리 이동

개발 일지|2024. 11. 20. 21:55

GameInstance에서 세션의 데이터를 관리하고, PlayerController 클래스에서 세션 생성 및 참여 로직을 관리하는게 맞는것 같다.

 

플레이어 한명이 각각 세션을 생성하고 참여하니까 그렇게 하는게 맞는것 같다.

 

코드가 좀 꼬여서 합치고 테스트 해볼예정

'개발 일지' 카테고리의 다른 글

Listen Server와 Dedicated Server  (0) 2024.11.26
계속되는 세션 오류  (0) 2024.11.22
세션 생성 시도시 Fatal Error  (0) 2024.11.19
이번엔 월드스폰  (0) 2024.11.18
세션 관리 로직 통합  (0) 2024.11.17

댓글()

세션 생성 시도시 Fatal Error

개발 일지|2024. 11. 19. 22:09

세션 생성 시도를 하니 Fatal Error가 뜨면서 엔진이 꺼졌다.

 

아마 GameInstance로 세션 관련 로직을 옮기면서, GameInstance는 게임 전체에 존재하는 클래스다 보니

속해있는 World의 컨텍스트를 올바로 가져올 수 없어서 그런것 같다.

 

그리고 다른 사람들이 데디케이트 서버를 연습삼아 해보는걸 보면, 블루프린트의 OpenLevel 노드를 사용해 IP주소를 입력하는 부분이 있었다.

 

나는 이런 과정이 코드에 없고, PIE에서 계속 테스트를 해보려고 했어서 계속 여기저기서 문제가 생긴것 같다.

 

근데 나는 PIE에서 세션 생성 및 참여 - 다음 Level에 스폰까지 확인하고 패키징 후 바뀐 서버 환경으로 계속 개발을 해보려고 했는데, 방향성이 잘못된건가?

 

생각이 많아진다..

'개발 일지' 카테고리의 다른 글

계속되는 세션 오류  (0) 2024.11.22
세션 관리 이동  (0) 2024.11.20
이번엔 월드스폰  (0) 2024.11.18
세션 관리 로직 통합  (0) 2024.11.17
OnlineSubsystem  (0) 2024.11.16

댓글()

이번엔 월드스폰

개발 일지|2024. 11. 18. 22:39

이제 세션 생성은 된다. 각 함수마다 초기화 하도록 수정했는데, 이러면 전체 클래스를 하나로 관리하려고 한 시도가 좀 의미없어지긴 하는데..

 

GetWorld가 올바른 월드 컨텍스트를 가져오지 못하고 있다.

이것도 빨리 고쳐보자..

'개발 일지' 카테고리의 다른 글

세션 관리 이동  (0) 2024.11.20
세션 생성 시도시 Fatal Error  (0) 2024.11.19
세션 관리 로직 통합  (0) 2024.11.17
OnlineSubsystem  (0) 2024.11.16
7. 온라인세션? 쉽지않다  (0) 2024.11.12

댓글()