이 문서는 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에서는 선언한 부분 아래에서만
접근할 수 있습니다.
privatevoidAwake(){LevelUP(); //C#에서는 이렇게 접근할 수 있습니다. }privatevoidLevelUP(){print("Level Up!"); }
LevelUP() --루아에서는 이렇게 접근할 수 없습니다. localfunctionLevelUP()print("Level Up!") endLevelUP() --루아에서는 선언부의 다음 줄에서만 접근할 수 있습니다.
변수
Lua에서 변수는 자료형 표기없이 선언합니다.
//지역 변수privateint Number =1;privatefloat FloatNumber =1.5;privatestring Message ="HelloWorld";privatebool State =false;privateGameObject obj =null;privateList<int> list =newList<int>();//public 변수 publicint Lv =1;//전역 변수publicstaticbool IsStartGame =true;
--지역 변수는 local로 선언합니다. local Number =1local FloatNumber =1.5local Message ="HelloWorld"local State =falselocal obj =nillocal list = {}--public 변수 Script.Lv =1--전역 변수는 local을 생략하고 선언합니다.IsStartGame =true
함수
Lua에서 함수는 인자/반환값 자료형 표기없이 선언합니다.
privatevoidAwake(){int sumValue =SomeFunc1(5,10); //함수 호출 }//지역 함수privateintSomeFunc1(int num1,int num2){int result = num1 + num2;return result;}//public 함수 publicintSomeFunc2(int num1,int num2){int result = num1 + num2;return result;}//전역 함수 publicstaticintSomeFunc3(int num1,int num2){int result = num1 + num2;return result;}
--지역 함수localfunctionSomeFunc1(num1,num2)local result = num1 + num2return resultend--public 함수function Script:SomeFunc2(num1,num2)local result = num1 + num2return resultend--전역 함수 functionSomeFunc3(num1,num2)local result = num1 + num2return resultendlocal sumValue =SomeFunc1(5, 10) --함수 호출
리스트
Lua에서 리스트는 table로 구현할 수 있습니다.
privatevoidSample(){List<int> objList =newList<int>();objList.Add(1);objList.Add(2);objList.Add(3);for(int i =0; i <objList.Count; i++) {print(objList[i]); }}
유니티에서는 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.MoveSpeedlocal JumpSpeed = Script.JumpSpeed--추가한 변수가 오브젝트나 다른 스크립트에 있으면 local Toy = Script.Parentlocal Damage = Toy.Damagelocal 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 ="" --전역으로 선언된 변수functionPrintMessage(msg) --전역으로 선언된 함수 print(msg)end
wait(1) --ServerScript1 다음에 동작할 수 있도록 지연 처리 WelcomText ="Hello World!" --전역 변수 사용 PrintMessage(WelcomText) --전역 함수 호출
서버<->클라이언트 스크립트간 함수 호출
서버 스크립트에서 클라이언트 스크립트의 함수를 호출하거나, 클라이언트 스크립트에서 서버 스크립트의 함수를 호출하려면 바인딩 이벤트를 이용해야 합니다.
이벤트 샘플의 BoradcastEvent, SendEventToServer, SendEventToClient를 참고하세요.
유니티의 함수를 디토랜드에서 사용하기
기본 이벤트 함수
--스크립트 제일 윗줄에서 처리하면 Awake나 Start처럼 동작합니다. print("HelloWorld!")
--바인딩 이벤트로 함수를 연결해서 구현할 수 있습니다. local timer =0localfunctionUpdate(updateTime) timer = timer + updateTimeprint(timer)endGame.OnUpdateEvent:Connect(Update)
충돌 체크
--스태틱메쉬나 콜라이더의 Collision 프로퍼티가 true면 동작합니다.local Cube = Workspace.Cube--충돌영역에 대상이 있을때 호출됩니다. --충돌영역 안에서 대상이 움직일때도 호출됩니다. localfunctionCollision(self,target)if target ==nilornot target:IsCharacter() thenreturnendprint("Target : " .. target.Name)endCube.Collision.OnCollisionEvent:Connect(Collision)
--콜라이더의 Collision 프로퍼티가 false면 동작합니다. local BoxCollider = Workspace.BoxCollider--충돌영역에 대상이 닿았을때 호출됩니다. localfunctionEnterTrigger(self,target)if target ==nilornot target:IsCharacter() thenreturnendprint("Enter Target : " .. target.Name)endCube.Collision.OnBeginOverlapEvent:Connect(EnterTrigger)--충돌영역 안에 대상이 있을때 계속 호출됩니다. localfunctionUpdateTrigger(self,target)if target ==nilornot target:IsCharacter() thenreturnendprint("Update Target : " .. target.Name)endCube.Collision.OnOverlapUpdateEvent:Connect(UpdateTrigger)--충돌영역에서 대상이 나갔을때 호출됩니다. localfunctionExitTrigger(self,target)if target ==nilornot target:IsCharacter() thenreturnendprint("Exit Target : " .. target.Name)endCube.Collision.OnEndOverlapEvent:Connect(ExitTrigger)
SetActive와 ActiveSelf
local Cube = Workspace.Cubeprint(Cube.Enable) --ActiveSelf처럼 동작합니다. wait(0.5)Cube.Enable =false--SetActive처럼 동작합니다. print(Cube.Enable)
Instantiate와 Destroy
local Cube = Workspace.Cube--Instantiate처럼 동작합니다. local newCube = Game:CreateSyncObject(Cube, Vector.new(300, 100, 100)) wait(2)--Destroy처럼 동작합니다. Game:DeleteObject(newCube)
transform.GetChild
local ObjectList = Workspace:GetChildList() --#ObjectList는 transform.childCount처럼 동작합니다. for i =1, #ObjectList, 1doprint(ObjectList[i].Name)end