각 행에 점프해 착지할 수 있는 플랫폼은 몇 개만 있는 독특한 플랫폼 그리드 시퀀스를 생성하는 방식은 플랫폼 게임 모드에서 흔히 접할 수 있습니다. 이 모드에서 플레이어는 속도를 줄이고 시퀀스를 파악해야 합니다.
이 튜토리얼에서는 각 행의 플랫폼을 랜덤으로 선택하여 콜리전과 라이트 컬러를 지정하고 나머지 플랫폼은 이를 지정하지 않은 플랫폼 그리드를 생성하는 방법을 알아봅니다.
플랫폼 프리팹 생성하기
다음 단계를 따라 Verse에서 생성할 플랫폼 프리팹을 만듭니다.
새로운 엔티티를 배치하고 이를 choose_one_platform_prefab으로 명명된 프리팹으로 승격합니다. 방법에 관한 지침은 프리팹 및 프리팹 인스턴스를 참고하세요.
프리팹 에디터에서 엔티티에 다음 컴포넌트를 추가합니다.
transform_component: 플랫폼 위치를 지정할 트랜스폼 컴포넌트입니다.
mesh_component: 플랫폼의 스태틱 메시를 설정하는 메시 컴포넌트입니다. 이 예시에서는 팹 마켓플레이스에 있는 Stylized Egyptian World Pack 에셋의 SM_block_02 메시를 사용합니다.
collision_component: 플랫폼에서 콜리전을 사용 및 사용 안 함으로 설정하기 위한 콜리전 컴포넌트입니다.
parent_constraint_component: Verse를 사용하여 월드에서 이 프리팹을 생성할 때, 부모 엔티티를 기준으로 하는 트랜스폼을 간편하게 설정하기 위한 부모 컨스트레인트 컴포넌트입니다.
자손 엔티티를 추가한 다음 Light로 명명합니다.
다음 컴포넌트를 자손 엔티티 Light에 추가합니다.
transform_component: 엔티티를 플랫폼 위에 배치하는 트랜스폼 컴포넌트입니다.
point_light_component: 광원을 추가할 포인트 라이트 컴포넌트로, 플랫폼에 콜리전이 있는지에 따라 색상을 변경합니다.
parent_constraint_component: 부모 엔티티를 기준으로 이 엔티티의 트랜스폼을 제한하는 부모 컨스트레인트 컴포넌트입니다.
프리팹을 저장합니다.
이제 프리팹이 Assets.digest.verse 파일에 프리팹과 동일한 이름인 choose_one_platform_prefab의 클래스로 나타납니다.
플랫폼 그리드 생성하기
다음 단계를 따라 플랫폼 프리팹으로 구성된 그리드를 생성합니다.
choose_one_component로 명명한 Verse 컴포넌트를 생성합니다. Verse 컴포넌트 생성하기 단계는 Verse를 사용하여 자신만의 컴포넌트 만들기를 참고하세요.
편집 가능한 다음 프로퍼티를 추가합니다.
그리드의 플랫폼 수를 정의할 수 있도록
GridSize로 명명된 인티저 2D 벡터vector2i필드를 추가합니다. X는 그리드의 행 개수이고, Y는 열 개수입니다.플랫폼 간의 간격을 지정할 수 있도록
PlatformSpacing으로 명명된 부동 소수점 2D 벡터vector2필드를 추가합니다.~~~(verse) GridSizeTip<localizes>:message = "그리드 크기입니다. 여기에서 X 단위는 그리드의 너비, Y 단위는 깊이입니다." PlatformSpacingTip<localizes>:message = "그리드에서 각 플랫폼 간 거리입니다."
choose_one_component<public> := class(component):
# 그리드 크기입니다. 여기에서 X 단위는 그리드의 너비, Y 단위는 깊이입니다. @editable_vector_number(int): ToolTip := GridSizeTip MinComponentValue := option{0} GridSize:vector2i = vector2i{X := 3, Y := 10}
# 그리드에서 각 플랫폼 간 거리입니다. @editable_vector_number(float): ToolTip := PlatformSpacingTip MinComponentValue := option{0.0} PlatformSpacing:vector2 = vector2{X := 256.0, Y := 256.0} ~~~
OnSimulate함수는GridSize벡터에서 반복작업을 수행하여 생성할 플랫폼 수를 파악합니다. 루프에서 프리팹 클래스의 인스턴스를 만들고 이를 Verse 컴포넌트가 어태치된 엔티티에 추가하여 월드의 프리팹을 생성합니다.~~~(verse) GridSizeTip<localizes>:message = "그리드 크기입니다. 여기에서 X 단위는 그리드의 너비, Y 단위는 깊이입니다." PlatformSpacingTip<localizes>:message = "그리드에서 각 플랫폼 간 거리입니다."
choose_one_component<public> := class(component):
# 그리드 크기입니다. 여기에서 X 단위는 그리드의 너비, Y 단위는 깊이입니다. @editable_vector_number(int): ToolTip := GridSizeTip MinComponentValue := option{0} GridSize:vector2i = vector2i{X := 3, Y := 10}
# 그리드에서 각 플랫폼 간 거리입니다. @editable_vector_number(float): ToolTip := PlatformSpacingTip MinComponentValue := option{0.0} PlatformSpacing:vector2 = vector2{X := 256.0, Y := 256.0}
OnSimulate<override>()<suspends>:void= # 플랫폼을 생성하여 그리드를 만듭니다. for (Column := 0..GridSize.Y - 1): for (Row := 0..GridSize.X - 1): # 프리팹의 인스턴스를 만들어 기존 엔티티에 추가하면 월드에 프리팹이 생성됩니다. ChooseOnePlatform := choose_one_platform_prefab{} Entity.AddEntities(array{ChooseOnePlatform}) ~~~
이제 코드를 실행해 보면 동일한 위치에서 모든 플랫폼이 생성됩니다. 프리팹에는 트랜스폼 컴포넌트와 부모 컨스트레인트 컴포넌트가 있으므로, 트랜스폼 컴포넌트에서 InitialRelativeTransform 프로퍼티를 설정하여 프리팹을 추가하려는 엔티티 위치를 기준으로 오프셋을 지정해 프리팹을 생성할 수 있습니다. 생성하는 엔티티에 부모 컨스트레인트 컴포넌트가 없으면, 월드 스페이스에서 (루트 엔티티를 기준으로 하지 않고) 위치를 지정해야 합니다.
VerseGridSizeTip<localizes>:message = "Size of the grid, where the grid is X units wide by Y units deep." PlatformSpacingTip<localizes>:message = "The distance between each platform on the grid." choose_one_component<public> := class(component): # Size of the grid, where the grid is X units wide by Y units deep. @editable_vector_number(int): ToolTip := GridSizeTip MinComponentValue := option{0} GridSize:vector2i = vector2i{X := 3, Y := 10}저장하고 코드를 컴파일합니다.
이 Verse 컴포넌트를 엔티티에 어태치하고 세션을 시작하면 플랫폼 그리드가 해당 엔티티의 위치에 나타납니다.
랜덤으로 유효 플랫폼 선택하기
이제 월드에 플랫폼 그리드가 생성되었으므로 플랫폼에 더 많은 기능을 추가할 수 있습니다. 아래 단계에서는 플레이어가 점프해 다닐 수 있는 독특하면서도 변화하는 플랫폼 시퀀스를 생성할 있도록, 콜리전을 지정할 플랫폼을 랜덤으로 선택하는 방법을 알아봅니다.
다음 단계를 따라 그리드에서 유효 플랫폼을 랜덤으로 선택합니다.
편집 가능한 다음 프로퍼티를 Verse 컴포넌트에 추가합니다.
콜리전이 있는 플랫폼의 최소 개수를 지정할 수 있도록
MinCorrectPlatformsPerRow로 명명된 인티저 변수를 추가합니다.콜리전이 있는 플랫폼의 최대 개수를 지정할 수 있도록
MaxCorrectPlatformsPerRow로 명명된 인티저 변수를 추가합니다.콜리전이 사용 설정된 경우 플랫폼 색상을 설정할 수 있도록
ChosenColor로 명명된 색상 변수를 추가합니다.콜리전이 사용 설정되지 않은 경우 플랫폼 색상을 설정할 수 있도록
NotChosenColor로 명명된 색상 변수를 추가합니다.Verseusing { /UnrealEngine.com/Temporary/SceneGraph } using { /UnrealEngine.com/Temporary/SpatialMath } using { /Verse.org } using { /Verse.org/Colors } using { /Verse.org/Native } using { /Verse.org/Random } using { /Verse.org/Simulation } GridSizeTip<localizes>:message = "Size of the grid, where the grid is X units wide by Y units deep." PlatformSpacingTip<localizes>:message = "The distance between each platform on the grid."
for표현식의 결과로 각 반복작업의 값을 담고 있는 배열이 반환됩니다. 한 행에서 생성된 모든 플랫폼을 배열에 저장하고, 플랫폼을 랜덤으로 설정하기 위한 함수에 이 배열을 전달합니다. 이 함수를RandomizeCollidablePlatformsPerRow()로 명명합니다.VerseOnSimulate<override>()<suspends>:void= # For each row, spawn multiple platforms and pick a number of them to have collision while the others don't. # The platforms with collision will have the Chosen color for their light component. # The platforms without collision will have the NotChosen color for their light component. for (Row := 0..GridSize.Y - 1): EntitiesInRow := for (Column := 0..GridSize.X - 1): # The prefab has a parent constraint component so set the InitialRelative Transform # on the transform component to offset each platform relative to this entity. # This means the platform prefabs will spawn same distance from each other # but moving the root entity will change where the platforms originate.RandomizeCollidablePlatformsPerRow로 명명된 함수를 생성하여 콜리전을 지정할 엔티티를 랜덤으로 선택하고, 모든 엔티티에서 콜리전을 비활성화로 설정합니다. 포인트 라이트 컴포넌트는 프리팹의 자손 엔티티에 있으므로,FindComponents를 사용하여 엔티티의 자손에서 포인트 라이트를 검색하여 색상을 변경할 수 있습니다.Verse# Randomly choose platforms to have collision in the row. RandomizeCollidablePlatformsPerRow(Entities:[]entity):void= # Disable all the entities before choosing which ones to enable. # It disables an entity by disabling the collision on the entity, # and finding a point light in its child entities to change its color. for: EntityPlatform : Entities Collision := EntityPlatform.GetComponents(collision_component)[0] Light := EntityPlatform.FindComponents(point_light_component)[0] do:ChooseOne으로 명명된 배열을 위한 익스텐션 메서드를 생성하여 해당 배열에서 랜덤 엘리먼트를 선택합니다. 선택한 엘리먼트와 선택하지 않은 다른 모든 엘리먼트가 있는 배열이 모두 포함된 튜플이 결과로 반환됩니다.Verse# An extension method for an array to get a randomly selected element from the array. (Input:[]t where t:subtype(comparable)).ChooseOne()<decides><transacts>:tuple(t, []t)= ChosenElement := Input[GetRandomInt(0, Input.Length - 1)] NotChosenElements := Input.RemoveFirstElement[ChosenElement] (ChosenElement, NotChosenElements)RandomizeCollidablePlatformsPerRow에서ChooseOne을 호출하여 콜리전을 지정할 엔티티를 선택하고 색상을 변경합니다.Verse# Randomly choose platforms to have collision in the row. RandomizeCollidablePlatformsPerRow(Entities:[]entity):void= # Disable all the entities before choosing which ones to enable. # It disables an entity by disabling the collision on the entity, # and finding a point light in its child entities to change its color. for: EntityPlatform : Entities Collision := EntityPlatform.GetComponents(collision_component)[0] Light := EntityPlatform.FindComponents(point_light_component)[0] do:RandomizeCollidablePlatformsPerRow를 업데이트하여 편집 가능한 프로퍼티에 따라 콜리전을 지정할 엔티티를 여러 개 선택합니다. 먼저 행별 올바른 플랫폼 개수 최솟값과 최댓값 사이에서 랜덤 값을 지정하고, 그만큼 엔티티를 선택합니다. 이후 다음 선택 후보 목록에서 이미 선택한 엔티티를 제거합니다.Verse# Randomly choose platforms to have collision in the row. RandomizeCollidablePlatformsPerRow(Entities:[]entity):void= # Disable all the entities before choosing which ones to enable. # It disables an entity by disabling the collision on the entity, # and finding a point light in its child entities to change its color. for: EntityPlatform : Entities Collision := EntityPlatform.GetComponents(collision_component)[0] Light := EntityPlatform.FindComponents(point_light_component)[0] do:저장하고 코드를 컴파일합니다.
이제 세션을 시작하면, 콜리전과 선택한 색상이 지정된 독특한 플랫폼 시퀀스를 갖춘 플랫폼 그리드가 월드에 생성됩니다.
전체 스크립트
using { /UnrealEngine.com/Temporary/SceneGraph }
using { /UnrealEngine.com/Temporary/SpatialMath }
using { /Verse.org }
using { /Verse.org/Colors }
using { /Verse.org/Native }
using { /Verse.org/Random }
using { /Verse.org/Simulation }
GridSizeTip<localizes>:message = "Size of the grid, where the grid is X units wide by Y units deep."
PlatformSpacingTip<localizes>:message = "The distance between each platform on the grid."