워크샵으로 기존에는 상상조차 불가능했던 게임을 창조해보세요! 워크샵 내에서는 이미 알고계시는 오버워치의 기존 게임 모드는 물론, 스크립트를 통해 규칙을 추가하고 고유한 플레이 조건을 연출해 볼 수도 있습니다. 여러분이 설정한 규칙으로 영웅의 움직임과 능력을 변경하고, 플레이어의 피해 또는 치유 방식을 바꿔보고, 특정 상황에서 텍스트를 표시하게 할 수도 있습니다.
초고열 불장판이라는 멋진 게임 모드도 만들어볼 수 있습니다. 여기에서는 영웅이 지면에 서 있으면 불에 타오르게 됩니다.
Rule과 Event를 추가하고 나면 Condition을 하나 이상 추가할 수 있는 옵션이 있습니다. Condition은 Rule에 의해 Action 목록을 실행하기 전 모두 True이어야 하는 조건 목록입니다. Condition이 "Ongoing - Global" 또는 "Ongoing - Each Player" Event 종류를 가진 Rule에 종속된 경우 지속적으로 True인지 확인을 거치게 됩니다. 그 이외 다른 종류의 Rule에 종속된 경우 Event가 발생할 때마다 확인하게 됩니다. 각 Condition은 두 개의 값(Value)으로 구성되며, 연산자를 사용하여 결과값이 True인지 아닌지 비교 확인 연산에 사용됩니다. 세부 정보는 Values에서 확인 가능합니다.
Condition 추가하는 법:
Condition 옆에 있는 추가를 클릭합니다.
항목 값을 채웁니다.
참고: 값 자체가 입력 정보 (Input)를 가지고 있는 경우 (예를 들어 영웅을 얻기 위해 플레이어를 알아야 하는 "Hero Of"), 해당 값의 Input은 그 아래에 따로 표시됩니다.
Action은 게임을 변경하는 인자로, 상위에서 하위로 실행됩니다. Action 목록의 실행은 다음과 같은 경우 시작됩니다.
Rule과 관련된 Event 발생
Rule의 모든 Condition이 True (또는 Condition 존재 안 함)
Event 종류가 "Ongoing - Global" 또는 "Ongoing - Each Player,"인 경우, 각 Condition을 처음 만족할 때 Action 목록이 실행됩니다. Condition 목록을 만족하지 못했다가 만족하는 경우, Action을 다시 실행하려 할 것입니다.
Wait Action(세부 정보는 Wait Action 참조)을 제외한 모든 Action은 즉시 실행 및 종료됩니다. 각 Action은 0 이상의 Input으로 이루어지며, 해당 내용으로 게임을 변화시키게 됩니다. 각 Input은 하나의 값 (Value)을 가지는데, 이는 정보를 얻기 위한 정보 또는 지침입니다. 세부 정보는 Values에서 확인 가능합니다.
Action 추가하는 법:
Action 옆에 있는 추가를 클릭합니다.
게임을 변화시킬 Action을 선택합니다.
새로 나타나는 Input마다 드롭다운 메뉴에서 값을 하나 선택합니다.
참고: 일부 Action은 오브젝트 또는 Behavior를 생성할 수 있습니다. 그러한 Action의 경우 "Reevaluation"이라는 Input을 가지고 있을 수 있습니다. 이 Input은 이 Action의 다른 Input이 fixed(오브젝트나 Behavior를 변경 안 함)인지 dynamic(Input 변경에 지정된 값대로 오브젝트 또는 Behavior 변경)인지를 결정합니다.
Modify the Global Variable(T, Add, 5): 전역 변수 (Global Variable) T를 5만큼 증가시킵니다
Set Invisible(Event Player, Enemies): 이 Rule을 실행시킨 플레이어가 적에게 보이지 않도록 합니다
Reevaluation Input이 있는 Action
Create Icon(All Players(All Teams), Global Variable(P), Alert, Position): Global Variable "P"가 지정한 위치에 있는 모든 이들이 식별 가능한 경고 아이콘을 생성합니다. 해당 위치 (Position)는 지속적으로 재연산 되므로 나중에 Global Variable "P"가 변경되면 아이콘 위치도 새로운 위치로 변경됩니다.
Create Icon(All Players(All Teams), Global Variable(P), Alert, None): Global Variable P가 지정한 위치에 있는 모든 이들이 식별 가능한 경고 아이콘을 생성합니다. 아무것도 재연산하지 않으므로 나중에 Global Variable P가 변경되어도 이 아이콘의 위치를 업데이트하지 않습니다.
값(Value)은 정보이거나 정보를 얻을 수 있는 지침으로, Condition, Action, 또는 다른 값의 Input으로 제공됩니다. 여러 값이 결합할 수도 있습니다.
무궁무진하게 많은 값이 있으므로 여기에서 모두 정의하지는 않겠지만, 워크샵 에디터에서 보실 수 있습니다. 여기 그 일부를 소개합니다.
Value설명
Number
Input에서 정의한 범위의 실수를 제공합니다
Vector
Input에서 정의한 범위의 3차원 값을 제공합니다. 위치 및 방향으로 쓰입니다
Team
특정 팀을 뜻합니다. (1팀, 2팀, 전체 팀)
Hero
특정 영웅을 뜻합니다
Null
플레이어 또는 개체가 없음을 뜻합니다
True
참 (True) 값을 제공합니다
False
거짓 (False) 값을 제공합니다
Compare
비교 결과에 따라 True 또는 False를 제공합니다
Event Player
해당 Rule의 인스턴스를 실행 중인 플레이어를 제공합니다. 그러한 플레이어가 없는 경우 Null을 제공합니다
Attacker
해당 Rule의 인스턴스의 공격자를 제공합니다. 공격자가 없는 경우 Null을 제공합니다
Victim
해당 Rule의 인스턴스의 피해자를 제공합니다. 피해자가 없는 경우 Null을 제공합니다
Current Array Element
If True For Any, If True For All, Filtered Array, 또는 Sorted Array Value와 함께 쓰이는 현재 값을 제공합니다
하나의 값은 여러 값의 집합체인 배열 (Array)에 저장될 수 있습니다.
일련의 Action 및 값으로 Array를 생성하거나 변경할 수 있습니다.
예를 들어 "All Players" 값으로는 게임 내 모든 플레이어가 담긴 Array 하나를 얻을 수 있습니다.
"Modify Global Variable" Action 또는 "Modify Player Variable" Action의 "Append To Array" 기능으로 자신만의 Array를 구성해볼 수도 있습니다.
Input은 Array를 요구하지만 다른 형태의 값을 받는 경우, 해당 값은 편의상 하나의 요소로 구성된 Array에 복사됩니다. 마찬가지로 Input은 다른 형태의 값을 요구하지만 Array를 받는 경우, 해당 Array의 첫 값(또는 Array가 비어있는 경우 0)이 사용됩니다.
변수(Variable)는 값을 저장하여 나중에 회수할 수 있는 공간입니다. 변수에는 String 외의 어떤 값도 저장할 수 있습니다. 모든 변수는 0이라는 숫자(Number)값으로 시작합니다.
스크립트에서는 두 가지 종류의 변수가 있습니다.
전역변수 (Global Variable): A부터 Z까지로 이름 지어진 26개의 Global Variable이 있으며, 각 변수는 각각 값 또는Array를 가지고 있습니다.
플레이어변수 (Player Variable): 각 플레이어는 A부터 Z까지로 이름 지어진 26개의 변수를 가지고 있으며, 각 변수는 각각 값 또는 Array를 가지고 있습니다.
변수 내에서 세 가지 연산이 가능합니다.
Setting: "Set Global Variable"과 "Set Player Variable"을 통해 변수가 가지고 있던 값을 새로운 값으로 설정합니다.
Modifying: "Modify Global Variable"과 "Modify Player Variable"은 특정 사칙연산 (Add, Multiply 등) 또는 Array 연산(Append, Remove)을 통해 변수 내 값을 변경합니다.
Chasing: "Chase Global Variable Over Time", "Chase Player Variable Over Time", "Chase Global Variable at Rate", "Chase Player Variable at Rate"을 통해 변수를 시간이 지남에 따라 조금씩 바꾸거나 특정 비율로 변경할 수 있습니다.
Chase의 목표치는 숫자 또는 Vector 값(또는 숫자나 Vector가 도출되는 값)일 수 있습니다.
목표치가 숫자라면 변수값은 Chase 시작 전에 숫자가 되어야 Chase가 정상 작동합니다.
목표치가 Vector라면 변수값은 Chase 시작 전에 Vector가 되어야 Chase가 정상 작동합니다.
목표치 Reevaluation을 사용하는 경우, Chase는 목표치에 도달한 적이 있더라도 필요 시 업데이트를 통해 변경된 목표치를 따라가게 됩니다. Reevaluation에 대한 세부 정보는 Action 추가에서 확인해주세요.
"Stop Chasing Global Variable" Action과 "Stop Chasing Player Variable" Action으로 Chase를 취소할 수 있습니다.
Chase가 취소되면 변수는 Chase 시작 전의 원래값과 목표치 사이의 현재값을 지니게 됩니다.
미러전 데스매치는 좀더 심화된 게임 모드입니다. 이 모드에서는 전원이 동일한 영웅을 플레이하는 짧은 라운드가 여러 차례 진행됩니다. 각 라운드가 종료되면 각 플레이어는 일정 목록 내 무작위 선택된 다음 영웅으로 원위치에서 부활합니다. 마지막 라운드가 종료되면 처치 수가 가장 많은 플레이어가 승리합니다.
예를 들어 한 경기에서 모두들 맥크리로 시작했다가 다음 라운드에서 파라로 바꿔 플레이하게 됩니다. 다른 경기에서는 위도우메이커로 시작했다가 다음 라운드에서 애쉬로 바꿔 플레이하게 됩니다. 생성된 목록대로 플레이하기 때문에 영웅을 동일한 순서로 플레이하게 될 가능성은 희박합니다!
자, 그럼 미러전 데스매치의 스크립트를 준비해 보죠!
플레이 > 게임 탐색기 > 만들기 > 설정 > 워크샵을 클릭합니다.
우선 플레이 예정인 영웅 목록을 만드는 Rule을 생성해보겠습니다.
목록은 Array로 Global Variable "L"에 저장됩니다.
Array는 플레이어 목록, 영웅 목록, 숫자 목록, 하나의 값, 또는 아무 값이 아닐 수도 있는("비어 있는" Array) 등 뭐든 될 수 있습니다.
Array에 저장된 각각의 값은 0에서부터 오름차순의 고유 인덱스로 저장됩니다. 하나의 인덱스와 그 값은 요소라고 지칭되기도 합니다.
Array의 순서는 중요합니다. [Reaper, Winston, Mercy]는 [Mercy, Winston, Reaper]와 서로 다른 Array입니다.
Array에는 서로 다른 종류의 값이 있을 수 있습니다. 예를 들어 ]123, Reaper, True, -4.5]라는 Array도 가능합니다.
Input이 기다리던 Array 형태가 아닌 단일 값 (single Value)이 제공되는 경우, 해당 Input은 이 단일 값을 요소 하나를 가진 Array로 받아들이게 됩니다.
Input이 기다리던 단일 값이 아닌 Array를 받는 경우, 해당 Input은 Array의 첫 값(또는 Array가 비어있는 경우 0)을 받아들이게 됩니다.
Rule을 추가하고 설명을 넣어서 이 Rule이 무슨 기능인지 알 수 있도록 합니다.
Event 종류를 Ongoing - Global로 설정합니다. 이 Rule의 인스턴스 하나만 실행한다는 의미입니다.
이 Rule은 Condition이 없으므로 게임이 시작하자마자 실행될 것입니다.
다음과 같이 Action 추가
Action: Set Global Variable
Variable: L
Value: Hero
Hero: 플레이 가능하도록 하고 싶은 영웅입니다.
이렇게 하면 영웅 Array가 생성됩니다. "Set Global Variable" Action을 통해 "L"을 목록의 첫 영웅으로 설정합니다.
게임에서 오직 하나의 영웅만 가능한 경우 지루할 수 있으니 더 추가해 보겠습니다! 다음과 같이 Action을 원하는 만큼 추가합니다.
Action: Modify Global Variable
Variable: L
Operation: Append
Value: Hero
Hero: 플레이 가능하도록 하고 싶은 영웅입니다.
이렇게 "L"에 만들었던 영웅 Array에 영웅을 추가합니다. 첫 Action이 "Set Global Variable" 대신 "Modify Global Variable"로 시작했다면, Array는 0부터 시작할 것입니다. 모든 변수는 기본값이 0이므로 설정을 변경하지 않으면 [0, Pharah, Hanzo, Ana,...]와 같은 Array를 얻게 됩니다.
이 Rule의 마지막 Action을 추가해 보겠습니다. 이 Rule은 Global Variable L(영웅 Array)의 무작위 복사본을 이용하여 0번 위치에서 시작하는 무작위 Array의 일부를 복사해 해당 게임 모드에 필요한 수의 영웅을 추가합니다. 이 복사본은 다시 Global Variable L로 저장됩니다. 여러분이 제공한 원본 영웅 목록이 무작위로 뒤섞인 부분 집합이 된 것입니다.
예) 초기 영웅 목록이 [Ashe, Doomfist, Hanzo, McCree, Pharah, Soldier: 76, Zenyatta, Widowmaker, Ana]였다면, 무작위화 된 Array는 [Hanzo, Pharah, Widowmaker, Ana, Ashe, Doomfist, Soldier: 76, Zenyatta, McCree]가 되며, 그 일부는 [Hanzo, Pharah, Widowmaker, Ana, Ashe, Doomfist]가 됩니다.
다음 Rule은 무슨 일이 있더라도 모든 플레이어가 언제든 동일한 영웅을 플레이하도록 보장합니다.
Rule을 추가하고 설명을 넣어서 이 Rule이 무슨 기능인지 알 수 있도록 합니다.
Event 종류를 Ongoing - Each Player로 설정합니다. 각 플레이어는 각자의 Rule 인스턴스를 실행한다는 뜻입니다.
두 개의 Condition을 추가합니다. 전부 True인 경우 다음과 같이 영웅을 강제합니다.
라운드 수인 Global Variable "R"이 영웅 목록에 있는 영웅의 총 수보다 작아야 합니다. 그렇지 않으면 게임이 종료되고 더 이상 영웅을 지정할 수 없기 때문입니다. 라운드 수는 0에서 시작해 증가하니 6 라운드로 진행한다면 마지막 라운드는 5입니다. 모든 변수는 기본값이 0이니 Global Variable "R"은 0으로 설정하지 않아도 됩니다.
Value: Global Variable
Variable: R
연산자: <
Value: Count Of
Array: Global Variable
Variable: L
이를 통해 특정 플레이어가 현재 플레이하는 영웅이 해당 라운드에 지정된 영웅과 다른지를 확인합니다. "특정 Player"는 현재 Rule 인스턴스를 실행한 플레이어라는 뜻의 특별 값인 Event Player로 사용합니다. 해당 라운드에 "지정된 영웅"은 영웅 목록(Global Variable "L")의 관련 인덱스에 대응하는 영웅입니다. 현재 라운드는 Global Variable "R"에 저장되어 있으므로 지정된 영웅은 "Value In Array"를 사용해 얻을 수 있습니다.
Value: Hero Of
Player: Event Player
연산자: !=
Value: Value in Array
Array: Global Variable
Variable: L
Index: Global Variable
Variable: R
플레이어가 영웅을 변경해야 하므로 다음과 같은 작업을 수행하는 Action 두 개를 추가합니다.
첫 Action은 Event Player에게 지정된 영웅을 배정합니다. 이 Action의 첫 Input은 영웅을 배정받는 플레이어입니다. 두 번째 Input은 영웅이므로 영웅을 지정합니다.
Action: Start Forcing Player To Be Hero
Player: Event Player
Hero: Value In Array
Array: Global Variable
Variable: L
Index: Global Variable
Variable: R
두 번째 Action은 목록 상의 다음 영웅을 미리 불러와서 플레이어가 영웅 교체 시 오래 대기하지 않도록 합니다. 각 플레이어는 전원이 동일한 영웅을 플레이한다고 해도 영웅을 개별적으로 미리 불러오는데, 이는 각 플레이어가 해당 영웅의 다른 스킨을 미리 불러와야 하는 경우가 있기 때문입니다. 값 추가로 Global Variable "R"에 1을 더하면 Action이 현재 영웅 대신 다음 영웅을 미리 불러옵니다. 그런데 이렇게 되면 마지막 라운드에서는 Array Global Variable "L"이 허용하는 범위 밖의 Array 인덱스가 사용됩니다. Array에서 허용하는 범위 밖의 값은 0으로 간주되므로 문제는 없습니다. 영웅을 기다리고 있는 Action이 0을 받게 되면 아무것도 하지 않기 때문입니다.
게임이 진행 중이어야 합니다. 좀 더 구체적으로 설명하자면 영웅 선택 화면과 준비 시간은 이미 지났지만, 게임이 종료되지는 않은 단계라는 뜻입니다.
Value: Is Game In Progress
연산자: ==
Value: True
Global Variable I은 False이어야 합니다. 이 변수는 현재 라운드가 시작되었는지 여부를 알기 위해 사용합니다. Global Variable I가 설정되지 않았으면 False에 준하는 0 값을 가지고 있을 것입니다.
Value: Global Variable
Variable: I
연산자: ==
Value: False
라운드 수인 Global Variable "R"은 영웅 목록에 있는 총 영웅 수보다 적어야 합니다.
Value: Global Variable
Variable: R
연산자: <
Value: Count Of
Array: Global Variable
Variable: L
Condition이 전부 True이면 라운드를 시작해야 합니다. Action 몇 개를 추가해서 이러한 작업을 수행합니다.
첫 Action은 경기가 일반적인 기준으로 종료되어서는 안 된다고 코어 게임 모드에게 알려주어야 합니다. 데스매치의 경우, 시간이 다 되었거나 누군가 제한 점수에 도달했다고 해서 경기가 종료되지 않는다는 의미입니다. 이 Action이 실행되면 스크립트가 게임 모드 종료 체계를 다시 활성화하거나 승자가 정해지지 않는 한 경기가 종료되지 않습니다.
Action: Disable Built-in Game Mode Completion
다음 Action으로 게임 모드의 현재 타이머를 라운드 길이만큼으로 설정합니다.
Action: Set Match Time
Time: Number
Number: 60.00
이 Action은 Global Variable "I"를 True로 설정하여 Global Variable "I"가 다시 False로 설정되지 않는 한 시작되지 않도록 합니다.
하나의 Condition을 추가합니다. Global Variable "R"이 Global Variable "L"에 있는 요소의 수와 같은지를 확인하기 위함입니다. 만약 같다면 영웅 목록에 있는 각 영웅으로 라운드를 진행했다는 뜻입니다. 이 경우 경기는 종료되어야 합니다.
Value: Global Variable
Variable: R
연산자: ==
Value: Count Of
Array: Global Variable
Variable: L
Condition이 True면 이 Action은 게임 모드 종료 체계를 다시 활성화할 것입니다. 타이머가 0일 것이므로 게임 모드는 즉시 경기를 종료하고 일반적인 경기 종료 과정이 시작될 것입니다.
단축키를 지정하시면 워크샵 인스펙터 사용이 훨씬 수월해집니다. Esc > 설정 > 조작법을 클릭하시고 ‘워크샵 인스펙터 열기’까지 스크롤을 아래로 내린 후 단축키를 지정하세요.
워크샵 인스펙터는 발생한 일은 물론, 발생하지 않은 일(및 그 이유)까지 알려드립니다!
간편 설정 게임이 있다는 것도 잊지 마세요! 손수 새로운 해결책을 강구할 필요 없이 이미 제공된 설정을 사용할 수도 있습니다.
Event가 제대로 시작되지 않는다면 Event Player가 이미 Action 목록을 실행 중이기 때문일 수 있습니다. Rule의 Wait Action을 확인해보세요. 특히 Condition을 무시하는 설정이 되어있는지는 않은지 잘 살펴보세요.
전장에서 특정 위치를 선택하려면 "Vector" 값을 사용해야 하며, 카메라 아이콘을 클릭해야 합니다.
경기 내에서 플레이어가 영웅을 선택했는지 논리적 확인을 해야 할 때는 "Has Spawned" 값이 유용합니다.
게임 준비 및 영웅 선택 단계 이후 여러분의 Rule만 실행되었으면 하는 경우에는 "Is Game In Progress" 값을 사용하세요.
변수에 값을 배정하고 워크샵 인스펙터로 살펴보면 게임플레이 중 어떤 값이 되돌아오는지 아주 쉽게 살펴볼 수 있습니다.
"Last Created Entity" 값을 사용하면 마지막으로 생성한 효과 또는 아이콘을 Player Variable에 저장할 수 있습니다. 이를 통해 나중에 해당 개체를 참조하여 제거할 수 있습니다.
필터링된Array를 "All Players On Objective" 또는 "Players Within Radius"와 같은 값과 섞어 쓰면 특정 기준 (사망, 생존, 상태 효과 등)에 부합하는 플레이어를 쉽게 필터링할 수 있습니다.
여러 진행 경로로 Behavior를 설정할 필요가 있는 경우, "Skip If" Action을 사용하면 주어진 Condition이 True일 때 원하는 수만큼의 Action을 건너뛸 수 있습니다. 이 경우 양쪽 경로 모두에서 진행이 되는 것을 막기 위해, 건너뛴 Action에 "Abort" Action을 넣어주어야 할 수 있습니다.
알파벳 문자를 입력하여 드롭다운 목록에서 필터링할 수 있습니다.
매개 변수로 Array를 받지 못한 경우, Input을 단일크기의 Array에 넣을 것입니다.
그 반대도 마찬가지입니다. 값이 단일 데이터가 아닌 Array를 받은 경우, 해당 Array의 0 위치에 있는 요소를 사용할 것입니다.
스크립트를 여러 개의 Action과 Condition으로 나누어 구성하면 어디에서 문제가 발생했는지 더 쉽게 알 수 있습니다.
Action, Value, Input의 용도를 이해하기 어렵다면 PC에서는 마우스 오버해 보시거나, 콘솔에서는 " 상세 정보 보기"를 선택해 관련 정보를 확인해 보세요.
댓글