Unreal Engine - 야구 게임(리슨 서버)

2025. 3. 25. 23:37·Unreal Engine

 

1. 기본 로직


1 - 1. 게임 시작 시

  • 레벨 BP
    • UI를 띄워주고,
    • UserID를 서버라면 HOST로 클라이언트라면 GUEST로 세팅해준다.

Level Blueprint

  • PlayerController
    • BeginPlay에서 아래와 같이 Widget의 이벤트 디스패처와 PlayerController를 Binding 해준다.

  • GameMode
    • BeginPlay에서 아래와 같이 게임에 필요한 값을 초기화 한다.
      • 난수 생성
      • turn 과 count 초기화
      • 타이머 초기화

 

1 - 2. 숫자 입력 받기

 

숫자 입력

  • UI에 /와 숫자를 입력한 다음 enter를 누르게 되면, UI의 SetMessagetoUserController가 call되는데 이 이벤트 디스패처는 PlayerController에 OnSendMessagetoServer와 바인딩 되어있다.

 

입력 처리

  • UI 함수와 바인딩 된 이벤트는 아래와 같이 생겼고, /라는 문자를 잘라준 다음 GameMode의 GotMessageFromClient 이벤트를 call해서 로직 처리를 하게 된다.

 

1 - 3. 입력 받은 숫자 처리

 

입력받은 숫자는 모두 서버에서 처리를 해주고, 그 결과값을 다시 보내서 UI로 출력할 수 있도록 구현하였다

 

GameMode

  • GameMode의 GotMessagefromClient 이벤트는 "서버에서 실행"으로 동작한다.
  • 가장 먼저 현재 turn 과 userID를 체크하게 된다.
    • 이때 return 값이 1이면 HOST, 2면 GUEST가 된다.

  • 이 함수의 return 값이 1또는 2인 경우만 유효한 경우이기 때문에 다음 처리를 진행한다.
    • 유효하지 않은 경우의 예시는 GUEST turn 일때 HOST가 입력하는 등의 경우를 말한다.
  •  Check Turn and ID 함수 코드
    • 로직을 설명하자면, TurnIndex는 매 턴마다 1씩 증가하게 되고, 1부터 시작하기 때문에 홀수인 경우는 HOST 짝수인 경우는 GUEST로 판정하게 된다.
    • 또한 인풋으로 받는 Message는 컨트롤러에서 가져온 UserID이다.
더보기
int32 ABaseBallGameMode::CheckTurnAndID(FString Message)
{
	//odd number and "HOST"
	if (TurnIndex % 2 != 0 && Message.Equals(TEXT("HOST")))
	{
		TurnIndex++;
		HostCount--;

		return 1;
	}

	//even number and "GUEST"
	if (TurnIndex % 2 == 0 && Message.Equals(TEXT("GUEST")))
	{
		TurnIndex++;
		GuestCount--;

		return 2;
	}

	return 3;
}
  • 이후 유효한 input인 경우 CheckResult 함수를 통해 스트라이크와 볼 판정을 해준다.
  • CheckResult 코드
    • 유효하지 않은 input의 경우 OUT을 리턴
    • 정답인 경우 CLEAR 리턴
    • 나머지 경우 스트라이크와 볼 갯수를 세서 리턴해준다.
더보기
FString ABaseBallGameMode::GetResult(FString Message)
{
	//false
	if (!ValidCheck(Message))
		return FString(TEXT("OUT"));

	int32 Res = FCString::Atoi(*Message);
	
	TArray<int32> Temp; //input value

	int32 Strike = 0;
	int32 Ball = 0;

	Temp.Add(Res / 100);
	Res -= (Res / 100) * 100;
	Temp.Add(Res / 10);
	Res -= (Res / 10) * 10;
	Temp.Add(Res);

	for (int i = 0; i < Temp.Num(); ++i)
	{
		//if find
		if (ResultArray.Find(Temp[i]))
		{
			if (ResultArray[Temp[i]] == i)
				Strike++;
			else
				Ball++;
		}
	}

	if (Strike == 3)
	{
		return FString("CLEAR");
	}

	return FString::Printf(TEXT("%d S %d B"), Strike, Ball);
}
  • 결과를 가지고 Set Result Text 함수를 통해 화면에 출력해주게 된다.
    • Input은 우리가 입력한 숫자를 말하고
    • Result는 판정 결과를 말한다.
    • 이 이벤트는 UI와 연동되는 함수이다. UI 로직은 아래에서 자세히 설명할 것이다.

  • 이후 결과를 통해 승 패 결과를 WinCheck 함수를 통해 진행한다.
    • 이 함수는 간단하게 매개변수 Message가 CLEAR 인지 확인하는 함수이다.

 

1 - 4. 승패 처리

 

이긴 경우

  • 바로 위에서 본 WinCheck함수가 true 라면 SetWinTieText라는 이벤트를 통해 화면 중앙에 Win 이라는 문구를 출력해주게 된다.
  • 이후 Check Turn and ID 함수를 통해 가져온 Turn 변수를 통해
    • 1이면 Host이므로 Host의 win count 를 증가
    • 2면 Guest 이므로 Guest의 win count를 증가시킨다.

  • 마지막으로 Win Game 함수를 통해서 UI와 값들을 리셋해주면 된다.

 

 

비긴 경우

  • Win Check가 false이고 Guest의 count가 0인 경우는 비긴 경우가 된다.
  • 아래 사진과 같이 비겼다는 것을 알려주는 UI 출력을 위해 Set Win Tie Text 함수를 호출 후

  • Tie Game 함수를 통해 UI및 값을 리셋해주면 된다.

 

이기거나 비기지 않은 일반적인 경우

  • UI와 타이머 등을 업데이트 해주면 된다.

 

 

2. UI 로직


이게 맞는 방식인지는 잘 모르겠다.....

 

내가 만든 UI 로직 순서

  • UserWidget BP에서 해당 UI를 세팅해주는 함수를 만든다.

  • PlayerController에서 해당 UI 이벤트를 call하는 이벤트를 만든다.
    • 이때 이 이벤트는 "소유중인 클라이언트에서 실행" 으로 설정한다.

  • GameMode에서 PlayerController의 'UI이벤트를 call하는 함수"를 call하는 함수를 만든다.

  • 이 GameMode에 존재하는 함수는 우리가 짜는 로직에서 사용하게 된다.

 

동작 순서

  • 동작하는 방식은 함수 만드는 순서의 반대로 동작하면 된다.
  • GameMode(서버) 의 로직에서 GameMode에 존재하는 이벤트를 call한다.
  • GameMode의 이벤트는 PlayerController의 "소유중인 클라이언트에서 실행"인 함수를 call한다.
  • 최종적으로 PlayerController의 함수는 UI의 함수를 call 한다.

 

 

3. 타이머 로직


아직 BP에 익숙하지 않아서 타이머 로직을 C++로 만들고 BP에서 사용하도록 구성했다.

 

  • BeginPlay에서 Timer를 set한다. (GameMode)

  • 참고) StartTimer 함수
더보기
void ABaseBallGameMode::StartTimer()
{
	GetWorldTimerManager().SetTimer(Timer, this, &ABaseBallGameMode::EndTimer, 10.f, false);
}
  • 이후 Tick을 통해 아래와 같이 현재 Timer의 값을 가져오는 함수와 UI를 업데이트 해주는 이벤트인 SetTimerText를 call한다.

  • 참고) GetRemainTime 함수
더보기
void ABaseBallGameMode::GetRemainTime()
{
	RemainingTime = GetWorldTimerManager().GetTimerRemaining(Timer);
}
  • 만약 Turn이 끝나서 다음 Turn으로 넘어가게 된다면(아래의 경우들) Timer를 clear해주는 함수를 call해주면 된다. 
    • 제대로 입력이 끝나서 Turn이 넘어가거나
    • 한명이 승리하거나
    • 비기거나

  • 참고) Clear Timer 함수
    • Clear Timer는 이후 바로 다시 타이머를 시작하면 되기 때문에
    • StartTimer 함수를 call하면 된다.
더보기
void ABaseBallGameMode::ClearTimer()
{
	GetWorldTimerManager().ClearTimer(Timer);
	StartTimer();
}
  • 타이머가 끝난 경우
    • StartTimer함수가 10초가 지나면 EndTimer라는 함수를 call해서 값들을 리셋해주는 작업이 필요하다.
    • TurnIndex를 증가시켜주고, 현재 turn에 맞는 Count를 감소시키면 된다.
    • 이후 Timer를 리셋하고, ResetValues라는 함수를 call한다.
      • ResetValues 함수는 UI 나 변수를 리셋해주는 역할을 한다.
      • 이 함수는 C++ 함수인데, BP의 함수를 불러와서 써야하는 상황이다!
      • 아래의 BlueprintImplementableEvent 로 해결했다.
더보기
void ABaseBallGameMode::EndTimer()
{
	TurnIndex++;
	if (TurnIndex % 2 == 0)
		HostCount--;
	else
		GuestCount--;

	ClearTimer();
	StartTimer();
	ResetValues();
}

 

트러블슈팅

우리가 가진 로직은 BP에 존재하는데, Timer함수 관련 로직은 C++로 만들어서 C++로직 안에 BP에서 만든 이벤트를 호출하고 싶은 상황이다.

 

해결) C++에서 선언하고 BP에서 정의하는 함수

  • 우리가 사용하는 기본적인 로직은 BP로 동작하는데, 타이머 로직은 c++로 구성하게 되었다.
  • 이때 EndTimer안에서 BP의 로직을 넣어주고 싶은데, 어떤 방법이 있을지 찾아보다가 BlueprintImplementableEvent 지정자를 알게 되었다.
  • 이 방식은 C++에서 함수 선언만 하고, 그 구현은 BP에서 하도록 하는 지정자이다.

함수 선언 (C++)

UFUNCTION(BlueprintImplementableEvent, Category = "MyEvents")
void ResetValues();

 

함수 정의 (BP)

 

 

4. 결과


https://youtu.be/ePo2tyuhsZM?si=GPG16644QaRRqRCe

 

'Unreal Engine' 카테고리의 다른 글

Unreal Engine - 데디케이티드 서버 개념 및 실습  (0) 2025.03.27
Unreal Engine - 플러그인 만들기  (0) 2025.03.26
Unreal Engine - Standalone을 리슨 서버로 확장하기  (0) 2025.03.24
Unreal Engine - Gameplay Framework  (0) 2025.03.24
Unreal Engine - UObject  (0) 2025.03.24
'Unreal Engine' 카테고리의 다른 글
  • Unreal Engine - 데디케이티드 서버 개념 및 실습
  • Unreal Engine - 플러그인 만들기
  • Unreal Engine - Standalone을 리슨 서버로 확장하기
  • Unreal Engine - Gameplay Framework
gbleem
gbleem
gbleem 님의 블로그 입니다.
  • gbleem
    gbleem 님의 블로그
    gbleem
  • 전체
    오늘
    어제
    • 분류 전체보기 (184)
      • Unreal Engine (73)
      • C++ (19)
      • 알고리즘(코딩테스트) (27)
      • TIL (60)
      • CS (4)
      • 툴 (1)
  • 블로그 메뉴

    • 홈
    • 카테고리
  • 링크

    • 과제용 깃허브
    • 깃허브
    • velog
  • 공지사항

  • 인기 글

  • 태그

    DP
    blend pose
    gamestate
    Vector
    enhanced input system
    싱글턴
    BFS
    const
    addonscreendebugmessage
    character animation
    템플릿
    applydamage
    actor 클래스
    C++
    motion matching
    cin함수
    additive animation
    매크로 지정자
    상속
    map을 vector로 복사
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
gbleem
Unreal Engine - 야구 게임(리슨 서버)
상단으로

티스토리툴바