역자주) 비주얼 스크립트를 작업해보지 않은 분이 본 내용을 이해하기는 어렵다. 이런게 있나 보다하고 넘어가면 될 듯 하다. 그렇게 심각하게 어려운 사항도 아니고 하다보면 그냥 자기도 모르게 익혀혀서 사용하게 된다.
관계(Relations)는 유닛의 각 포트간의 의존성을 이해하는 데 유용한 도구다.예를 들어, Add 유닛을 사용하여 A + B의 결과를 얻으려면 A와 B의 값을 제공해야 한다.마찬가지로, 로그 유닛을 호출하기 전에 메시지 입력 포트에 대한 값을 제공하십시오.
비주얼 스크립팅은 예측 디버깅을 위해 이 정보를 백그라운드에서 사용한다.예를 들어 A에 대한 값을 제공하지 않고 A + B 값을 얻으려고 하면 실행 모드에서 실패가 될 것을 의미하는 주황색으로 노드가 표시한다.
이 경우 그래프 인스펙터(Inspector)에 표시된 경고 메시지를 통해 누락된 내용을 확일 할 수 있다.
또한 관계(Relations)는 필수적으로 포트의 연결이 필요한 경우와 선택적으로 연결이 필요한 포트를 이해하는 데에도 도움이 될 수 있다. 예를 들어 Get Child 유닛(퍼지 파인더에서 Codebase > Unity Engine > Transform)에서 변환 값 출력을 얻는 것이 목표라면 제어 포트를 연결할 필요가 없다.
사용된 유닛의 내부 연결성에 대해서는 도구 모음에서 Relations 토글 버튼을 활성화하면 된다.
그래프(Graph)에는 스크립트 그래프(Script Graph)와 상태 그래프(State Graph) 두 종류가 있다.스크립트 그래프는 판단(decisions)과 흐름(flow)으로 구성된 그래프이다.상태 그래프는 캐릭터의 달리기(running) 및 점프(jumping) 같이 사용자가 정의한 상태를 가지며, 각개의 상태 유닛(State Unit)은 스크립트 그래프를 가질 수 있다.
스크립트 머신 그래프를 만들기.
스크립트 머신(Script Machine)은 스크립트가 시각적으로 표현된 스크립트 그래프를 가지고 있는 유니티 컴포넌트(component)를 의미한다.
Embed(임배드): 이 그래프는 GameObject에 직접 포함되어 있으며, 에셋(여기서는 스크립트 그래프 파일)이 하드 디스크가 아닌 GameObject에 바로 저장되어 진다. 참고: 실행(Play) 모드(런타임)에서 스크립트 그래프를 변경하면 실행 모드가 종료된 후 모두 사라진다. 따라서 수정을 반영하고자 한다면 Play 모드를 종료하고 다시 수정해야 한다. (본 글의 6번으로 이동)
Graph(그래프): 일반적인 그래프이다. 스크립트 그래프 파일이 GameObject에 저장되지 않고 에셋 형태로 하드디스크에 새롭게 생성되어 저장된다. 참고: 그래프(Graph)를 사용하면 여러 오브젝트에서 공유 가능한 스크립트 파일을 만들 수 있으며, 실행(Play) 모드(런타임)에서 변경한 사항들이 사라지지도 않는다. 그래프는 프로토타입 제작에 이상적이다.
스크립트 파일이 그래프(Graph)인 경우:
새로운 스크립트 그래프는 새로운 스크립트 그래프 파일을 생성한다. 새로운 스크립트 그래프를 저장하고(다른이름으로저장선택) 파일을 저장할 폴더를 선택한다. Start Event 및 Update Event로 자동 채워지는 새 그래프를 보려면EditGraph를 클릭한다.다른 이벤트를 추가하려면 그래프 편집창에서 마우스 오른쪽 버튼으로 클릭하고이벤트 추가를 선택한다.
이미 만들어진 스크립트 그래프 파일이 있는 경우 해당 그래프를 드래그하여 Graph 파일 공간에 놓는다. Unity는 프로젝트에서 그래프를 로드하게 되고 이후 부터는 인스펙터(Inspector)에서 편집할 수 있다.
역자주) 스크립트 파일 생성 참고 영상
스크립트 그래프에 새로운 유닛을 추가하려면 퍼지 파인더(fuzzy finder)를 사용한다. 포트(port)에서 유닛으로 연결선을 끌면 퍼지 파인더는 가장 많이 사용되는 맥락적인 노드(소스 장치에 연결할 수 있는 노드)의 목록을 제공한다.특정 유닛을 찾으려면 퍼지 탐색기 필드에 단위 이름을 입력하한다.유닛을 포트 커넥터와 연결한다.
역자주) 본 내용은 메뉴얼 원본에 있어서 추가하긴 하였으나 사용할 일은 없어 보인다. 매우 전문적인 프로그래머가 어떤 필요에 의해 사용할 일이 있을 수 있지만 프로그래밍이 아닌 비주얼 스크립트 내부의 기능만으로도 상당부분 해결이 되는 문제라고 생각된다. 초보자라면 무시하고 넘어가도록 하자.
비주얼 스크립팅에서 프로그래밍을 한다는 것은 로직 블록을 연결하는 것을 의미한다.이 블록들을 유닛(Unit)이라고 부른다.
비주얼 스크립팅(Visual Scripting)은 게임(앱) 개발에 필요한 작업들을 처리하도록 세분화된 아주 다양한 형태의 유닛(Units)들을 가지고 있다.
Events:OnStart, OnUpdate, OnButton과 같은 작업을 실행하는 진입점.
Flow:실행이 다른 노드에 의해 트리거되어야(be triggered) 하는 장치(예: if 및 Position 설정)
Data:데이터를 갖는 유닛(예: float literal 및 integer literal).
단순한 사용자 정의 유닛 만들기
빈 유닛을 새로 만드는 방법:
1) 프로젝트에서 마우스 오른쪽 버튼을 클릭하고Create>C# Script를 선택하여 유닛의 이름입력하고 프로젝트에 새 C# 파일을 생성한다. 예를 들어, MyNode.cs.
2) 다음 코드를 스크립트에 복사, 붙여넣기 및 저장한다.
using Unity.VisualScripting;
publicclass MyNode : Unit { protected override void Definition() //The method to set what our node will be doing. { } }
3) 편집(Edit)>프로젝트 설정(Project Settings)을 선택하십시오. Project Settings 창이 나타난다.
4) 프로젝트 설정 창에서시각적 스크립팅(Visual Scripting)을 선택하고유닛 재생성(Regenerate)을 선택하여 퍼지 탐색기(Fuzzy Finder)에 새 노드를 추가한다. Project Settings 창이 나타난다.
5) 그래프에 새로운 유닛을 추가하려면 스크립트 그래프의 배경을 마우스 오른쪽 버튼으로 클릭한다.새로운 커스텀 유닛은 퍼지 탐색기(fuzzy finder) 끝에 있다.
퍼지 탐색기(fuzzy finder)에서 직접 만든 노드를 선택한다.My Node 유닛이 그래프에 표시된다.
참고: 비주얼 스크립팅은 사용자 지정 유닛을 자동으로 처리한다.노드 라이브러리의 목록에 C# 파일을 추가할 필요는 없다.
포트 추가 및 코드 실행하기
유닛을 생성할 때는 포트를 추가해야 한다.
사용자가 처리될 데이터를 추가할 수 있도록 하는 데이터 포트
현재의 노드가 작업이 완료된 후 사용자가 해당 노드나 다른 노드를 트리거할 수 있도록하는 제어 포트
유닛에 네 가지 다른 유형의 포트(입력되는 제어 포트와 데이터 포드, 출력되는 제어 포트와 데이터 포트)를 생성하면 된다.
노드 예:
포트(Ports):
ControlInput:유닛에서 로직을 실행하는 진입점.
ControlOutput: 현재 포트에 연결된 다음 작업을 트리거(다음 유닛으로 실행 흐름이 넘어감).
ValueInput: 유닛에 전달되는 모든 종류의 데이터.
ValueOutput: 유닛 외부에 전달할 모든 종류의 데이터(연결된 다음 유닛으로 데이터가 넘어감).
제어 포트 추가를 추가하는 방법
유닛에 제어 포트를 추가하려면:
1) ControlInput및ControlOutput에 원하는 포트 변수를 추가한다.
2) 정의방법(Definition Method)에 있는 포트 변수를 사용한다.
using Unity.VisualScripting;
publicclass MyNode : Unit { [DoNotSerialize] // No need to serialize ports. public ControlInput inputTrigger; //Adding the ControlInput port variable
[DoNotSerialize] // No need to serialize ports. public ControlOutput outputTrigger;//Adding the ControlOutput port variable.
protected override void Definition() { //Making the ControlInput port visible, setting its key and running the anonymous action method to pass the flow to the outputTrigger port. inputTrigger = ControlInput("inputTrigger", (flow) => { return outputTrigger; }); //Making the ControlOutput port visible and setting its key. outputTrigger = ControlOutput("outputTrigger"); } }
이제 다른 제어 포트에 연결할 수 있는 기본적이고 기능을 갖는 플로우 라우팅 유닛(Flow Routing Unit)이 있어야 한다. 플로우 라우팅 유닛(Flow Routing Unit)을 사용하여 그래프에서 흐름의 방향을 변경하여 비정형적이고 유지관리가 어려운 비주얼 소스 코드를 피할 수 있다.
값 포트 추가하는 방법
유닛에 값 포트를 추가하려면 노드에 입력(Input)할 데이터 유형을 정의해야 한다.두 가지 유형의 데이터가 있다.
Generic: Object Type(오브제트 타입)으로 코드 상에서 어떤 데이터라도 처리할 수 있도록 한다.
Type Value: String(문자열), Integer(정수) 및 float과 같은 특정 데이터 타입을 처리하는데 사용된다.
아래의 예시 코드는 문자열 타입의 입력 값 2개를 받을 수 있고, 문자열 타입의 출력 값 1개를 내보낼 수 있는 유닛이 생성된다.기본값(Default)을 추가할 수도 있다: 아래 예제에서는 myValueA의 기본 문자열 값으로 "Hello"가 설정되어 있다.
using Unity.VisualScripting;
publicclass MyNode : Unit { [DoNotSerialize] public ControlInput inputTrigger;
[DoNotSerialize] public ControlOutput outputTrigger;
[DoNotSerialize] // No need to serialize ports public ValueInput myValueA; // Adding the ValueInput variable for myValueA
[DoNotSerialize] // No need to serialize ports public ValueInput myValueB; // Adding the ValueInput variable for myValueB
[DoNotSerialize] // No need to serialize ports public ValueOutput result; // Adding the ValueOutput variable for result
private string resultValue; // Adding the string variable for the processed result value protected override void Definition() { inputTrigger = ControlInput("inputTrigger", (flow) => { return outputTrigger; }); outputTrigger = ControlOutput("outputTrigger");
//Making the myValueA input value port visible, setting the port label name to myValueA and setting its default value to Hello. myValueA = ValueInput<string>("myValueA", "Hello "); //Making the myValueB input value port visible, setting the port label name to myValueB and setting its default value to an empty string. myValueB = ValueInput<string>("myValueB", string.Empty); //Making the result output value port visible, setting the port label name to result and setting its default value to the resultValue variable. result = ValueOutput<string>("result", (flow) => { return resultValue; }); } }
위의 노드를 연결하려고 하면 흐름이 이 노드를 통과하지만resultValue변수의 값이 처리되도록 하는 지시가 없기 때문에 Result Value는 null이다. (다음 단락의 유닛 내부의 로직 실행하기를 참고하라)
유닛 내부의 로직 실행하기
새로 생성된 유닛이ControlInputnameinputTrigger가 트리거될 때 두 개의 문자열을 연결(Concatenate)하여 하나의 문자열로 출력하도록 할 것이다.이렇게 하려면ControlInput inputTrigger를 처리하는 람다 식(lambda expression) 내에 로직을 추가하면 된다.
publicclass MyNode : Unit { [DoNotSerialize] public ControlInput inputTrigger;
[DoNotSerialize] public ControlOutput outputTrigger;
[DoNotSerialize] public ValueInput myValueA;
[DoNotSerialize] public ValueInput myValueB;
[DoNotSerialize] public ValueOutput result;
private string resultValue; protected override void Definition() { //The lambda to execute our node action when the inputTrigger port is triggered. inputTrigger = ControlInput("inputTrigger", (flow) => { //Making the resultValue equal to the input value from myValueA concatenating it with myValueB. resultValue = flow.GetValue<string>(myValueA) + flow.GetValue<string>(myValueB) + "!!!"; return outputTrigger; }); outputTrigger = ControlOutput("outputTrigger");
Requirement(myValueA, inputTrigger); //To display that we need the myValueA value to be set to let the unit process Requirement(myValueB, inputTrigger); //To display that we need the myValueB value to be set to let the unit process Succession(inputTrigger, outputTrigger); //To display that the input trigger port input will exits at the output trigger port exit. Not setting your succession also grays out the connected nodes but the execution is still done. Assignment(inputTrigger,result);//To display the data that is written when the inputTrigger is triggered to the result string output. } }
참고: 관계 설정 전후
참고: 사용자 지정(custom) 노드의 최종 결과.
유닛에 설명(documentation) 추가하기
유닛에 설명을 추가하는 것은 반드시 필요한 사항은 아니지만 사용자가 유닛의 목적을 이해하는데 도움이 된다.
퍼지 파인더나 그래프 인스펙터에서 읽을 수 있는 포트에 대한 요약을 추가하려면 현재 유니티에 새로운 C# 스크립트 파일을 만들고Editor 폴더에 넣어야 한다. MyNodeDescriptor라는 새로운 C# 스크립트를 만들고 다음 코드를 복사하여 붙여 넣기 한다.
protected override void DefinedPort(IUnitPort port, UnitPortDescription description) { base.DefinedPort(port, description); switch (port.key) { case"inputTrigger": description.summary = "Trigger the concatenation of the myValueA with the myValueB and return the result string on the Result port."; break; case"myValueA": description.summary = "First string value for the returned result of myValueA + myValueB."; break; case"myValueB": description.summary = "Second string value for the returned result of myValueA + myValueB."; break; case"outputTrigger": description.summary = "Execute the next action after myValueA and myValueB concatenation."; break; case"result": description.summary = "The result string obtained from myValueA and myValueB concatenation."; break; } } }
그래프에서 유닛을 선택하면Graph Inspector의 유닛 포트에 대한 설명이 나타난다.
유닛 커스터마이징 하기
유닛 커스터마이제이션(customization, 사용자 지정)은 사용자가 그래프에서 무슨 일이 일어나고 있는지 이해하는 데 도움이 되도록 하는 것이다. 유닛을 사용자 정의하려면 유닛에 속성(attributes)을 설정해야 한다.다음은 유닛의 모양을 수정하는 데 사용하는 속성 목록이다.
유닛 클래스 속성들(unit class attributes)
속성(attributes)은 노드를 사용자 지정하는 데 사용되며 유닛 앞쪽에 놓여져야 한다.
참고: 이를 위해서는 퍼지 파인더를 업데이트해야한다. 파인더에서 노드의 위치가 변경 된다.
---
속성: [TypeIcon(Typeof(GameObject))]
설명: Visual Scripting 아이콘 라이브러리에서 아이콘을 가져오며, 이 아이콘은 unity 내부 라이브러리에 저장되어져 있다.
참고: 사용자가 이 아이콘을 변경할 수는 없다.
포트 속성(Ports Attributes)
포트 속성들은 유닛 클래스 내부의 ControlInput, ControlOutput, ValueInput 및 ValueOutput 변수를 초기화하는 위치보다 앞쪽에 놓여야 한다.
publicclass MyNode : Unit { [DoNotSerialize] // Mandatory attribute, to make sure we don’t serialize data that should never be. [PortLabelHidden] // Hiding the port label because we normally hide the label for default Input and Output triggers. public ControlInput inputTrigger;
속성: [DoNotSerialize]
설명: 모든 포트에 대한 필수 속성 포트.직렬화되지 않은 데이터가 직렬화되지 않도록 필요한 경우.
---
속성: [PortLabelHidden]
설명: 포트 아이콘 옆에 있는 텍스트 레이블 숨기기
참고:레이블이 숨겨져 있지 않으면 포트 변수가Definition: method의 키와 동일하게 만들어 진다.
스크립트 그래프(Script Graph)는 게임 플레이 로직을 구현한다.플로우 그래프에 유닛을 추가하는 방법에는 여러 가지가 있다.가장 일반적인 두 가지 방법은 다음 과정에 자세히 설명되어 있다.
참고: 새로운 스크립트 그래프를 만들면 "Start Event" 유닛과 "Update Event" 유닛이 스크립트 그래프에 자동으로 추가된다.스크립트 그래프를 초기화할 때 "Start" 유닛은 한 번만 실행된다. "Update" 유닛은 GameObject가 활성화되어 있는 한 계속 매 프레임마나다 실행된다.
그래프에 단위를 추가하려면 다음과 같이 하한다.
스크립트 그래프를 연다.
다음 중 하나를 수행한다.
그래프의 빈 공간을 마우스 오른쪽 버튼으로 클릭한다. 퍼지 탐색기(Fuzzy Finder)가 모든 유닛 카테고리와 함께 나타난다. 퍼지 검색기를 스크롤하거나 검색 필드에 이름을 입력하여 장치를 선택한다. 선택된 유닛이 그래프에 나타난다. 입출력 포트를 통해 장치를 다른 장치에 연결한다.
유닛에 있는 어느 하나의 트리거(Trigger) 또는 데이터 포트(삼각 화살표 아이콘은 트리거 포트이고 다른 둥근 아이콘은 데이터 포트)를 클릭하여 빈 곳에 끌어다 놓는다. 원 소스 유닛과 호환되는 모든 유닛의 목록이 나타난다. (퍼지 탐색기 필드에서 스크롤하거나 이름을 입력하여) 하나를 선택한다.선택한 유닛은 첫 번째 유닛에 연결된 그래프로 배치된다.
스크립트를 생성하기 위한 유닛과 포트간의 연결 링크(Connections Link)를 설명한다.
포트의 호환성(Compatible Ports)
연결 포트간에 연결이 가능한 경우에는 연결을 하려고 할 때 포트가 하이라이트가 된다. 반대로 연결이 불가한 경우 포트는 흐리게 표시된다. 만약 유닛에 호환 가능한 포트가 없는 경우에는 유닛 전체가 흐리게 표시된다. 즉, 대상 포트가 하이라이트되지 않는 다면 연결을 만들 수 없다.
예를 들어 어떤 숫자가 컴포넌트의 값으로 전환될 방법이 없는 경우 수의 연산 결과(숫자)를 타겟 유닛(컴포넌트)에 연결할 수 없게 된다.
자동 포트 선택
비주얼 스크립팅은 사용자가 커서를 타겟 유닛에 직접 대지 않더라도 유닛에서 가장 잘 호환되는 포트를 자동으로 선택하여 더 쉽게 조준할 수 있도록 도와준다.이 포트는 노란색 직사각형으로 강조 표시되어 연결될 위치를 미리 볼 수 있다.이는 작은 포트에 연결하기 위해 고도의 집중을 하지 않더라도 손쉽고 빠르게 새로운 연결을 만들 수 있다는 것을 의미한다.
컬러 코딩
제어 연결(Control Connections)은 항상 흰색인 반면 값 연결(Value Connections)은 타입에 따라 색상으로 구분된다. 타입마다 고유의 색상을 가지고 있고 이를 통해 쉽게 찾을 수 수 있다.컬러 펠릿 아이콘이 없는 타입은 모두 녹색으로 연결된다.
역자주)
* 제어 연결(Control Connections): 유닛의 제일 상단에 있는 삼각형 포트간의 연결을 의미한다.
* 값 연결(Value Connections): 빈 동그란 원형 포트간의 연결을 의미한다.
* 컬러 펠릿 아이콘(Color Pellet Icon): 값 연결시 대응되는 값의 타입을 아이콘으로도 표시하고 있다.
값(Values)
툴바에서 Values toggle을 활성화하면 비주얼 스크립팅은 런타임 동안 이 연결을 통과한 최종 값을 보여준다.
Unity>Preferences>Visual Scripting>Script Graphs>Predic Connection Values가 활성화된 경우, 비주얼 스크립팅은 플레이 모드로 들어가기 전에 값을 예측하려고 시도한다.
예를 들면 다음과 같다.
자동 변환
비주얼 스크립팅은 사용자가 그래프를 깔끔하게 유지할 수 있도록 하기 위해 많은 타입들을 자동으로 변환한다(역자주-프로그래밍의 자동 형변환의 개념임).
예를 들어, 비주얼 스크립팅이 자동으로 처리해 주기 때문에 Transform 출력과 Animator 입력 사이에 Get Component를 사용할 필요가 없다.
다음의 경우 자동 변환이 지원된다.
숫자와 숫자간(예: integer 숫자를 float 변수 혹은 포트에, float 숫자를 integer 변수 혹은 포트에 연결할 때)
부모 클래스(Base Class)를 자식 클래스(Child Class)에 연결할 때
자식 클래스(child Class)를 부모 클래스(Base Class) 연결에 연결할 때
사용자 지정 연산자(Custom Operators)(예: Vector 2에서 Vector 3로 연결할 때)
게임 오브젝트(Game Object)를 하위 컴포넌트(Child Component)에 연결할 때
컴포넌트(Component)를 부모 게임 오브젝트(Parent Game Object)에 연결할 때
컴포넌트(Component)를 형제 컴포넌트(Sibling Component)에 연결할 때
배열(Array)에 열거형(Enumerable)을 연결할 때
목록(List)에 열거(Enumerable)을 연결할 때
또한 비주얼 스크립팅은 박싱(Boxing)과 언박싱(Unboxing)을 지원한다. 즉, 어떤 객체 타입의 포트에서 다른 값 포트로의 연결도 가능하도록 해준다. 참고: 이 경우 데이터 타입이 호환되는지 확인하는 것은 사용자의 책임이며, 그렇지 않으면 재생 모드에서 오류가 발생할 수 있다.
다중 연결
단일 포트는 편의를 위해 여러 개의 포트에 연결될 수 있다.
예를 들어 아래처럼 단일 값 출력 포트(Value output Port)를 여러 값 입력 포트(Value Input Ports)에 연결할 수 있다.
어떤 값을 사용해야 하는지 분명하지 않은 경우에는 다중 연결이 허용되지 않는다.
여러 개의 제어 출력 포트(Control Output Ports)를 단일 제어 입력 포트(Control Input Port)에 연결할 수도 있다.예를 들어, 점프(Jump)는 플레이어가 Space Bar를 누르거나 어떤 오브젝트를 클릭했을 때 모두 발동되도록 할 수 있다.
출력 유닛에서 실행 순서가 명확하지 않은 경우에는 단일 제어 출력 포트를 여러 제어 입력 포트에 직접 연결할 수 없다. 이런 경우를 해결 하기위해서는 여러개의 제어 출력 포트를 가지고 있는 "Sequence" 노드를 이용하면 된다.
두 개 이상의 작업을 연결하려면 시퀀스 노드 헤더의 필드에 더 높은 숫자를 사용하십시오(역자주-2를 4로 바꾸면 4개의 출력 포트가 아래에 생긴다.)
상황별 옵션
연결하고자하는 유닛을 모두 만들어서 연결할 필요 없이 어느 한쪽의 유닛 포트에서 마우스를 끌어 빈공간을 클릭하면 퍼지파인더가 자동으로 팝업되며 연결가능한 옵션이 자동으로 활성화된다. 여기서 어느 하나를 선택하면 자등으로 연결이 이루어진 유닛이 생성된다.
유닛(Units)은 비주얼 스크립팅이 처리하는 가장 기본적인 요소다.다른 비주얼 스크립팅 언어에서는 이를 노드(Node) 또는 작업(Action)이라고 부른다. 유잇은 입력과 출력 포트를 가지고 있으며, 스크립트 그래프(Script Graph)에서 "블록(Blokcs)"처럼 시각적 그래픽으로 표현된다.
유닛(Units)
유닛은 비주얼 스크립팅에서 계산을 처리하는 가장 기본적인 요소다.유닛들은 매우 다양한 일들을 할 수 있다. 예를 들어, 이벤트(Event)를 듣고(Listen, 역자주-받는다 수신한다는 의미), 변수(Variable)의 값(Value)을 얻고(Get), 컴포넌트(Componets)나 게임 오브젝트(Game Objects)에 있는 메소드(Methods)를 호출(invoke)한다.
유닛들은 실행되는 순서를 나타내는 연결(Connections)을 가지고 있으며, 다른 유닛으로부터 값을 전달받아 전송하기도 한다.
유닛 생성하기
기본적으로 비주얼 스크립팅에는 23,000개 이상의 유닛들이 있다.여기에는 전체 Unity 스크립팅 API뿐만 아니라 사용자 지정 스크립트(Custom Scripts) 및 타사 플러그인(Third Party Plugins)의 모든 메서드(Methods)와 클래스(Classes)까지 포함된다. Math, Logic, Variables, Loops, Branching, Events, Coroutines을 위해 추가된 유틸리티 유닛들도 있다.
유닛은 퍼지 파인더(Fuzzy Finder)라는 간단하고 검색이 가능한 생성 메뉴에 잘 정리되어 있다.
퍼지 파인더를 띄우려면 편집창의 아무 빈곳에 마우스 오른쪽 버튼으로 클릭하면 된다. 유닛을 빠르게 찾기 위해 카테고리를 따라가 보거나 제일 위의 상단 필드에서 검색하면 된다.
퍼지 파인더에서 흐리게 보여지는 유닛들은 비주얼 스크립팅이 현재 맥락에서 사용할 수 없다는 의미를 전달하는 것이다. 이는 유용한 예측 디버깅을 가능하게 한다.
퍼지 파인더는 각 유닛이 생성되기 전에 미리보기 안내를 제공한다.예를 들어, Subtract 유닛의 경우 Subtract 유닛의 기능과 포트(Ports)에 대한 간략한 설명이 있다.
오버로드(Overloads)
일부 유닛들은 동일힌 이름으로 여러개로 분화되어져 있는데, 이를 오버로드(Overload, 역자주-프로그래밍 용어임)라고 한다.
예를 들어, Add 유닛의 경우 기본 Add 유닛 이외에 4개의 Add 유닛(Scalar, 2D Vector, 3D Vector, 4D Vector)을 더 가지고 있다. 이 경우 이름 우측에 있는 범주내용을 보고 구분하면 된다.
어떤 메서드 유닛(Method Unit)들은 파라미터 오버로드(parameter Overloads)가 있다. 일반적으로 이러한 다양화는 편의를 위한 제공된 것이며 이들은 거시적으로 같은 기능을 수반한다.어떤 오버로드들은 비교적 더 세부적으로 세팅을 구성할 수 있도록 한다.
예를 들어 Rotate Transform 유닛에는 6개의 오버로드가 있다.그 중 2개는 단일 오일러 각 벡터(Euler Angle Vector)로 각도 값을 취하고, 다른 2개는 X, Y, Z 3개의 개별 축의 값으로 취하고, 마지막 2개는 축에 상대적인 각도 값으로 취한다. 아래 이미지에서 보여지는 3쌍의 유닛들 중 왼쪽은 상대 공간(Relative Space, 상대 좌표)을 우측은 월드 공간(World Space, 절대 좌표)을 기준으로 각도를 지정한다.
아래 이미지는 rotate 유닛에 대한 6개의 오버로드를 나타낸다.
다양한 옵션들에 익숙해질 때까지 적절한 오버로드를 찾는데 여러번의 시행착오나 오류를 경험할 것이다. 이러한 다양한 사용기능들을 올바르게 사용 위해서는 기본적으로 제공되는 가이드나 Unity 메뉴얼을 잘 활용하기 바란다.
유닛의 해석
아래 이미지의 Rotate Transform 유닛의 다음 예에서 가장 먼저 주목해야 할 것은 이 유닛이 선택된 유닛임을 나타내는 가장자리의 파란색 테두리선이다. 유닛을 선택하면 옵션과 가이드가 그래프 검사기(Graph Inspector)에 표시된다.
유닛의 윗부분은 헤더로, 유닛이 하는 일을 간략히 요약한 설명이있다.이 경우 헤더는 Transform Component에서 Rotate Method를 호출하고 있음을 설명하고 있다.
그래프 인스펙터(Graph Inspector)
그래프 인스펙터는 다음과 같이 이루어져 있다.
상단에는 선택된 유닛의 제목과 요약이 있으며, 유닛이 하는 작업에 대한 간략한 개요를 제공한다.
그 아래, 비주얼 스크립팅은 유닛에 대한 모든 경고를 표시한다.위의 예시에서 비주얼 스크립팅은 메시지가 누럭되었음을 경고하고 있다.
그 아래는 유닛의 세팅에 대한 안내가 있다. 세팅은 유닛마다 다르며, 어떤 유닛의 경우 세팅이 필요 없는 경우도 있다. (역자주- "Unit is never entered."는 입력 포트로의 입력 연결이 필요한데 연결되어 있지 않다는 의미를 나타내고 있다.)
그리고 끝으로 Inputs과 Outputs의 각 포트에 대한 설명이 있다.
인라인 값(Inline Values)
어떤 입력 값 포트(Value Input Ports, 아래 유닛에서 제일 좌측의 빈 동그라미들)들은 그 옆에 작은 필드(아래 대부분 0이라고 쓰여져 있는 부분)를 가지고 있다.이를 인라인 값(Inline Value)이라고 한다.포트가 연결되어 있지 않으면 이 필드의 값이 대신 사용된다.대부분의 일반적인 타입들은 인라인 값을 지원하지만 모든 타입이 인라인 값을 지원하는 것은 아니다.인라인 값은 모든 값 입력 포트(Value Input Port)에 리터럴 유닛(Literal Units)이 연결되지 않도록 허용하기 때문에 그래프를 깔끔하게 유지하는 데 유용하다.
스크립트 그래프(Script Graphs)는 프로젝트에서 상호작용(Interaction)을 만드는 주요 도구다. 유닛(Unit) 기반 액션(Actions)과 값(Values)을 사용는 이 그래프는 매 프레임(Frame)마다 또는 어떤 이벤트(Event)가 발생했을 때 세부적으로 정해진 순서대로 로직을 실행한다.
본 챕터에서는 아래의 요약 내용들을 다루게 된다.
레고 블럭같은 유닛들 유닛(Units)은 비주얼 스크립팅에서 처리하는 가장 기본적인 요소다. 유닛은 스크립트 그래프내에서 입력과 출력 포트가 있는 노드(nodes)로 표시된다.
유닛의 연결 유닛의 연결은 연결 가능한 출력 포트와 입력 포트간에만 이루어 지도록 되어있다.(역자주-연결 불가한 경우 자동적으로 비활성화되어 연결이 이루어 지지 않는다.)
릴레이션(Relations)을 이용한 디버그 릴레이션(Relations)은 각 유닛의 고유한 형태로 사전 정의되어(predefined) 있어서 수정할 수 없지만, 유닛(Unit)들의 각 포트(Port)간에 의존관계를 이해하는데 유용하다. 당연히 비주얼 스크립팅 역시 예측 디버깅(Predictive debugging)을 위해 백그라운드에서 이들 관계 정보(Relation Information)를 이용하고 있다.
역자주)여기서 릴레이션은 비주얼 스크립팅 그래프 에디터의 우측상단에 보이는 "Relations" 메뉴를 눌렀을 때 각개 유닛 내부에 보이는 검은선 색의 흐름표시를 의미한다. 솔직히 어두운 색이라 잘 보이지는 않는다. 유닛이 어떻게 다른 유닛과 연결되어야 하는지 즉, 컨트롤 포트의 연결 필요 유무, 데이타의 연결 필요 유무를 알 수 있다. 그런데 현재 시점에서 굳지 이해하지 못해도 무관하다. 하다보면 알게 된다. 혹은 몰라도 인터페이스적으로 해당 규칙을 따르지 않으면 안되기에 자연스럽게 이용하게 된다.
예측 디버깅(Predictive Debugging) 비주얼 스크립팅은 플레이 모드로 진입하기 전에 오류의 원인을 예측하고 해당 유닛을 가르킨다.
재사용 가능한 그래프인 슈퍼 단위(Super Units) 슈퍼 유닛(Super Units)은 독립된 단일 유닛처럼 부모 스크립트 그래프에 중첩(nested)되는 스크립트 그래프다. 이는 스크립트 그래프를 재사용 가능하게 하고 구조화시킬 수 있는 강력한 기능이다.
그룹은 작성한 그래프(유닛들의 집합)들을 조직화하여 관리할 수 있도록 하는 박스를 의미하며, 이는 비주얼 스크립트의 일부를 재사용할 수 있도록 하기도 합니다.
스크립트 그래프에서 그룹을 만드는 방법
Ctrl 키또는 Mac에서Cmd를 누른 상태에서 그래프 주변 영역을 마우스로 선택한다.
그래프의 일부 유닛들이 포함되도록 마우스를 드래그한다.
각 그룹에 제목을 지정한다.팁: 그룹에 의미 있는 제목을 제공하는 것이 좋다.
참고: 그룹의 헤더를 두 번 눌러 그룹의 모든 항목을 선택하십시오.
참고: 유니티 컨트롤 스킴(Unity Control Scheme)을 사용할 경우, Alt(Option) 키를 누른 채 마우스로 헤더(박스 위쪽)를 끌 경우 내용을 가만있고 박스만 움직일 수 있다.(역자주-기본적으로 그냥 마우스로 박스 헤더를 이동하면 박스 안의 모든 내용이 함께 움직임니다. 박스만 움직일 경우 Alt키를 함께 누르면 된다.)
그룹이 선택되어 있을 때 마우스 오른쪽 버튼을 누르고 Delete(Section)를 하면 그룹 박스가 삭제된다.
그래프 인스펙트(Graph Inspector)에서 그룹의 이름, 주석 그리고 색상을 변경할 수 있다. 그 코멘트(comment)는 인스펙터(Inspector)에서만 볼 수 있다.
편집기내부에 생성된 임배드 그래프(Embed Graph) 프리팹 인스턴스(Prefab Instances)를 제외한 모든 타입의 그래프에 대해 완전하게 프리팹(Prefab)에서의 사용을 지원한다.
프리팹 인스턴스(Prefab Instance)
Graph
Embed
편집기에서 생성된 경우
O
!
런타임에 인스턴스화된 경우
O
O
프리팹(Prefab)으로 임베드 그래프(Embed Graph)가 있는 머신(Machine)을 사용하면 프리팹 정의에서 편집한 내용이 자동으로 프리팹 인스턴스(Prefab Instances)로 전파된다. 이 때 비주얼 스크립팅은 인스펙터(Inspector)와 그래프 창에 경고 메시지를 표시한다.
참고: 프리팹에 머신(Machine)을 추가할 때는 임배드(Embed) 대신 그래프(Graph)를 사용하십시오.
프리팹 오버라이드(Prefab Overrides)
비주얼 스크립팅은 Unity의 기본 직렬화(Serialization)를 사용하지 않는다. 중첩(Nesting), 확장성(Extensibility) 및 커버리지(Coverage)가 요구하는 안정성을 위해 사용자 지정 직렬화 엔진(Custom Serialization Engine)인FullSerializer를 사용한다.
참고: 인스펙터(Inspector) 라벨(Labels)과 값(Values)이 볼드(Bold)로 표시되면 프리팹(Prefab)은 오버라이드(Override)보다는 차별화(Differentiation)를 나타낸다.예를 들어, 프리팹 인스턴스의 인스펙터 필드는 이 값을 오버라이드했더라도 프리팹 정의와 동일한 값을 갖는 경우에는 절대 볼드(Bold)로 표시되지 않는다.
역자주) 위 내용의 말이 어려워서 아래 영상을 제작해서 추가합니다. Embed Machine을 가지고 있는 프리팹의 경우 프리팹 원본을 수정하는 것에는 문제가 없지만 하이어라키(Hierarchy)로 끌어와서 편집하려고 하면 경고 메시지가 나오게 됩니다. 즉, 편집하지 말라는 것입니다. 따라서 프리팹에 비주얼 스크립트를 작성할 때는 Embed가 아닌 Graph로 작성하여 연결하는게 여러모로 안전합니다.
Unity와 비주얼 스크립팅에는 수백 가지의 타입이 있다.다음은 가장 일반적인 타입의 요약 표이다.
타입
설명
Float
소수점 값이 있는 숫자. 부동소수점(예: 0.5 또는 13.25)
Integer
소수점 값이 없는 숫자(예: 3 또는 200).
Boolean
불(Bool), 참 또는 거짓만 될 수 있는 값.일반적으로 논리 또는 토글에 사용된다.
String
문자열(String), 이름 또는 메시지와 같은 텍스트의 한 부분.
Char
문자열의 단일 문자(영문자 A, a, B, b 또는 문자로 나타내는 숫자 1, 2).거의 사용할 일이 없다.
Enums
열거형이라고 한다.각각은 드롭다운에서 흔히 볼 수 있는 옵션으로 유한하게 열거된다. 예시1) Unity에서 "Force Mode" 열거형은 "Force", "Impulse", "Acceleration" 또는 "Velocity Change"가 될 수 있다. 예시2) "Direction(방향)"의 열거형은 "동(East)", "서(West)", "남(South)", "북(North)"으로 나타낼 수 있다.
Vectors
벡터(Vectors)는 부동 좌표(float coordinates)의 집합으로 위치(Positions) 또는 방향(directions)을 갖는다. Unity에는 다음과 같은 세 가지 벡터가 있다. Vector 2: 2D에 대한 X, Y 좌표 Vector 3: 3D에 대한 X, Y, Z 좌표 Vector 4: X, Y, Z, W 좌표로 거의 사용되지는 않는다.
GameObject
게임 오브젝트(GameObject)는 유니티 씬에 있는 가장 기본이 되는 엔터티(entity)다.각 게임 오브젝트는 이름(name), 위치(position)와 회전(rotation)을 위한 트랜스폼(transform), 컴포넌트(component) 리스트가 있다.
Lists
목록(Lists)은 순서가 정해진 요소(elements)의 모음입니다.요소(elements)로는 어떤 타입이든 될 수 있지만, 하나의 목록(List)은 모두 동일한 타입의 요소들로 이루어 져야 한다. 단, 1번이 아닌 0번 부터 목록 번호가 할당(zero-based index) 되기 때문에 이를 기준으로 목록의 각 요소를 검색하고 할당해야 한다.
Dictionaries
딕셔너리(Dictionary, 번역하면 사전이지만 프로그래밍 용어상 딕셔너리로 불림)는 요소들(elements)가 고유 키(unique key)와 그 키에 매핑되는 값(value)을 갖는 모음이다. 예를 들어, Name(string key)에 대해 Age(integer value)을 가질 수 있다. 고유 키(key)로 각 요소를 검색하고 값을 할당한다.
Object
"오브젝트"는 특수한 타입이다.노드(Node)가 오브젝트를 요구할 때, 이는 오브젝트의 종류에 상관하지 않겠다는 갓을 의미한다. (역자주-Object 데이타 타입은 모든 데이터들의 최상위 타입이다.)
역자주) 완전 초보자를 위해 코맨트를 하면, 위 내용은 비주얼 스크립팅을 하든 C#, C++ 코딩을 하든 프로그래밍 이라는 작업을 하기 위해서는 알아야 하는 기초 개념이다. 최소한 변수(Variable)의 의미 그리고 위 내용 중 integer(정수), float(플로트), bool(불) string(string) 정도만이라도 알고 넘어가기 바란다.
오브젝트(Object)가 무엇을 나타내고 무엇을 할 수 있는지 구별하기 위해 각 오브젝트는 타입(유형, 역자주-데이터 타입)이 있다. 비주얼 스크립팅에서 대부분의 타입은 아이콘으로 표현된다.
타입을 선택해야 하는 경우 비주얼 스크립팅에 타입 메뉴가 표시된다.
가장 일반적인 타입은 메뉴 상단에 있다.열거형(Emun)은 맨 아래에 그룹화되어져 있다. 기타 타입들은 그 타입 명칭의 네임스페이스(Namespace)로 그룹화되어져 있다. 모든 유니티 컴포넌트(Unity Component) 및 데이타 타입(Data Type)은 Unity Engine namespace에서 찾을 수 있다.
사용자 정의 타입
비주얼 스크립팅은 모든 클래스(Class) 및 구조체(Struct) 타입을 지원한다.기본적으로 유니티 오브젝트(Unity Objects), 컴포넌트(Components), 모노 비헤이비어(Mono Behaviours), 스크립터블 오브젝트(Scriptable Objects)에서 파생된 가장 일반적으로 사용되는 타입만 퍼지 파인더(Fuzzy Finder)에 나타난다.
(역자주-디폴트로 나타나지 않는 타입들은 "Edit > Project Settings > Visual Scripting"에 추가해주면 된다. 추후 사용 가능한 기능이 많아지면 본인의 필요에 따라 이 메뉴를 자주 이용하게 될 듯 하다)
타사 플러그인과 같은 사용자 정의 어셈블리의 사용자 정의 타입을 사용하려면 먼저어셈블리 옵션(Assembly Options)에 추가해야 한다.
그래프(Graph)는 재사용할 수 있으며 그 그래프 소스를 가지고 있는 머신(Machine)에 의해 참조되어 진다.그래프(Graph)는 일반적으로 임베드(Embed)보다 우월하다. 그래프(Graph)는 재사용 가능하고 어떤 오브젝트에 억매이지도 않으며 프리팹(Prefabs)에서 사용할 때도 안정적으로 작동한다.
그래프(Graph) 파일을 생성하는 방법
프로젝트 패널의 빈 폴더를 마우스 오른쪽 버튼으로 누른다.
Create>Visual Scripting>(Script또는State) Graph를 선택한다. 참고: 최상위 그래프 폴더에 그래프 파일을 저장하는 것이 좋지만 폴더의 구조는 기능에 영향을 주지 않는다. (역자주-보통 C# 코드는 Scripts 폴더를 만들어 저장하듯이 VisualScripts라는 폴더를 만들어서 저장하면 된다.)
객체 변수(Object Variables)는 변수 컴포넌트로도 존재하며, 스크립트 그래프에서 사용할 수 있다.예를 들면, 게임 오브젝트에 체력(health) 변수가 노출된다는 것이다..
객체 변수(Object Variable)는 게임 오브젝트(Game Object)를 선택하고 인스펙터(Inspector)의 변수(Variable) 컴포넌트에서 확인할 수 있고 블랙보드(Blackboard)의 오브젝트(Object) 탭에서도 확인할 수 있다.
참고: 블랙보드(Blackboard)에서 변수 콤포넌트(Variable Component)가 있는 게임 오브젝트를 선택했을 때 게임 변수(Object Variable) 탭이 활성화되며, 이후 이 탭에서는 선택한 게임 오브젝트의 변수만 볼 수 있다.프로젝트 창에서 스크립트 그래프 에셋을 선택하면 오브젝트(Object) 탭이 사라진다.
역자 주-참고를 위해 아래 이미지를 추가함.
객체 변수(Object Variable)의 사용 방법.
스크립트 머신(Script machine)을 추가한다. 유니티에서 자동으로 해당 게임 오브젝트에 변수 컴포넌트(Variable Component)를 추가한다.이 컴포넌트는 객체 변수(Object Variables)를 위한 것이다. 참고: 객체 변수(Object Variable)는 해당 오브젝트 전체에 공유된다. 게임 오브젝트에 적용된 여러 개의 스크립트 그래프는 모두 동일한 객체 변수(Object Variable)를 사용할 수 있다.사용자가 모든 겍체 변수를 직접 추가해야 하므로 게임 오브젝트에 존재하지 않는 객체 변수(Object Variable)는 사용하면 안된다.
Edit Graph를 선택한다.
그래프에 유닛(Units)을 추가한다.
변수 컴포넌트(Variable Component)에 사용할 새 변수의 이름을 입력한다.
이 새 변수를 추가하려면 (+) 버튼을 클릭한다. 새로 생성된 변수가 변수 목록에 나타나고 값이 null로 설정된다.
변수 이름과 유형을 변경하려면 드롭다운 메뉴를 클릭한다.
변수 탬의 새 변수를 그래프 상에 드래그 앤 드롭으로 끌어올 수도 있다.
이제 그래프 안에서 이 변수를 사용할 수 있다.
주의: 변수 콤포넌트(Variable Component) 내부의 변수 이름을 변경하면, 그래프에 올려진(이미 사용중인) 변수 유닛에 반영되지 않는다. (역자 주-이미 사용중인 변수 유닛의 경우 수동으로 변경된 이름에 맞게 수정해주어야 함. 변수 유닛의 이름에서 풀다운 메뉴로 변경해주면 됨)
변수(Variables)는 값을 저장하는 저장소이다.각 변수에는 이름(name), 유형(type) 및 값(value)이 있다.변수 내부의 값은 런타임 중에 변경될 수 있다.
블랙보드 윈도우(Blackboard Window)
블랙보드 윈도우는 스크립트 그래프 윈도우(Script Graph Window)의 블랙보드(Blackboard) 버튼(<x>)을 통해 열수 있다(역자 주-기본적으로 열려져 있음). 각 변수의 타입에 해당하는 탭이 하나씩 있다. 그래프(Graph) 탭은 스크립트 그래프를 선택한 경우에만 활성화된다.오브젝트(Object) 탭은 게임 오브젝트를 선택한 경우에만 활성화된다.
변수는 무엇인가를 담는 용기와 같다.각 변수에는 이름, 유형 및 값이 있다. 비주얼 스크립팅에는 다음과 같은 6가지 유형의 변수가 있다.
변수형
설명
Flow Variable 플로우 변수
플로우 변수(Flow Variable)는 지역 변수(Local Variable)와 동일하다. (역자 주-C#, C++에서 for문 작성할 때 흔히 쓰는 "int i"같은 개념 )
Graph Variable 그래프 변수
그래프 변수(Graph Variable)는 스크립트 그래프의 인스턴스(Instance)에 범위의 변수이다. 이 변수는 가장 작은 범위를 가지고 있고 그래프 밖에서 접근하거나 수정할 수 없다.
Object Variable 객체 변수
객체 변수(Object Variable)는 게임 객체(Game Object) 범위의 변수이다. 이 변수는 해당 게임 오브젝트에 있는 모든 비주얼 스크립트 그래프에 공유된다.
Scene Variable 씬 변수
씬 변수(Scene Variable)는 현재 씬(Scene) 전체에 공유된다.
Application Variable 어플리케이션 변수
어플리케이션 변수(Application Variable)는 씬(Scene)이 바뀌어도 지속된다. 단, 응용 프로그램이 종료되면 리셋된다.
Saved Variable 저장 변수
저장 변수(Saved Variable)는 응용 프로그램이 종료된 후에도 지속된다.단순하지만 강력한 저장 시스템으로 활용될 수 있다.이 변수들은 유니티의 Player Prefs에 저장된다는 것으로 게임 오브젝트나 컴포넌트 같은 유니티 오브젝트를 참조하지 않는다는 뜻이다.
저장 변수(Saved Variable)와 초기 변수(Initial Variable)의 값
저장 변수(Saved Variable) 탭 아래에는 두 개의 하위 탭이 있다. 초기화(Initial) 및 저장됨(Saved).
초기화(Initial) 탭에서는 새로운 게임을 시작할 때 자동으로 생성되는 기본 값을 정의한다.
저장된(Saved) 탭에는 현재 시스템의 저장 변수(Saved Variable) 상태가 표시된다. 저장 변수의 값을 초기화 하거나 변경하고자 한다면 수동으로 편집하거나 모두 삭제하면 된다. (역자 주 - 게임 만들 때는 Initial 부분에만 변수를 지정하면 됨. Saved 탭에는 자동으로 Initial에 만들어진 변수와 게임을 실행하면서 변경된 값이 저장되어짐)
동적 변수의 값 설정
존재하지 않는 변수에 값을 세팅(저장)하려 하면 변수가 자동으로 생성된다.예를 들어, 다음 그래프는 변수로써 gold가 정의되지 않았음에도 불구하고 250 값을 담는 gold라는 이름의 정수(Ingeger) 타입의 저장 변수(Saved Variable)를 생성한다.
변수(Variable)는 편집 모드 상에서나 플레이 모드 상에서 선언할 수 있다.
변수의 가시성(Variable's Visibility)
비주얼 스크립팅의 모든 객체 변수(Object Variable)는 퍼블릭(Public)으로 선언된다. 따라서 다른 오브젝트에서 액세스하도록 할 수 있다.
그래프는 로직(logic)을 시각적으로 표현한 것이다. 이 그래프가 비주얼 스크립팅의 핵심에 있다.
그래프에는 두 가지 종류가 있다.
스크립트 그래프(Script Graphs)는 개별적인 동작들과 값을 특정 순서로 연결하는 것이다.실행 순서는 스크립트(Script)의 흐름(Flow)이다.스크립트 그래프는 언리얼 엔진의 블루프린트(Blueprint) 비주얼 스크립팅 언어와 유사하다. (역자 주 - Script Graphs는 Script Machine에서 작성)
상태 그래프(State Graphs)는 서로 다른 상태를 만들고 그 상태들 간에 전환을 생성한다.각 상태(State)는 작은 프로그램 역할을 한다.상태 그래프는 플레이 메이커(PlayMaker) 또는 유한 상태 머신(FSM; Finite State Machine) 시스템과 유사하다. (역자 주 - State Graphs는 State Machine에서 작성, 각 State Graphs의 내부는 Script Graph로 작성된다. 여기 있는 Script Graph의 집합이 시스템 설계의 목적상 어떤 상태를 의미(정의)하기 때문에 State Graph가 되는 것이다)
이 두 종류의 그래프로 어떤 종류의 게임도 만들 수 있다.이 글에서는 그래프(Graph)와 그 그래프들의 유사점을 설명하고자 한다.각 그래프에대한 설명은 본 메뉴얼에 별도의 전용 섹션이 마련되어 있다. 스크립트 그래프와 상태 그래프의 순서로 읽어 보기 바란다. 더욱이 두 종류의 그래프는 결합할 수 있다. 예를 들어, 상태 그래프의 각 상태 노드(State Node)는 실제로 스크립트 그래프(Script Graphs)로 이루어져 있다.
어떤 경우에 스크립트 그래프와 상태 그래프를 사용하는가!
스크립트 그래프(Script Graph)는 매 프레임마다 또는 충돌과 같은 이벤트가 발생할 때 동작이 실행된다.스크립트 그래프는 분기(branching, 역자 주-if, swith 같은), 루프(loop), 수학(math) 등과 같은 소위 "낮은 수준(low-level)"이라 일컬어지는 로직(logic)에 이용된다. 스크립트 그래프는 "언제 작동할 것인가?, 어떤 동작을 할 것인가? 그리고 어떤 순서로 동작할 것인가?"라는 질문에 가장 잘 대답한다.(역자 주-보통 프로그래밍을 처음 공부할 때 접하는 대부분의 것들이 스크립트 그래프에 속한다.)
상태 그래프(State Graph)는 AI 행동, 씬(Scene) 또는 레벨 구조(level structure), 그리고 상태 개념이 요구되는 "고 수준(high-levle)" 로직(logic)을 만드는 데 사용된다.예를 들어, 몬스터 NPC가 "패트롤(patrol)", "추적(chase)" 및 "공격(attack)" 상태를 가져야 하는 경우, 혹은 어떤 문이 "잠금(locked)", "잠금 해제(unlocked)", "열림(open)" 상태를 가져야 하는 경우이다. 상태 그래프(state graphs)는 "현재 나의 행동은 무엇인가? 그리고 언제 그 행동이 바뀌어야 하는가?"라는 질문에 가장 잘 답한다. (역자 주-일련의 프로그래밍 집합이 의미있는 행동을 하도록 하는 것이 상태 그래피이다. 즉, 왔다 갔다 경계를 하고 있던 몬스터가 플레이어 캐릭터가 나타나면 공격을 시작한다고 할 때 경계 상태에서 공격 상태로 전환되는 것을 구현하는 것이다.)
다음은 두 종류의 그래프 모두 가지고 있는 공통의 기본 개념에 관한 것이다.
머신들(Machines)
머신(앞쪽 글에서 이해를 위해 시스템으로 번역하였으나 이후 부터는 혼돈을 막기 위해 머신으로 번역함)는 게임 오브젝트에 추가되어 플레이 모드 중 그래프의 로직을 실행하는 구성요소다.각 그래프는 스크립트 머신(Script Machine)과 상태 머신(State Machine)이 있다. 이들은 모두 비주얼 스크립팅 컴포넌트 분류에 있다.
스크립트 머신은 오브젝트(Object)가 어떻게 동작해야 하는지를 설명하고, 상태 기계는 오브젝트(Object)가 언제 그 동작을 변경해야 하는지를 결정한다.
두 머신 모두 인스펙터(Inspector)에 동일한 옵션을 가지고 있다.다음 예는 스크립트 머신 컴포넌트가 생성된 경우다.
각 그래프 마다 제목(title)과 간단한 설명(summary)을 작성할 수 있도록 되어져 있고 이는 비주얼 스크립팅 기능에 전혀 영향을 미치지 않는다. (역자 주-C#에 주석을 다는 것과 같음)
편집할 그래프 열기
그래프 편집 버튼(Edit Graph Button)은 그래프 윈도우(Graph Window)와 그래프 인스펙터(Graph Inspector)에 있으며 머신 그래프(Machine Graph) 창을 활성화 시킨다. 하나의 오브젝트에 하나의 머신이 있는 경우 비주얼 스크립팅은 그 그래프를 자동으로 선택한다. (역자 주-여러 개의 머신이 하나의 오브젝트에 있다면 제일 위에 것이 자동 선택되는 듯함)
스크립트 소스(Sources): 임배드(Embeds) 와 그래프(Graphs)
스크립트 소스는는 두 가지 유형이 있다. 임배드(embed) 방식(삽입되어져 있음의 뜻)과 그래프(graph) 방식(별도 파일로 만들어져짐)이다..
머신 컴포넌트를 제거해도 그래프 에셋은 여전히 존재한다.소스를 임베드로 전환해도 그래프는 삭제되지 않는다.
씬 참조
임베드 그래프는 프리팹으로 저장되지 않는 그 그래프가 속한 현재 씬의 게임 오브젝트를 가르킨다.
그래프는 어떤 씬에도 귀속되지 않기 때문에 현재 씬의 게임 오브젝트만을 가르킨다고 말할 수 없다.
프리팹(Prefabs)
임배드 스크립트 머신(embed script를 가지고 있는 Machine)이 에디터에 존재한다면 프리팹을 인스턴스화하해서 사용해서는 안 된다.
그래프 스크립트 머신(graph script를 가지고 있는 machine)은 모든 프리팹상에서 안전하게 사용할 수 있다.
역자 주) 위에서 설명한 임배드(Embed) 와 그래프(Graph)는 막상 알면 쉬운데 그래프(Graph)라는 단어를 중복적으로 사용해서 헷갈리게 만든다. "비주얼 스크립트는 그래프(Graph)를 작성한다"는 것은 프로그래밍을 한다는 의미인데 위의 표에서 설명하는 그래프(Graph)는 에셋 파일로 그래프 스크립트를 저장해서 사용한다는 의미이다. 임배드(Embed)는 머신 컴포넌트(Machine Componet)에 내장시켜서 사용한다는 의미이다. 즉, 형식적으로는 파일로 저장하느냐 마느냐의 차이이다. 따라서 그래프(Graph)라는 단어의 의미를 잘 구분해서 이해해야 한다.
그래프(Graph)
그래프(graph)는 여러 다른 머신에서 참조하는 연결된 유닛들의 재사용 가능한 집합이다.그래프(graph)는 일반적으로 임베드(embed)보다 재사용가능하다는 측면, 특정 오브젝트에 억매이지 않는다는 측면 그리고 프리팹으로 사용해도 안전하다는 측면에서 우수하다.그런데 어떤 소스를 사용할지(즉, embed를 사용할지, graph를 사용할지) 결정하는 아주 간단한 가이드 라인이 있다.
그래프로 머신의 원본 옵션을 전환하고자한다면 머신에서 그래프를 선택하면 된다(역자 주-머신 컴포넌트를 추가하면 임배드와 그래프중 선택하는 메뉴가 자동으로 나타난다. 기본은 그래프 설정이다).스크립트 머신(Script Machine)은 스크립트 그래프(Script Graph)가 필요하고 상태 머신(Script Machine)은 상태 그래프(State Graph)가 필요하다.
대부분의 경우 그래프(graph)를 사용하게 될 것이다.그래프(graph)를 하나 이상의 오브젝트 또는 씬(scene)에 걸쳐 재사용하고자 할 때 그래프(graph)를 로드하는 것이 빠르고 유지관리가 쉽기 때문이다.
현재 씬(scene)에서 한 번만 사용되는 그래프(graph - 여기서 그래프는 스크림트로 작성한 그래프)라면 임베드(embed)를 사용할 수 있다.이는 GUI에서 유용한데 특정 씬에서만 사용되도록 할 수 있다.
참조한 모든 오브젝트에 공통으로 반영
그래프(graph)를 변경하면 해당 그래프가 연결된 모든 오브젝트에 변경 사항이 모두 적용된다. 오브젝트의 모든 인스턴스에 대해 고유한 그래프를 사용하거나 변경사항을 복사하여 붙여넣을 필요는 없다.
소스 변환
한 종류의 소스에서 다른 종류의 소스로 변환할 수 있다.
(역자 주-임배드를 그래프로, 그래프롤 임배드로 전환할 수 있다)
그래프(graph)에서 임배드(embed)로 전환하는 경우
그래프에서 임베드로 전환하려면변환(Convert) 버튼을 클릭하면 된다.
예를 들어, AI 동작에 대해 여러개의 에너미 개체에서 공유되고 있는 공통의 상태 그래프를 사용 중인데 특정 에너미 하나에 대해 특수한 동작을 추가 혹은 삭제하는 경우 그래프(graph)를 임베드(embed) 그래프로 변환하여 다른 개체와는 독립적으로 작동하게 할 수 있다.
임배드(embed)에서 그래프(graph)로 전환하는 경우
임배드(Embed)에서 그래프(Graph)로 변환하려면변환(Convert)버튼을 클릭하고 새 그래프의 경로를 지정한 후와 파일 이름을 입력하면된다. 비주얼 스크립팅은 임배드 그래프(embed graph)의 모든 내용을 그래프(graph)로 복사한다(그래프에서 지원되지 않는 씬 참조는 제외됨).그러면 머신 컴포넌트가 자동적으로 그래프 모드로 전환되고 새로운 그래프를 참조한다.
예를 들어, 적 게임 오브젝트의 이동을 구현하는 임베드 그래프를 만들었지만, 유사한 다른 NPC에 동일한 로직이 필요하다면 임베드 그래프(embed graph)를 다시 사용할 수 있도록 그래프(graph)로 변환하면 된다.
유닛(units)은 비주얼 스크립팅에서 계산의 가장 기본적인 요소다.유닛들은 매우 다양한 일들을 할 수 있다. 예를 들어, 이벤트 받기(listen), 변수의 값(value) 얻기(get) 그리고 컴포넌트(components)와 게임 오브젝트(game objects)에 대한 메소드(methods)를 호출(invoke)한다.
유닛들(units)은 자신이 사용되거나 다른 유닛들로부터 값을 전달받고 전달하는 순서를 의미하는 연결(conections)을 가지고 있다.
포트(Port)
연결(connections)은 한 유닛의 포트에서 다른 유닛의 포트로 선을 끌고가 붙임으로 생성된다.
유닛의 왼쪽에는입력 포트(Input Ports)가 있다.
유닛의 오른쪽에는출력 포트(Output Ports)가 있다.
제어 포트(Control Ports)는 연결 및 흐름(flow) 생성에 사용된다.흐름(flow)은 유닛이 실행되는 순서다.흐름(Flow)은 항상 왼쪽에서 오른쪽으로 흐르게 되는데 유닛에 있는 작은 화살표로 그 방향을 표시하고 있다.
값 포트(Value Ports)는 값을 연결하는 데 사용된다.각 값 포트에는 노드를 연결할 때 일치해야 하는 유형(type)이 있다.
역자 주) 이해를 돕기위해 아래 이미지를 추가하였다. 각 유닛의 왼쪽은 입력 포트이고 우측은 출력포트인데, 삼각형 모양이 제어 포트(Control Ports)이고 작은 동그라미들은 값 포트들(Value Ports)이다. 값 포트들은 유닛 내부에 색깔이나 이미지들을 가지고 있는데 값 포트의 각 노드에 선을 연결하기 위해서는 이 색이나 이미지가 같해야만 연결이 이루어 진다. 즉, 이는 데이터의 타입을 의미한다. 주황색은 텍스트(string), 하늘색은 숫자(int, float 등), 보라색은 불리언(Boolean)을 의미한다. Vector, Quaternion을 나타내는 이미지들도 있다.
포트 유형(Types of Ports)
플로우 포트(Flow Ports)는 작업이 실행되는 순서를 나타낸다.일반적으로 유닛(Unit)은 처리가 완료되면 해당 유닛의 오른쪽면에 있는 출력 포트 중 하나에서 다음 유닛으로 흐름(flow)이 전달된다. (역자 주 - 왼쪽에서 입력 받아서 오른쪽으로 출력는 흐름이라는 의미)
데이터 포트(Data Ports)에는 타입 값(type values)이 포함되어 있다. 타입(Types)에는 부울(boolean), 정수(integer), 문자열(string) 등이 있다. 유닛의 오른쪽에 있는 데이터 포트는 출력으로 간주되는 반면, 장치의 왼쪽에 있는 포트는 입력이다. 이것들을 연결하면 정보가 한 유닛에서 다음 유닛으로 전달하는 흐름이 생겨나게 된다.
타입(Type) - 데이터 타입 타입은 데이터 사용 방법을 컴파일러에게 알려주는 데이터의 속성(attribute)이다. 스크립팅에서 모든 것은 객체(Object): 즉, 숫자(numbers), 텍스트(pieces of text), 벡터(vectors) 및 유니티 컴포넌트(unity components)는 모두 객체(Objects)다.
변수(Variable) 변수는 값과 데이터를 저장하는 용기(containers)이다. 각 변수에는 이름(name), 타입(type) 및 값(value)을 가지고 있다. 변수 내부의 값은 런타임(runtime) 중에(즉, 실행중에) 변경될 수 있다.
그래프(Graphs), 상태(States) 및 시스템(Machines) 그래프(Graphs)는 논리(logic)를 시각적으로 표현한 것이다. 이 것들이 비주얼 스크립팅의 핵심에 있다.
(역자 주 - machine을 시스템으로 번역하였다. 유한 상태 머신(FSM - Finite State Machine)에서 machine의 개념을 이해하는게 도움이 된다. 유니티에서는 Script Machine, State Machine 이라는 용어를 사용하고 있다.)
그룹(Groups) 그래프들을 조직화하기 위해 그룹을 만들게된다. 그룹은 유닛을 둘러싸는 박스형태로 만들어진다.
참고: 파일을 공용 저장소(repository)에 푸시(push)한 경우 이 방법은 커밋 기록(commit history)에서 삭제되지 않는다. 비주얼 스크립팅 파일을 불법적으로 재배포하고 있는 경우. 저장소(repository)를 비공개로 설정하거나 비주얼 스크립팅 파일을 포함하지 않는 새 트리를 사용하여 새로운 저장로(repository)를 시작해야 한다.
반복된 작업을 빠르게 하기 위해 창 레이아웃(에디터 구성)과 바로 가기 키를 설정할 수 있다.이 글에서는 이러한 바로 가기뿐만 아니라 창 설정에 대한 개요를 제공한다.키보드 단축키를 사용하여 많은 비주얼 스크립팅 기능을 바로 실행할 수 있다. 비주얼 스크립팅 에디터는 3개의 메인 창이 있는데 "Window > Visual Scripting"에서 확인할 수 있다.
Graph(그래프): 메인 그래프 에디터.
Graph Inspector(그래프 인스펙터): 유닛과 기타 그래프 요소의 세부 정보를 확인하고 설정할 수 있는 인스펙터.
Blackboard(블랙 보드): 유닛의 입력 및 출력 포트를 편집한다. 또한 변수들을 정의하고 편집할 수 있다.
팁: 윈도우들을 배치하는 레이아웃 순서는 선호하는 방식으로 하면되지만, 다음을 고려하는 것이 좋다.
Graph Window(그래프 창)와 씬(scene) 뷰는 동일한 공간에 배치한다.
Graph Inspector창은 Unity Inspector 창이 다른 창들의 옆에 독립적으로 있는 것처럼 배치한다.
역자 주) 위의 팁을 참고하면 아래처럼 하라는 것인데, 모니터 2개의 경우 Graph Window를 별도 창에 놓거나 Shit+Space Bar로 전체 화면으로 하는게 편리합니다.
그래프 창 최대화
전체 화면을 차지하도록 그래프 창을 최대화할 수 있다.이렇게 하면 Graph Inspector(그래프 인스펙터)와 변수 탭이 사이드에 잘 나타나게 된다.최대화하면 복잡한 그래프를 보다 보기 쉽게 시각화할 수 있다.최대화하는 방법에는 다음 세 가지가 있다.
마우스를 Graph Window(그래프 윈도우) 위에 놓고 Shift+Space를 클릭한다.
Graph Window 배경을 마우스로 더블 클릭한다.
도구 모음에서 최대화(Full Screen)를 선택한다.
사이드바의 레이아웃 단추를 사용하여 최대화된 뷰포트 주변의 각 패널들을 재정렬하거나 이동할 수 있다.
참고: 듀얼 모니터를 사용하는 경우 두 번째 모니터에서 비주얼 스크립팅 작업을 진행하는 것이 편리하다.이렇게 하면 그래프 편집 공간이 더 넓어지고 유니티 레이아웃이 그대로 유지된다. 전체 편집화면에서 사이드 바 윈도우(Graph Window, Blackboard)는 자동적으로 필요한 크기를 먼저 확보하도록 되어있다.
그래프 창
그래프를 선택하면 도구 모음이 그래프 창에 표시된다.
토글/이동/확대축소:
그래프 인스펙터를 닫거나 열기다.
블랙보드를 닫거나 열기한다.
그래프 인스펙터, 블랙보드를 화면의 왼쪽 혹은 오른쪽으로 이동시킨다. (참고-위 이미지에서는 보이지 않음)
그래프 윈도우(그래프 편집창)을 확대하거나 축소한다.
Relationships 옵션: 유닛의 내부 연결을 표시한다(스크립트 그래프에만 해당)
Value 옵션: 비주얼 스크립팅이 값을 예측하여 그래프의 연결선에 그 값을 표시한다(스크립트 그래프에만 해당).
Carry 옵션이 토글되면 현재 선택 영역의 하위 유닛들이 함께 움직인다.이것은 각 유닛을 수동으로 선택하지 않고 그래프의 많은 부분을 한 꺼번에 이동 및 배치하는데 유용하다.
Overview(개요) 버튼은 Graph Window 화면내에 작업된 전체 Graph가 모두 보여지도록 확대 또는 축소된다.
그래프 윈도우에서 두 요소(또는 그 이상)를 선택하면 정렬(Align) 및 분배(Distribute) 드롭다운 메뉴가 활성화되는데 이 메뉴를 통해 자동 레이아웃 작업을 할 수 있다.
바로 가기 및 키 바인딩
그래프 창을 이동 및 확대/축소하는 방법에는 두 가지 제어 체계가 있다. "Edit>Preferences>Visual Scripting"에서 제어 체계를 설정할 수 있다.기본 설정은 언리얼(Unreal)이다.
* Unreal : 마우스 휠 클릭 - 화면 좌우상하 이동 / 마우스 휠 회전 - 화면 확대 또는 축소
* Unity: 마우스 휠 클릭 - 화면 좌우상하 이동 / 마우스 휠 회전 - 상하이동 (여기서 화면 획대 축소는 Ctrl + 휠 회전)
참고: 트랙패드가 있고 두 손가락으로 그래프를 탐색하려면 해당 설정을 Unity로 변경하면 된다.
비주얼 스크립팅에는 두 가지 구성 옵션을 사용할 수 있다. "Edit(편집) > 프로젝트 설정(Project Settings) > 비주얼 스크립팅(Visual Scripting)"을 통해 다음의 두 가지 옵션에 구성 요소들을 업데이트(추가)할 수 있다.
* 타입 옵션(Type Options): 변수와 유닛들의 타입(type) 옵션. MonoBehaviour type은 기본적으로 포함되어져 있다. * 노드 라이브러리(Node Library): 유닛으로 사용하고자 하는 어셈블리(assemblies) 옵션. 기본적으로 모든 프로젝트와 유니티 어셈블리가 포함되어져 있다. 새 어셈블리를 추가하려면 "Add(+)"를 통해 추가한다.
각 옵션에는 그것이 무엇을 하는지 설명하는 툴팁이 있다. 옵션의 기능을 잘 모를 경우 기본값을 그대로 두고 나중에 변경할 수 있다.
참고: 일부 옵션은 재시작(restart)이 필요할 수 있다. 따라서 구성 변경 사항이 적용되지 않은 경우 편집기를 다시 시작한다.
역자 주) Type Options과 Node Library는 아직 이해하기 어렵습니다. 추후 숙련도가 올라가고 더 많은 기능의 사용이 필요해지게 될경우 자연스럽게 이해할 수 있게 됩니다.
비주얼 스크립팅은 코드를 쓰지 않고도 게임이나 응용 프로그램에 대한 로직을 만들 수 있게 해준다. 비주얼 스크립팅은 프로그래머뿐 아니라 기획자와 그래픽 디자이너 모두가 최종 로직을 설계하거나 프로토타입을 신속하게 만들수 있도록 하는 시각적 단위(비주얼 유닛, Visual Unit) 기반 그래프(Graph)들로 이루어져 있다. 비주얼 스크립팅은 프로그래머가 보다 고급 작업을 위해 사용하거나 다른 팀원이 사용할 수 있는 사용자 지정 유닛(커스텀 유닛, custom unit)을 만들수 있는 API도 제공한다.
비주얼 스크립팅은 함수, 연산자 또는 변수들을 그래픽 요소(graphical element)로 표현하고, 에지(여기서는 유닛들을 연결하는 선)를 사용하여 포트에 장치를 연결하는 방식의 개념에 기초하고 있다. 즉, 코드를 한 줄씩 써야 하는 대신, 모든 것을 시각적으로 작성한다.
설치(Installation) 2021.1 버전부터는 기본 패키지로 비주얼 스크립팅이 설치된다. 패키지 관리자에서 확인할 수 있다. 2019년형 LTS, 2020년형 LTS 등 이전 버전의 Unity는 Unity Asset Store를 통해 설치해야 한다.
비주얼 스크립팅 환경설정(Configuring visual scripting) 필요에 따라 "Edit > project setting"과 "Edit > preferences"에서 기본 설정을 변경할 수 있습니다.
화면 레이아웃 및 바로 가기 사용(Using Windows and shortcuts) 화면 레이아웃을 설정하고 바로 가기 키를 설정할 수도 있습니다.
비주얼 스크립팅 업데이트(Updating visual scripting) 비주얼 스크립팅 업데이트 하는 방법은 이곳에서 확인하세요.
시스템 요구 사항(System Requirements) 비주얼 스크립팅은 추가적인 다른 프로그램(external dependency)을 필요로 하지 않는다.
Visual Script는 크게 두가지로 분류된다. 이를 설명하기 이전에 Visual Script는 멋지게 구조화된 스크립트 작성이 용이하고 재사용성의 개념이 잘되어 있다는 장점이 있지만 단점은 초보자들이 초기에 개념정립을 하기에 헷갈린다는 것이다.
나름 이해를 돕기위해 아래와 같은 도표를 작성해 보았다.
* Machine은 프로그래밍 파일(C#, C++ 등등) 하나로 간주 하면 좋을 듯 하다.
* Script Machine은 기본적인 프로그래밍 코드들이 작성되는 파일이다.
* State Machine은 조금 상위 개념의 구조화된 코드들이 작성되는 파일로 생각하면 될 듯 하다. 게임을 예로 들었을 때, Player 캐릭터가 '기본 상태 일때', '공격을 받아서 1초간 무적일 상태' 그리고 '죽었을 때'에 따라서 다른 처리가 될텐데, 이렇게 Player 캐릭터의 상태를 정의하고 상태에 맞는 처리를 해줄 수 있도록 한다.
* 저장 방식(Embed, Graph)에서 Embed는 Script File들이 별도의 저장파일로존재하지 않고 Component에 삽입된다는 의미이다. 반면에 Graph는 별도의 Script File로 존재하고 Component가 이를 참조하는 것이다. 매우 국소적인 로컬 프로세스를 처리할 경우에 즉, 다른 Component에서 참조 혹은 재사용할 일이 전혀 없다면 Embed를 사용하면 된다. 또한 Embed는 특정 오브제트에 대해 커스터마이징(Customization)할 때도 유용하다. Embed와 Graph 상태는 서로 변경가능하다. 하지만 Embed에서 Graph로 변경할 경우 기존에 작성된 스크립트는 사라지게 된다. 반대로 Graph를 Embed로 변경할 경우 사라지지는 않는다.
* Unit : 아래 이미지에서 보이는 모든 그래프 하나하나가 Unit이다. Visual Script는 이러한 Unit들의 집합인 것이다. 마우스 우클릭을 하면 퍼지 파인더(Fuzzy Finder)창이 나타나며 이를 이용해 필요한 Unit을 선택하게 된다.
* Super Unit : 일련의 Unit들의 집합니다. 복합한 스크립트 구조를 단순화 시킬 수 있으며 Visual Script를 재사용할 수 있도록 해준다.
* Super State Unit : State Machine에서 사용하는 State Unit들의 집합이다.
위의 스크립트는 프레임(frame) 마다가 아닌 매초(per second)마다 Y축으로 1씩 이동하라는 의미입니다. 실행해보면 해당 오브젝트가 서서히 상승하는 동작을 확인할 수 있습니다. Per Second를 사용하지 않을 경우 Frame마다 1씩 이동하게 되는데 그렇게 되면 너무 빨라 눈으로 확인하기 어렵게 됩니다.
위에 있는 것은 어떤 동작하는 스크립트는 아닙니다. 다양한 형태를 보여드리기 위해 위와 같이 이미지를 구성하였습니다.
Visual Script에서는 Transform.Translate를 다양한 상황에서 쉽게 사용할 수 있도록 옵션처럼 여러 형태의 함수를 제공하고 있습니다.
좌측의 3개는 Vector3 좌표를 한 번에 변경할 때 사용하고, 우측의 3개는 X, Y, Z축 각각을 독립적으로 변경할 수 있도록 하고 있습니다.
또한 상대좌표를 World, Self, 그리고 다른 오브젝트를 기준으로 할 수도 있습니다.