런타임 시 폰의 위치를 지정하는 주요 동기 중 하나는 플레이할 때마다 게임플레이를 다르게 하는 것입니다.
폰이 에디터 내에 배치되고 플레이할 때마다 움직이지 않는다면, 라운드를 한 번만 플레이하면 매번 폰이 어디에 배치될지 정확히 알게 될 것입니다. 이렇게 하는 대신 매번 폰을 랜덤하게 배치할 경우 시작 구성이 여럿 생길 것입니다.
알기 쉽게 설명해 보면, 5x5타일 크기 보드와 폰 5개가 있는 경우, 25개 중 5개를 선택하므로 53,130개의 서로 다른 구성이 나옵니다. 각 차원에서 보드 공간을 딱 1만 올려 크기를 6x6으로 만들고 폰 5개는 그대로 둔다 해도, 36개 중 5개를 선택하므로 숫자가 11,686,752로 증가합니다.
랜덤화는 다양한 게임플레이를 만들 수 있는 강력한 도구입니다.
랜덤 타일 좌표 생성하기
폰을 랜덤하게 배치하려면 보드 바운드 내에 랜덤 타일 좌표를 생성해야 합니다. 2차원 공간에서 랜덤하게 좌표를 생성하는 데는 여러 방법이 있습니다. 가장 흔한 방법은 균등 분포로, 이 예시에서 사용하게 됩니다. 균등 분포의 경우, 보드의 타일에 폰이 놓일 확률은 모든 타일에서 동일합니다. 자세한 내용은 https://en.wikipedia.org/wiki/Discrete_uniform_distribution을 참고하세요. 이를 위해 이름이 GenerateUniformRandomTileCoordinate인 유틸리티 함수를 만듭니다. 바운드 오브젝트를 가져다 어느 도메인 내에서 좌표를 생성할지 파악하는 함수입니다.
2차원 공간에서 균등 분포된 타일 좌표를 생성하려면 각 차원에서 서로 다른 integer를 생성한 뒤 타일 좌표 오브젝트에서 합칩니다.
using { /Verse.org/Simulation }
using { /Verse.org/Random }
UtilityFunctions<public> := module:
...
GenerateUniformRandomTileCoordinate<public>(BoardBounds:board_bounds)<transacts>:tile_coordinate =
tile_coordinate:
Left := GetRandomInt(BoardBounds.LeftBounds.Low, BoardBounds.LeftBounds.High)
이 함수는 다음 단계를 수행합니다.
보드의 왼쪽 바운드 내에서 랜덤 integer를 생성합니다.
보드의 앞쪽 바운드 내에서 랜덤 integer를 생성합니다.
이를 타일 좌표 오브젝트로 합칩니다.
지지집합이 유한하며 보다 이산적인 분포의 목록은 다음 표를 참고하세요. https://en.wikipedia.org/wiki/List_of_probability_distributions 이러한 분포 중 일부를 따른 좌표를 직접 생성하는 함수를 만들어 보고, 폰 배치가 어떻게 변경되는지 확인해 봐도 좋습니다.
열린 공간이 충분한지 확인하기
보드에 폰을 배치하기 전 고려해야 할 또 하나의 사항은 폰의 수를 모두 수용할 보드 공간이 충분한지 확인하는 것입니다. 이는 이름이 `NumberOfTileCoordinates`인 유틸리티 함수를 만들어 확인할 수 있습니다. 이 함수는 보드 바운드 오브젝트를 가져다 보드 위 타일의 수를 출력합니다.
using { /Verse.org/Simulation }
using { /Verse.org/Random }
UtilityFunctions<public> := module:
...
NumberOfTileCoordinates<public>(BoardBounds:board_bounds)<transacts>:int =
(BoardBounds.LeftBounds.High - BoardBounds.LeftBounds.Low) * (BoardBounds.ForwardBounds.High - BoardBounds.ForwardBounds.Low)폰 랜덤하게 배치하기
보드에 랜덤하게 폰을 배치하려면 얼마나 많은 폰을 생성할지 알아야 합니다. 이를 보드 클래스에 편집 가능한 변수로 추가하세요.
보드 위의 폰 개수를 결정했다면 폰 배치 과정은 다음과 같습니다.
NumberOfTileCoordinates를 이용해 폰의 개수만큼 이용 가능한 타일 좌표가 충분하도록 합니다.GenerateUniformRandomTileCoordinate로 랜덤하게 타일 좌표를 생성합니다.해당 좌표에 이미 폰이 있는지 확인합니다.
있다면 1단계로 돌아갑니다.
없다면 4단계로 갑니다.
생성된 좌표에
SetPawn이 성공하는지 확인합니다.성공했다면 다음 폰으로 이동합니다.
실패했다면 오류가 생성됩니다.
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
using { /UnrealEngine.com/Temporary/Diagnostics }
using { /UnrealEngine.com/Temporary/SpatialMath }
using { /Verse.org/Assets }
using { DataTypes }
using { UtilityFunctions }
board<public> := class(creative_device):
이 함수는 다음 조건이 충족될 때만 성공합니다.
지정된 폰 개수에 대해 보드 공간이 충분합니다.
각 폰이 아직 폰이 없는 좌표에 성공적으로 배치되었습니다.
런타임 시 보드 생성하기
런타임 시 보드를 생성하려면, 남은 작업은 보드 OnBegin 함수를 오버라이드하고 PlacePawns를 호출하는 것뿐입니다.
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
using { /UnrealEngine.com/Temporary/Diagnostics }
using { /UnrealEngine.com/Temporary/SpatialMath }
using { /Verse.org/Assets }
using { DataTypes }
using { UtilityFunctions }
board<public> := class(creative_device):
요약
요약해 보면, 이 페이지에서는 다음 단계를 알아보았습니다.
보드 위에 모든 폰을 랜덤 배치합니다.
Files
using { /Verse.org/Simulation }
using { /Verse.org/Random }
DataTypes<public> := module:
tile_coordinate<public> := class<concrete>:
@editable
Left<public>:int = 0
@editable
Forward<public>:int = 0
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
using { /UnrealEngine.com/Temporary/Diagnostics }
using { /UnrealEngine.com/Temporary/SpatialMath }
using { /Verse.org/Assets }
using { DataTypes }
using { UtilityFunctions }
board<public> := class(creative_device):