35 - Save & Load, Network, Thread

Overcle·2023년 3월 22일
0

학원

목록 보기
28/29

수업내용


레벨이 전환 될때, GameMode가 다르다면 데이터유지에 제약사항이 발생할 경우가 있다.

GameInstance로 할수도 있고.
메모리 또는 저장매체를 이용하여 Save & Load 방식으로 유지 할 수도 있다.

Save Game Class

저장해야 되는 데이터 기준 = 초기화 되면 안되는 데이터

Load하는방법

  1. 원하는 Load 시점 찾기
  2. SaveGame Include
  3. Load 코드 추가.
		
	UUE11SaveGame* LoadGame = Cast<UUE11SaveGame>(UGameplayStatics::LoadGameFromSlot(TEXT("Save"), 0));
	AUE11PlayerState* State = Cast<AUE11PlayerState>(GetPlayerState());

	if (IsValid(LoadGame))
	{
		State->mPlayerInfo = LoadGame->mPlayerInfo;
		State->mCameraZoomMin = LoadGame->mCameraZoomMin;
		State->mCameraZoomMax = LoadGame->mCameraZoomMax;
	}
	else
	{
		//DataTable로 생성하여, 초기값 설정 후 불러오기
	}

Save하는방법

  1. 저장하고자 하는 클래스 접근
  2. SaveGame Include
  3. Save함수 생성 및 구현
	UUE11SaveGame* SaveGame Cast<UUE11SaveGame>(UGameplayStatics::CreateSaveGameObject(UUE11SaveGame::StaticClass()));
    
    AUE11PlayerState* State = Cast<AUE11PlayerState>(GetPlayerState());

	SaveGame->mPlayerInfo = State->mPlayerInfo;
	SaveGame->mCameraZoomMin = State->mCameraZoomMin;
	SaveGame->mCameraZoomMax = State->mCameraZoomMax;
	
	UGameplayStatics::SaveGameToSlot(SaveGame, TEXT("Save"), 0);

Save경로

FPaths:: 안에 다양한 경로가 지정되어있다.

FString FullPath = FPaths::ProjectSavedDir()+ TEXT("SaveGames/Save.txt");

	FArchive* Writer = IFileManager::Get().CreateFileWriter(*FullPath);

	if (Writer)
	{
		
	}

Network, Thread // 구조만 설계하고 나머진 내일.


Build.cs

        PublicDependencyModuleNames.AddRange(new string[]
        {
              "Core"
            , "CoreUObject"
            , "Engine"
            , "InputCore"
            , "AIModule"
            , "GameplayTasks"
            , "NavigationSystem"
            , "UMG"
            , "Niagara"
            , "MovieScene"
            , "LevelSequence"
            , "MediaAssets"
            , "Networking"
            , "Sockets"
        });

GameInfo.h

#include "Networking.h"
#include "Sockets.h"
#include "SocketSubsystem.h"
#include "HAL/Runnable.h"
#include "HAL/RunnableThread.h"

클래스 생성

부모 클래스 : 없음
이름 : NetworkManager
경로 : Network/

부모 클래스 : 없음
이름 : NetworkSession
경로 : Network/

부모 클래스 : 없음
이름 : PacketStream
경로 : Network/

NetworkManager.h

#pragma once

#include "../GameInfo.h"

/**
 * Network Singleton으로 설계.
 */
class UE11_API CNetworkManager
{
private:
	CNetworkManager();
	~CNetworkManager();


public:
	bool Init();


private:
	static CNetworkManager* mInst;

public:
	static CNetworkManager* GetInst()
	{
		if (!mInst)
			mInst = new CNetworkManager;

		return mInst;
	}

	static void DestroyInst()
	{
		if (mInst)
		{
			delete mInst;
			mInst = nullptr;
		}
	}
};

NetworkManager.cpp

#include "NetworkManager.h"

CNetworkManager* CNetworkManager::mInst = nullptr;

CNetworkManager::CNetworkManager()
{
}

CNetworkManager::~CNetworkManager()
{
}

bool CNetworkManager::Init()
{
	return true;
}

NetworkSession.h

#pragma once

#include "../GameInfo.h"

/**
 * 
 */
class UE11_API CNetworkSession
{
public:
	CNetworkSession();
	~CNetworkSession();

private:
	FSocket* mSocket;
	bool	mConnect;
	uint8	mReceivePacket[PACKET_SIZE];
	uint8	mSendPacket[PACKET_SIZE];

public:
	bool Connect(const FString& IPAddr, int32 Port);
	void Close();
	bool Receive(int32& PacketHeader, int32& Length, uint8* Packet);
	bool Send(int32 PacketHeader, int32 Length, uint8* Packet);
};

NetworkSession.cpp

#include "NetworkSession.h"
#include "PacketStream.h"

CNetworkSession::CNetworkSession()	:
	mSocket(nullptr),
	mConnect(false),
	mReceivePacket{},
	mSendPacket{}
{
}

CNetworkSession::~CNetworkSession()
{
	Close();
}

bool CNetworkSession::Connect(const FString& IPAddr, int32 Port)
{
	// 소켓을 생성한다.
	mSocket = ISocketSubsystem::Get(PLATFORM_SOCKETSUBSYSTEM)->CreateSocket(
		NAME_Stream, TEXT("Default"), false);

	// 문자열로 들어온 IP와 Port를 이용해서 주소 객체를 만들어준다.
	FIPv4Address	ip;
	FIPv4Address::Parse(IPAddr, ip);

	TSharedRef<FInternetAddr>	Addr = ISocketSubsystem::Get(PLATFORM_SOCKETSUBSYSTEM)->CreateInternetAddr();

	Addr->SetIp(ip.Value);
	Addr->SetPort(Port);

	mConnect = mSocket->Connect(*Addr);

	return true;
}

void CNetworkSession::Close()
{
	if (mConnect)
	{
		mSocket->Close();
		delete mSocket;
	}
}

bool CNetworkSession::Receive(int32& PacketHeader, int32& Length, 
	uint8* Packet)
{
	if (!mConnect)
		return false;

	bool Result = mSocket->Recv(mReceivePacket, PACKET_SIZE, Length,
		ESocketReceiveFlags::None);

	if (!Result || Length == 0)
		return false;

	CPacketStream	stream;
	stream.SetBuffer(mReceivePacket);

	stream.GetData(&PacketHeader, 4);
	stream.GetData(&Length, 4);
	stream.GetData(Packet, Length);

	return true;
}

bool CNetworkSession::Send(int32 PacketHeader, int32 Length,
	uint8* Packet)
{
	if (!mConnect)
		return false;

	CPacketStream	stream;

	stream.SetBuffer(mSendPacket);

	stream.AddData(&PacketHeader, 4);
	stream.AddData(&Length, 4);
	stream.AddData(Packet, Length);

	return mSocket->Send(mSendPacket, stream.GetLength(), Length);
}

PacketStream.h

#pragma once

#include "../GameInfo.h"

/**
 * 
 */
class UE11_API CPacketStream
{
public:
	CPacketStream();
	~CPacketStream();

private:
	uint8* mBuffer;
	int32	mLength;

public:
	void SetBuffer(uint8* Buffer)
	{
		mBuffer = Buffer;
	}

	int32 GetLength()
	{
		return mLength;
	}

public:
	void AddData(void* Data, int32 Size);
	void GetData(void* Data, int32 Size);
};

PacketStream.cpp

#include "PacketStream.h"

CPacketStream::CPacketStream()	:
	mBuffer(nullptr),
	mLength(0)
{
}

CPacketStream::~CPacketStream()
{
}

void CPacketStream::AddData(void* Data, int32 Size)
{
	FMemory::Memcpy(mBuffer + mLength, Data, Size);
	mLength += Size;
}

void CPacketStream::GetData(void* Data, int32 Size)
{
	FMemory::Memcpy(Data, mBuffer + mLength, Size);
	mLength += Size;
}
profile
게임 프로그래머 지망생의 발자취

0개의 댓글