이 문서는 C# 스크립트를 사용하는 유니티 게임 개발자가 디토랜드와 Lua 스크립트에 쉽게 적응할 수
있도록 하기 위해 제작되었어요.
에디터
유니티에서는 하이어라키와 프로젝트뷰가 분리되어 있지만 디토랜드에서는 통합되어 있어요.
씬뷰와 게임뷰도 통합되어 있어요.
C#과 루아의 차이점
내용
C# Script
Lua Script
코드 블록
코드 블록
청크
한줄 주석
//
--
여러줄 주석
/*로 시작해서
*/로 닫는다.
--[[로 시작해서
]]--로 닫는다.
같지 않음 연산자
!=
~=
논리 연산자
&&
||
!
and
or
not
널 값
null
nil
거짓 값
false
false, nil
지역 선언
private 또는 생략
local
전역 선언
static
생략
문자열 합치기
+
..
배열 인덱스
0부터 시작
1부터 시작
배열 길이
arrName.Length 또는
listName.Count
#arrName
#listName
라인 끝맺음
;
기본적으로 미사용
한줄에 여러 내용 쓸때만 사용
코드의 흐름
C#에서는 선언된 함수나 변수를 위아래 구분없이 접근할 수 있지만, Lua에서는 선언한 부분 아래에서만
접근할 수 있습니다.
private void Awake()
{
LevelUP(); //C#에서는 이렇게 접근할 수 있습니다.
}
private void LevelUP()
{
print("Level Up!");
}
LevelUP() --루아에서는 이렇게 접근할 수 없습니다.
local function LevelUP()
print("Level Up!")
end
LevelUP() --루아에서는 선언부의 다음 줄에서만 접근할 수 있습니다.
변수
Lua에서 변수는 자료형 표기없이 선언합니다.
//지역 변수
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;
--지역 변수는 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
함수
Lua에서 함수는 인자/반환값 자료형 표기없이 선언합니다.
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;
}
--지역 함수
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) --함수 호출
리스트
Lua에서 리스트는 table로 구현할 수 있습니다.
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]);
}
}
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
--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
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")
유니티와 디토랜드의 차이점
내용
유니티
디토랜드
오브젝트 편집 단축키
Q
W
E
R
1
2
3
4
테스트 플레이 단축키
컨트롤 + P
F5
재사용 가능한 객체
프리팹
팔레트
좌표계 (가로, 세로, 높이)
X
Z
Y
Y
X
Z
스크립트를 읽는 순서
유니티에서는 Project Settings의 Script Execution Order에서 설정한 순서를 토대로 스크립트를 읽지만,
디토랜드에서는 스크립트가 서버인지 클라이언트인지에 따라 읽는 방식이 결정됩니다.
서버 스크립트는 ScriptServer에 있는 스크립트를 제일 먼저 읽고, Workspace에 있는 스크립트는 순서대로
읽습니다.
클라이언트 스크립트는 ScriptClient에 있는 스크립트를 제일 먼저 읽고, Workspace에 있는 스크립트는
순서대로 읽습니다.
동적으로 생성된 오브젝트의 스크립트들은 생성되는 시점에서 읽고, 모듈은 require로 참조되는 시점에서
읽습니다.
계층 구조로 오브젝트 참조
유니티에서는 Find 함수에서 문자열로 오브젝트의 계층을 탐색해서 접근할 수 있지만, 디토랜드에서는
별도의 함수를 사용하지 않고 접근할 수 있습니다.
GameObject character = transform.Find("Map/GameObject/Character").gameObject;
local character = Workspace.Character --계층간의 구분은 . 으로 표기합니다.
에디터 모드에서 변수 편집
유니티는 스크립트에서 public으로 선언했거나 직렬화한 변수가 에디터 모드에서 표시되지만,
디토랜드에서는 프로퍼티창의 Script Parameters 항목에서 추가할 수 있습니다.
Script Parameters에서 추가한 변수는 아래의 방법으로 접근할 수 있습니다.
--추가한 변수가 Script 자신에게 있으면
local MoveSpeed = Script.MoveSpeed
local JumpSpeed = Script.JumpSpeed
--추가한 변수가 오브젝트나 다른 스크립트에 있으면
local Toy = Script.Parent
local Damage = Toy.Damage
local BulletSpeed = Toy.Bullet.BulletServerScript.BulletSpeed
다른 스크립트의 변수/함수 호출하기
public으로 변수/함수 선언
같은 종류(서버/클라)의 스크립트끼리만 접근할 수 있습니다.
서버 스크립트1에서 선언된 public 변수/함수는 서버 스크립트2에서는 접근이 가능하지만, 클라이언트
스크립트에서는 접근할 수 없습니다.
Script.Lv = 1 --public으로 선언된 변수
function Script:DoSomething() --public으로 선언된 함수
print("DoSomething")
end
wait(1) --ServerScript1 다음에 동작할 수 있도록 지연 처리
Workspace.ServerScript1.Lv = 2 --public 변수 사용
Workspace.ServerScript1:DoSomething() --public 함수 호출
전역으로 선언된 변수/함수
같은 종류(서버/클라)의 스크립트끼리만 접근할 수 있습니다.
서버 스크립트1에서 선언된 전역 변수/함수는 서버 스크립트2에서는 접근이 가능하지만, 클라이언트
스크립트에서는 접근할 수 없습니다.
같은 종류의 스크립트(서버/클라)에서 전역 변수/함수는 같은 이름으로 선언할 수 없는 점에 주의하세요.
WelcomText = "" --전역으로 선언된 변수
function PrintMessage(msg) --전역으로 선언된 함수
print(msg)
end
wait(1) --ServerScript1 다음에 동작할 수 있도록 지연 처리
WelcomText = "Hello World!" --전역 변수 사용
PrintMessage(WelcomText) --전역 함수 호출
서버<->클라이언트 스크립트간 함수 호출
서버 스크립트에서 클라이언트 스크립트의 함수를 호출하거나, 클라이언트 스크립트에서 서버 스크립트의 함수를 호출하려면 바인딩 이벤트를 이용해야 합니다.
이벤트 샘플의 BoradcastEvent, SendEventToServer, SendEventToClient를 참고하세요.
유니티의 함수를 디토랜드에서 사용하기
기본 이벤트 함수
--스크립트 제일 윗줄에서 처리하면 Awake나 Start처럼 동작합니다.
print("HelloWorld!")
--바인딩 이벤트로 함수를 연결해서 구현할 수 있습니다.
local timer = 0
local function Update(updateTime)
timer = timer + updateTime
print(timer)
end
Game.OnUpdateEvent:Connect(Update)
충돌 체크
--스태틱메쉬나 콜라이더의 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)
--콜라이더의 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)