> For the complete documentation index, see [llms.txt](https://ditoland-utplus.gitbook.io/ditoland/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://ditoland-utplus.gitbook.io/ditoland/guide-for-developers/guide-for-unity-developer.md).

# Guide For Unity Developer

![](/files/-MX9peyLK4Dk11V7-t8m)

이 문서는 C# 스크립트를 사용하는 유니티 게임 개발자가 디토랜드와 Lua 스크립트에 쉽게 적응할 수 \
있도록 하기 위해 제작되었어요.&#x20;

## 에디터&#x20;

![](/files/-MX9peyNjuWLKq5RD67z)

유니티에서는 하이어라키와 프로젝트뷰가 분리되어 있지만 디토랜드에서는 통합되어 있어요.

씬뷰와 게임뷰도 통합되어 있어요.&#x20;

## C#과 루아의 차이점&#x20;

| 내용        | C# Script                                     | Lua Script                              |              |                               |
| --------- | --------------------------------------------- | --------------------------------------- | ------------ | ----------------------------- |
| 코드 블록     | 코드 블록                                         | 청크                                      |              |                               |
| 한줄 주석     | //                                            | --                                      |              |                               |
| 여러줄 주석    | <p>/*로 시작해서</p><p>*/로 닫는다.</p>                | <p>--\[\[로 시작해서</p><p>]]--로 닫는다.</p>    |              |                               |
| 같지 않음 연산자 | !=                                            | \~=                                     |              |                               |
| 논리 연산자    | <p>&&</p><p>                                  |                                         | </p><p>!</p> | <p>and</p><p>or</p><p>not</p> |
| 널 값       | null                                          | nil                                     |              |                               |
| 거짓 값      | false                                         | false, nil                              |              |                               |
| 지역 선언     | private 또는 생략                                 | local                                   |              |                               |
| 전역 선언     | static                                        | 생략                                      |              |                               |
| 문자열 합치기   | +                                             | ..                                      |              |                               |
| 배열 인덱스    | 0부터 시작                                        | 1부터 시작                                  |              |                               |
| 배열 길이     | <p>arrName.Length 또는</p><p>listName.Count</p> | <p>#arrName</p><p>#listName</p>         |              |                               |
| 라인 끝맺음    | ;                                             | <p>기본적으로 미사용</p><p>한줄에 여러 내용 쓸때만 사용</p> |              |                               |

###

### 코드의 흐름&#x20;

C#에서는 선언된 함수나 변수를 위아래 구분없이 접근할 수 있지만, Lua에서는 **선언한 부분 아래**에서만 \
접근할 수 있습니다.&#x20;

{% tabs %}
{% tab title="C# Script" %}

```csharp
private void Awake()
{
    LevelUP(); //C#에서는 이렇게 접근할 수 있습니다. 
}

private void LevelUP()
{
    print("Level Up!"); 
}
```

{% endtab %}

{% tab title="Lua Script" %}

```lua
LevelUP() --루아에서는 이렇게 접근할 수 없습니다. 

local function LevelUP()
    print("Level Up!") 
end

LevelUP() --루아에서는 선언부의 다음 줄에서만 접근할 수 있습니다. 
```

{% endtab %}
{% endtabs %}

### 변수&#x20;

Lua에서 변수는 **자료형 표기없이** 선언합니다.&#x20;

{% tabs %}
{% tab title="C# Script" %}

```csharp
//지역 변수
private int Number = 1;
private float FloatNumber = 1.5;
private string Message = "HelloWorld";
private bool State = false;
private GameObject obj = null;
private List<int> list = new List<int>();

//public 변수 
public int Lv = 1;

//전역 변수
public static bool IsStartGame = true;
```

{% endtab %}

{% tab title="Lua Script" %}

```lua
--지역 변수는 local로 선언합니다. 
local Number = 1
local FloatNumber = 1.5
local Message = "HelloWorld"
local State = false
local obj = nil
local list = {}

--public 변수 
Script.Lv = 1

--전역 변수는 local을 생략하고 선언합니다.
IsStartGame = true
```

{% endtab %}
{% endtabs %}

### 함수&#x20;

Lua에서 함수는 인자/반환값 **자료형 표기없이** 선언합니다.&#x20;

{% tabs %}
{% tab title="C# Script" %}

```csharp
private void Awake()
{
    int sumValue = SomeFunc1(5, 10); //함수 호출 
}

//지역 함수
private int SomeFunc1(int num1, int num2)
{
    int result = num1 + num2;
    return result;
}

//public 함수 
public int SomeFunc2(int num1, int num2)
{
    int result = num1 + num2;
    return result;
}

//전역 함수 
public static int SomeFunc3(int num1, int num2)
{
    int result = num1 + num2;
    return result;
}
```

{% endtab %}

{% tab title="Lua Script" %}

```lua
--지역 함수
local function SomeFunc1(num1, num2)
    local result = num1 + num2
    return result
end

--public 함수
function Script:SomeFunc2(num1, num2)
    local result = num1 + num2
    return result
end

--전역 함수 
function SomeFunc3(num1, num2)
    local result = num1 + num2
    return result
end

local sumValue = SomeFunc1(5, 10) --함수 호출 
```

{% endtab %}
{% endtabs %}

### 리스트&#x20;

Lua에서 리스트는 **table**로 구현할 수 있습니다.&#x20;

{% tabs %}
{% tab title="C# Script" %}

```csharp
private void Sample()
{
    List<int> objList = new List<int>();
    
    objList.Add(1);
    objList.Add(2);
    objList.Add(3);
    
    for(int i = 0; i < objList.Count; i++)
    {
        print(objList[i]);
    }
}
```

{% endtab %}

{% tab title="Lua Script" %}

```lua
local function Sample()
    local objList = {}
    
    table.insert(objList, 1)
    table.insert(objList, 2)
    table.insert(objList, 3)
    
    for i = 1, #objList, 1 do
        print(objList[i])
    end
end
```

{% endtab %}
{% endtabs %}

### 제어문과 반복문&#x20;

C#과 Lua의 제어문과 반복문은 비슷한 부분이 많습니다.

하지만 Lua에는 **switch문**은 존재하지 않습니다.&#x20;

{% tabs %}
{% tab title="C# Script" %}

```csharp
//if문 
private string Animal = "Dog";
if(Animal == "Dog")
    print("Dog");
else if(Animal == "Cat")
    print("Cat");
else
    print("Other Animal"); 
    
//for문 
for(int i = 0; 5; i++)
{
    print(i);
    break;
}

//while문
while(true)
{
    print("Hello World");
    break;
}
```

{% endtab %}

{% tab title="Lua Script" %}

```lua
--if문 
local Animal = "Dog"
if Animal == "Dog" then
    print("Dog")
elseif Animal == "Cat" then
    print("Cat")
else
    print("Other Animal") 
end

--for문 
for i = 1, 5, 1 do
    print(i)
    break
end

--while문 
while true do
    print("Hello World")
    break
end
```

{% endtab %}
{% endtabs %}

Lua에서도 for문이나 while문을 **break**로 중단할 수 있습니다.

그러나 if문안에서 **continue**는 사용할 수 없습니다.

### goto문&#x20;

Lua에서도 goto문을 사용할 수 있습니다.&#x20;

{% tabs %}
{% tab title="C# Script" %}

```csharp
private void Awake()
{
    int Count = 0;

    case1:
    if (Count == 1)
    { 
        print("1");
        goto case3;
    }

    case2:
    print("2");
    if (Count == 0)
    {
        Count = Count + 1;
        goto case1;
    }

    case3:
    print("3");
}
```

{% endtab %}

{% tab title="Lua Script" %}

```lua
local Count = 0

::case1::
if Count == 1 then
    print("1")
    goto case3
end

::case2::
print("2")
if Count == 0 then
    Count = Count + 1
    goto case1
end

::case3::
print("3")
```

{% endtab %}
{% endtabs %}

## 유니티와 디토랜드의 차이점&#x20;

| 내용               | 유니티                              | 디토랜드                             |
| ---------------- | -------------------------------- | -------------------------------- |
| 오브젝트 편집 단축키      | <p>Q</p><p>W</p><p>E</p><p>R</p> | <p>1</p><p>2</p><p>3</p><p>4</p> |
| 테스트 플레이 단축키      | 컨트롤 + P                          | F5                               |
| 재사용 가능한 객체       | 프리팹                              | 팔레트                              |
| 좌표계 (가로, 세로, 높이) | <p>X</p><p>Z</p><p>Y</p>         | <p>Y</p><p>X</p><p>Z</p>         |

###

### 스크립트를 읽는 순서&#x20;

유니티에서는 Project Settings의 Script Execution Order에서 설정한 순서를 토대로 스크립트를 읽지만,\
디토랜드에서는 스크립트가 서버인지 클라이언트인지에 따라 읽는 방식이 결정됩니다.&#x20;

![](/files/-MX9vuhSqc5yv3BSGSb8)

서버 스크립트는 **ScriptServer**에 있는 스크립트를 제일 먼저 읽고, Workspace에 있는 스크립트는 순서대로\
읽습니다.&#x20;

클라이언트 스크립트는 **ScriptClient**에 있는 스크립트를 제일 먼저 읽고, Workspace에 있는 스크립트는 \
순서대로 읽습니다.&#x20;

동적으로 생성된 오브젝트의 스크립트들은 생성되는 시점에서 읽고, **모듈**은 require로 참조되는 시점에서\
읽습니다.&#x20;

### 계층 구조로 오브젝트 참조&#x20;

유니티에서는 Find 함수에서 문자열로 오브젝트의 계층을 탐색해서 접근할 수 있지만, 디토랜드에서는\
별도의 함수를 사용하지 않고 접근할 수 있습니다.&#x20;

{% tabs %}
{% tab title="C# Script" %}

```csharp
GameObject character = transform.Find("Map/GameObject/Character").gameObject;
```

{% endtab %}

{% tab title="Lua Script" %}

```lua
local character = Workspace.Character --계층간의 구분은 . 으로 표기합니다. 
```

{% endtab %}
{% endtabs %}

### 에디터 모드에서 변수 편집&#x20;

유니티는 스크립트에서 public으로 선언했거나 직렬화한 변수가 에디터 모드에서 표시되지만, \
디토랜드에서는 **프로퍼티창**의 **Script Parameters 항목**에서 추가할 수 있습니다.&#x20;

![](/files/-MX9zDmXxNc12px-yFJg)

Script Parameters에서 추가한 변수는 아래의 방법으로 접근할 수 있습니다. &#x20;

```lua
--추가한 변수가 Script 자신에게 있으면 
local MoveSpeed = Script.MoveSpeed
local JumpSpeed = Script.JumpSpeed

--추가한 변수가 오브젝트나 다른 스크립트에 있으면 
local Toy = Script.Parent
local Damage = Toy.Damage
local BulletSpeed = Toy.Bullet.BulletServerScript.BulletSpeed
```

### 다른 스크립트의 변수/함수 호출하기&#x20;

#### public으로 변수/함수 선언&#x20;

**같은 종류**(서버/클라)의 스크립트끼리만 접근할 수 있습니다.&#x20;

서버 스크립트1에서 선언된 public 변수/함수는 서버 스크립트2에서는 접근이 가능하지만, 클라이언트 \
스크립트에서는 접근할 수 없습니다.&#x20;

{% tabs %}
{% tab title="ServerScript1" %}

```lua
Script.Lv = 1 --public으로 선언된 변수

function Script:DoSomething() --public으로 선언된 함수 
    print("DoSomething")
end
```

{% endtab %}

{% tab title="ServerScript2" %}

```lua
wait(1) --ServerScript1 다음에 동작할 수 있도록 지연 처리 

Workspace.ServerScript1.Lv = 2 --public 변수 사용 
Workspace.ServerScript1:DoSomething() --public 함수 호출 
```

{% endtab %}
{% endtabs %}

#### 전역으로 선언된 변수/함수

**같은 종류**(서버/클라)의 스크립트끼리만 접근할 수 있습니다.&#x20;

서버 스크립트1에서 선언된 전역 변수/함수는 서버 스크립트2에서는 접근이 가능하지만, 클라이언트 \
스크립트에서는 접근할 수 없습니다.&#x20;

같은 종류의 스크립트(서버/클라)에서 전역 변수/함수는 **같은 이름**으로 선언할 수 없는 점에 주의하세요.&#x20;

{% tabs %}
{% tab title="ServerScript1" %}

```lua
WelcomText = "" --전역으로 선언된 변수

function PrintMessage(msg) --전역으로 선언된 함수 
    print(msg)
end
```

{% endtab %}

{% tab title="ServerScript2" %}

```lua
wait(1) --ServerScript1 다음에 동작할 수 있도록 지연 처리 

WelcomText = "Hello World!" --전역 변수 사용 
PrintMessage(WelcomText) --전역 함수 호출 
```

{% endtab %}
{% endtabs %}

#### 서버<->클라이언트 스크립트간 함수 호출&#x20;

서버 스크립트에서 클라이언트 스크립트의 함수를 호출하거나, 클라이언트 스크립트에서 서버 스크립트의  함수를 호출하려면 바인딩 이벤트를 이용해야 합니다.&#x20;

[이벤트 샘플](/ditoland/sample/event.md#undefined-1)의 BoradcastEvent, SendEventToServer, SendEventToClient를 참고하세요.

## 유니티의 함수를 디토랜드에서 사용하기

### 기본 이벤트 함수

{% tabs %}
{% tab title="Awake 및 Start" %}

```lua
--스크립트 제일 윗줄에서 처리하면 Awake나 Start처럼 동작합니다.  
print("HelloWorld!")
```

{% endtab %}

{% tab title="Update" %}

```lua
--바인딩 이벤트로 함수를 연결해서 구현할 수 있습니다. 
local timer = 0

local function Update(updateTime)
    timer = timer + updateTime
    print(timer)
end
Game.OnUpdateEvent:Connect(Update) 
```

{% endtab %}
{% endtabs %}

### 충돌 체크

{% tabs %}
{% tab title="Collision" %}

```lua
--스태틱메쉬나 콜라이더의 Collision 프로퍼티가 true면 동작합니다.
local Cube = Workspace.Cube

--충돌영역에 대상이 있을때 호출됩니다. 
--충돌영역 안에서 대상이 움직일때도 호출됩니다. 
local function Collision(self, target)
    if target == nil or not target:IsCharacter() then
        return
    end
    
    print("Target : " .. target.Name)
end
Cube.Collision.OnCollisionEvent:Connect(Collision)
```

{% endtab %}

{% tab title="Trigger" %}

```lua
--콜라이더의 Collision 프로퍼티가 false면 동작합니다. 
local BoxCollider = Workspace.BoxCollider

--충돌영역에 대상이 닿았을때 호출됩니다. 
local function EnterTrigger(self, target)
    if target == nil or not target:IsCharacter() then
        return
    end
    
    print("Enter Target : " .. target.Name)
end
Cube.Collision.OnBeginOverlapEvent:Connect(EnterTrigger)

--충돌영역 안에 대상이 있을때 계속 호출됩니다. 
local function UpdateTrigger(self, target)
    if target == nil or not target:IsCharacter() then
        return
    end
    
    print("Update Target : " .. target.Name)
end
Cube.Collision.OnOverlapUpdateEvent:Connect(UpdateTrigger)

--충돌영역에서 대상이 나갔을때 호출됩니다. 
local function ExitTrigger(self, target)
    if target == nil or not target:IsCharacter() then
        return
    end
    
    print("Exit Target : " .. target.Name)
end
Cube.Collision.OnEndOverlapEvent:Connect(ExitTrigger)
```

{% endtab %}
{% endtabs %}

### SetActive와 ActiveSelf

{% tabs %}
{% tab title="Server Script" %}

```lua
local Cube = Workspace.Cube

print(Cube.Enable) --ActiveSelf처럼 동작합니다. 

wait(0.5)
Cube.Enable = false --SetActive처럼 동작합니다. 

print(Cube.Enable)
```

{% endtab %}
{% endtabs %}

### Instantiate와 Destroy&#x20;

{% tabs %}
{% tab title="Server Script" %}

```lua
local Cube = Workspace.Cube

--Instantiate처럼 동작합니다. 
local newCube = Game:CreateSyncObject(Cube, Vector.new(300, 100, 100)) 
wait(2)

--Destroy처럼 동작합니다. 
Game:DeleteObject(newCube)
```

{% endtab %}
{% endtabs %}

### transform.GetChild

{% tabs %}
{% tab title="Server Script" %}

```lua
local ObjectList = Workspace:GetChildList() 

--#ObjectList는 transform.childCount처럼 동작합니다. 
for i = 1, #ObjectList, 1 do
    print(ObjectList[i].Name)
end
```

{% endtab %}
{% endtabs %}

### 더 많은 기능을 보려면&#x20;

[샘플 맵](/ditoland/sample.md)이나  [API Reference](/ditoland/api-reference.md)를 참고하세요.

## 컨텐츠 제작 강좌

{% content-ref url="/pages/-MVtaEEMjggOg6xaCW4B" %}
[Tutorial](/ditoland/tutorial.md)
{% endcontent-ref %}
