OnlineSubsystem Steam 연결 및 Create Session

개발 일지|2024. 11. 27. 19:01

OnlineSubsystem Steam에 연결해보자

 

https://dev.epicgames.com/documentation/en-us/unreal-engine/online-subsystem-steam-interface-in-unreal-engine

먼저 언리얼 공식 문서에 검색해보면 다음의 구문을 Config/Engine.ini 파일에 추가하라고 되어있다.

[/Script/Engine.GameEngine]
+NetDriverDefinitions=(DefName="GameNetDriver",DriverClassName="OnlineSubsystemSteam.SteamNetDriver",DriverClassNameFallback="OnlineSubsystemUtils.IpNetDriver")
 
[OnlineSubsystem]
DefaultPlatformService=Steam
 
[OnlineSubsystemSteam]
bEnabled=true
SteamDevAppId=480
 
; If using Sessions
; bInitServerOnClient=true
 
[/Script/OnlineSubsystemSteam.SteamNetDriver]
NetConnectionClassName="OnlineSubsystemSteam.SteamNetConnection"

중간에 세션을 사용할거면 bInitServerOnClient=true 문장을 추가하라고 되있다.

아마 세션 멀티플레이 기능을 사용하지 않고 도전과제, 친구 등의 기능만 사용하는 개발자들을 위해 저부분을 주석처리 한것 같다.

우리는 세션 기능을 사용할것이기 때문에 주석을 풀어준다.

 

그리고 uproject 파일을 우클릭해 Generate project file을 해준다.


다음으로 할일은 Character 클래스에 세션 로직을 추가해 Steam에 실제로 연결이 되는지 확인하는 것이다.

1인칭 기본 템플릿으로 프로젝트를 생성한다.

plugin을 열어 OnlineSubsystem Steam을 체크해주면 에디터를 재시작하라고 뜨는데 순순히 따라준다.

이러면 플러그인은 추가됬고, 코드로 가서 로직을 작성해보자.

 

캐릭터 클래스에 세션 관리 로직을 추가한다.

멀티플레이 게임이기 때문에 각각의 유저가 세션 생성, 세션 참가 등의 활동을 수행할것이다.

따라서 캐릭터 클래스에 로직을 추가해야 각각의 플레이어가 문제없이 세션 관련 활동을 진행할 수 있을것이다.

 

캐릭터의 생성자에 OnlineSubsystem을 Get 함수로 받아오고 헤더파일에 선언한 OlnineSessionInterface 변수에 SessionInterface를 저장해준다.

// MenuCharacter.h

public:
	// Pointer to the online session Interface
	IOnlineSessionPtr OnlineSessionInterface;
    
// MenuCharacter.cpp

// Session Section
IOnlineSubsystem* OnlineSubsystem = IOnlineSubsystem::Get();
if (OnlineSubsystem) {
	OnlineSessionInterface = OnlineSubsystem->GetSessionInterface();
}

이러고 빌드를 하면 에러가 뜬다.

키워드는 C3646

IOnlineSessionPtr 타입의 변수로 선언한 OnlineSessionInterface가 unknown override specifier라는 에러이다.

보통 포인터 변수를 선언할 때 전방선언을 해준다. 하지만 IOnline session pointer 타입으로 선언한 OnlineSessionInterface 변수는 그렇게 할 수 없는데, 변수가 ESPMode의 thread safe으로 지정된 SharedPtr 변수이며 Thread Safe를 보장받는 스마트 포인터이기 때문이다.

 

두가지 해결방법이 있는데, 하나는 헤더에 OnlineSubsystem을 추가하는 것이고 다른 하나는 TSharedPtr로 스마트포인터를 감싸는것이다.

이번엔 후자의 방법을 간단히 사용하겠다.

public:
	// Pointer to the online session Interface
	TSharedPtr<class IOnlineSession, ESPMode::ThreadSafe> OnlineSessionInterface;

 

이렇게 해서 PIE로 테스트 해보면, 전부 Subsystem Null이 잡힌다.

Subsystem NULL은 NULL값이 아니라, 플랫폼이 NULL인것.

패키징해서 실행해보면 Steam 연결이 잘 되는걸 확인할 수 있다.


Delegates

  • 언리얼 엔진의 함수 reference를 가지고 있는 오브젝트
  • 함수를 바인딩해 시그널을 broadcasting시켜 각 함수가 실행되도록 하는 역할
  • 콜백 함수를 델리게이트에 바인딩 한다.
  • 게임에서 특정 이벤트가 일어나면 델리게이트는 fire되거나 broadcast를 실행하고 그 응답으로 콜백 함수가 실행된다.
  • 온라인 세션 인터페이스는 델리게이트들을 이용하는데, 세션을 생성하거나 참가하는걸 인터넷을 통해 정보를 수신받아야 할 수 있기 때문. 인터넷 속도에 따라 시간이 소요되는것도 당연

대충 이런 구조로 돌아간다


CreateSession

  • 헤더에 CreateSession함수, 델리게이트, 콜백함수를 선언해준다.
	UPROPERTY(BlueprintCallable)
	void CreateGameSession();

	void OnCreateSessionComplete(FName SessionName, bool bWasSuccessful);

private:
	FOnCreateSessionCompleteDelegate CreateSessionCompleteDelegate;
  • 그리고 cpp파일의 캐릭터 생성자에 델리게이트를 바인딩한다. 
    • 생성자에 델리게이트 바인딩? -> 객체 생성 시점에 해당 이벤트를 처리할 준비를 마치기 위해.
    • 기본 구조: FDelegateType::CreateUObject(UObjectInstance, &ClassName::FunctionName);
    • CreateUObject: 델리게이트에 현재 객체와 멤버함수를 바인딩, UObjectInstance: 델리게이트를 호출할 때 사용할 UObjectInstance, &ClassName::FunctionName: 호출할 함수의 포인터.
AMenuCharacter::AMenuCharacter():
	CreateSessionCompleteDelegate(FOnCreateSessionCompleteDelegate::CreateUObject(this, &AMenuCharacter::OnCreateSessionComplete))
  • 그리고 가장 먼저 할 일은, 세션이 이미 있는지 확인 후 없애는것.
  • 이후 세션 세팅을 설정해주고, CreateSession으로 세션 생성을 마친다.
void AMenuCharacter::CreateGameSession()
{
	// Called when pressing the 1 key
	if (!OnlineSessionInterface.IsValid()) {
		return;
	}
	auto ExistingSession = OnlineSessionInterface->GetNamedSession(NAME_GameSession);
	if (ExistingSession != nullptr) {
		OnlineSessionInterface->DestroySession(NAME_GameSession);
	}

	OnlineSessionInterface->AddOnCreateSessionCompleteDelegate_Handle(CreateSessionCompleteDelegate);

	TSharedPtr<FOnlineSessionSettings> SessionSettings = MakeShareable(new FOnlineSessionSettings());
	SessionSettings->bIsLANMatch = false;
	SessionSettings->NumPublicConnections = 4;
	SessionSettings->bAllowJoinInProgress = true;
	SessionSettings->bAllowJoinViaPresence = true;
	SessionSettings->bShouldAdvertise = true;
	SessionSettings->bUsesPresence = true;

	const ULocalPlayer* LocalPlayer = GetWorld()->GetFirstLocalPlayerFromController();

	OnlineSessionInterface->CreateSession(*LocalPlayer->GetPreferredUniqueNetId(), NAME_GameSession, *SessionSettings);
	
}

void AMenuCharacter::OnCreateSessionComplete(FName SessionName, bool bWasSuccessful)
{
	if (bWasSuccessful) {
		if (GEngine) {
			GEngine->AddOnScreenDebugMessage(
				-1,
				15.f,
				FColor::Blue,
				FString::Printf(TEXT("Created session: %s"), *SessionName.ToString())
			);
		}
	}
	else {
		if (GEngine) {
			GEngine->AddOnScreenDebugMessage(
				-1,
				15.f,
				FColor::Red,
				FString(TEXT("Faild to Create Session!"))
			);
		}
	}
}
  • 그다음 window 버전으로 패키징 후 실행시켜보면, 스팀 오버레이가 우하단에 출력되며 올바르게 연결된것을 확인할 수 있다.

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

플러그인 등록  (0) 2024.11.30
Join Session  (0) 2024.11.29
Listen Server와 Dedicated Server  (0) 2024.11.26
계속되는 세션 오류  (0) 2024.11.22
세션 관리 이동  (0) 2024.11.20

댓글()

Listen Server와 Dedicated Server

개발 일지|2024. 11. 26. 16:48

Listen Server로 구현하기로 했다.

 

Dedicated Server로 구현하려고 했는데, 문제가 너무 많다.

일반 가정집에서 Dedicated Server를 사용하려면, 방화벽과 포트포워딩 문제뿐만 아니라

동적으로 변하는 IP를 사용하는 문제, 클라우드 서버 금액문제 등 너무 번거롭다.

 

현재 프로젝트는 테스트하기 용이한 Listen Server로 구현한다.

제대로된 서버 맛보기 -> IOCP 윈도우 서버를 직접 구현해 MMO 게임 개발

이걸 다음 프로젝트의 목표로 삼고, 이번 프로젝트를 끝내면 개발해보자.

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

Join Session  (0) 2024.11.29
OnlineSubsystem Steam 연결 및 Create Session  (0) 2024.11.27
계속되는 세션 오류  (0) 2024.11.22
세션 관리 이동  (0) 2024.11.20
세션 생성 시도시 Fatal Error  (0) 2024.11.19

댓글()

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

댓글()