반응형

이번에 작업할 내용은 파라곤 에셋 적용, 간단한 로비 구현, 플레이어 이동 버그 수정, 플레이어 타입 구분 등이 있다.

 

먼저 언리얼에서 기본으로 제공해주는 에셋으로는 제대로 된 컨텐츠를 구현하기에는 리소스가 부족하니, 예전에 무료로 배포했던 '파라곤' 에셋을 사용하여 컨텐츠를 구현 해주자.


에셋을 다운 받으면, 알아서 애니메이션과 이동등을 블루프린트로 만들어 놓았다.

여기서 내가 필요한 것을 추가하고 필요없는 걸 제외해서 간단하게 플레이어를 만들었다.

코드 또한 만들어 놓은 MyBoPlayer를 그대로 사용하되,

Yaw를 설정하는 부분만 따로 함수로 파서 블루프린트에 적용시켰다.

MyKallari 코드

UFUNCTION(BlueprintCallable)
void SetDesiredYaw();


void AMyKallari::SetDesiredYaw()
{
	if (Controller != nullptr)
	{		
		// find out which way is forward
		const FRotator Rotation = Controller->GetControlRotation();
		const FRotator YawRotation(0, Rotation.Yaw, 0);

		// get forward vector
		const FVector ForwardDirection = FRotationMatrix(YawRotation).GetUnitAxis(EAxis::X);

		// get right vector 
		const FVector RightDirection = FRotationMatrix(YawRotation).GetUnitAxis(EAxis::Y);

		//Cache
		{
			DesiredMoveDirection = FVector::ZeroVector;
			DesiredMoveDirection += ForwardDirection * DesiredInput.Y;
			DesiredMoveDirection += RightDirection * DesiredInput.X;
			DesiredMoveDirection.Normalize();

			const FVector Location = GetActorLocation();
			FRotator Rotator = UKismetMathLibrary::FindLookAtRotation(Location, Location + DesiredMoveDirection);
			DesiredYaw = Rotator.Yaw;
		}
	}
}

 

 

간단하게 리소스 적용을 완료했다.


이번에는 플레이어의 위치가 틀어지는 문제를 해결해보자.

우선 현재 문제가 발생하는 이유를 알아보기 위해 기존 코드의 작동 원리를 알아보자.

 

현재 코드가 패킷으로 부터 받은 좌표로 캐릭터를 이동시켜 주는 것이 아니라,

GameInstance의 HandleMove 함수에서 SetDestInfo 함수를 호출해주면서,

현재 상태를 MOVE_STATE_RUN으로 바꿔주고,

DestInfo에 위치 값을 넘겨준다.

 

그 다음, BoPlayer의 Tick 함수에서 현재 상태가 MOVE_STATE_RUN 일 경우에

해당 좌표(DestInfo)를 바라보는 방향으로 액터를 회전시켜서 앞으로 이동시켜주고 있다. (AddMovementInput)

 

즉, 해당 좌표(DestInfo)까지 이동하라고 한게 아니라 해당 좌표 방향으로 이동하라는 것이기 때문에,

위치가 틀어지는 문제가 발생하게 된것이다.

 

이를 해결해주기 위해 고민하다 해결방안을 떠올렸다.

일단 내가 생각했을 때는 제일 간단하고 확실한 해결방안이라고 생각한다.

바로 패킷으로 전달 받은 좌표(DestInfo)와 일정 거리가 벌어지면 강제로 좌표로 액터의 위치를 옮기는 것이다.

BoPlayer 코드 수정

    if (State == Protocol::MOVE_STATE_RUN)
    {
        //패킷으로 받은 PosInfo와 현재위치가 많이 떨어지면 강제로 그 위치로 이동.
        FVector Dest = FVector(DestInfo->x(), DestInfo->y(), DestInfo->z());
        if (FVector::Distance(GetActorLocation(), Dest) > 100)
            SetActorLocation(Dest);
        SetActorRotation(FRotator(0, DestInfo->yaw(), 0));
        AddMovementInput(GetActorForwardVector());
    }

 

일단 문제가 해결되었지만 가끔 플레이어가 강제로 움직이느라 버벅거리는 현상이 발생한다.

더 좋은 방법을 생각해 봐야 할 것 같다. ㅠ


간단한 캐릭터 선택창이 있는 로비를 만들어 주자.

빠르게 진행하기 위해 블루프린트로 간단하게 만들어 주었다.

기존에는 DevMap에서 실행했을 때 서버에 접속해 주었는데 그 부분만 로비의 Connect 버튼의 이벤트로 옮겨 주었다.

 

이제 DevMap(메인 맵)에서는 매 틱마다 패킷을 받아주는 작업과, Q를 눌렀을 때 플레이어가 퇴장하는 기능만 남아있다.

 

DevMap

 

 

로비 맵에서는 미리 만들어둔 WBP를 ViewPort에 띄워준다.

그리고 캐릭터 버튼을 누르면 SetPlayerCharacterType 함수가 호출되면서 플레이어의 타입을 저장해준다.

Connect 버튼을 누르면 서버에 접속하면서 플레이어가 선택한 캐릭터의 정보를 넘겨준다.

 

LobbyMap

 

WBP_Lobby

 

ServerPacketHandler 코드 수정

bool Handle_S_LOGIN(PacketSessionRef& session, Protocol::S_LOGIN& pkt)
{
	for (auto& Player : pkt.players())
	{

	}
	for (int32 i = 0; i < pkt.players_size(); i++)
	{
		const Protocol::ObjectInfo& Player = pkt.players(i);
	}

	Protocol::C_ENTER_GAME EnterGamePkt;
	Protocol::ObjectInfo* Player = EnterGamePkt.add_players();
	Player->set_player_type(pkt.players(0).player_type());
	Player->set_object_type(pkt.players(0).object_type());
	EnterGamePkt.set_playerindex(0);	
	//로비에서 선택한 캐릭터 Enum값 확인.
	UE_LOG(LogTemp, Warning, TEXT("Connected Character Type : %d"), Player->player_type());

	SEND_PACKET(EnterGamePkt);

	return true;
}

 

MyGameInstance 코드 수정

void UMyGameInstance::HandleSpawn(const Protocol::ObjectInfo& ObjectInfo, bool IsMine)
{
	//TODO : 플레이어 타입에 맞게 캐릭터 스폰
	UE_LOG(LogTemp, Warning, TEXT("Object type : %d, Player Type : %d"), ObjectInfo.object_type(), ObjectInfo.player_type());
}

 


 

반응형

'언리얼 엔진 서버 연동' 카테고리의 다른 글

플레이어의 공격과 피격(1)  (0) 2024.04.18
접속한 플레이어 타입에 맞춰서 스폰  (0) 2024.04.17
Job  (0) 2024.04.11
플레이어 이동 동기화 보정  (0) 2024.04.09
플레이어 이동 동기화  (0) 2024.04.09