SlideShare ist ein Scribd-Unternehmen logo
1 von 89
넥슨 코리아 데브캣 스튜디오 드래곤하운드(프로젝트DH) 개발팀
전형규(henjeon@nexon.co.kr)
UE4에서 Lua 사용하기
SilvervineUE4Lua
NDC2019
• 현재, 드래곤하운드(프로젝트DH) 개발팀 엔지니어링 책임자
발표자 소개
• 참여 프로젝트
• GEARS(2001)
• 마비노기(2004), 마비노기 XBOX360, 마비노기2
• 링토스 세계여행(2014)
• 마비노기 듀얼(2015)
• 주요 관심사: UE4, 육아, 그리고 AI
• 자율 주행 엔지니어를 찾고 있습니다(농담아님).
발표 내용
• UE4 Blueprint Overview
• Blueprint의 장점과 단점 요약
• 관련 작업
• UE4 스크립트 플러그인 몇 가지 소개
• SilvervineUE4Lua 소개
• 개발 동기 및 특징 설명
발표 내용
• 드래곤하운드 사례 분석
• Lua를 적용한 작업 몇 가지를 예로 들어서 설명
• SilvervineUE4Lua 스크립팅 가이드
• 플러그인 사용 방법과 유용한 팁 소개
• SilvervineUE4Lua 설계 리뷰
• 스크립트 플러그인 제작 시 참고할 만한 경험을 공유
발표 자료 URL
• NDC 다시 보기
• http://ndcreplay.nexon.com/#
• 데브캣 스튜디오 슬라이드셰어
• https://www.slideshare.net/devcatpublications
• 올해부터 다른 곳에 올릴 가능성이 있음(구글 프리젠테이션, GitHub, …)
UE4 Blueprint Overview
UE4 Blueprint
• 노드 기반의 비주얼 스크립팅 시스템
• 엔지니어의 도움 없이 디자이너가 직접 기능을 구현할 수 있다.
http://api.unrealengine.com/images/Engine/Blueprints/GettingStarted/Level_Blueprint_Main.jpg
UE4 Blueprint의 장점
• 사용자 관점에서
• 배우기 쉽다.
• 사용법이 간단하다.
• 작업 진행 속도가 빠르다(프로토타이핑에 유리).
• 언어 관점에서
• 데이터의 흐름, 상태를 기술할 때 편하다
• [+] 셰이더(머티리얼) 프로그래밍
• [+] 애니메이션 상태 기계 프로그래밍
UE4 Blueprint의 단점
• 복잡도 관리가 어렵다
• 시간이 지나면... 괴물이 된다.
https://blueprintsfromhell.tumblr.com/image/180629779201
UE4 Blueprint의 단점
• 공동 작업이 어렵다.
• 바이너리 형식이라서 ‘브랜치 후 머지’ 방식을 쓸 수 없다.
• 배타적 체크아웃으로 인한 작업 병목이 심하다.
UE4 Blueprint의 단점
• 코드 리뷰가 어렵다
• 변경점을 찾기 불편하다.
UE4 Blueprint의 단점
• 디버깅이 어렵다
• 눈을 크게 뜨고 디버깅해야 한다.
UE4 Blueprint의 장점과 단점
• 쓰기 쉽다.
• 그러나 협업이 어렵다.
• 해결 방법은?
• [-] Blueprint를 쓰지 않는다.
• [+] 텍스트 스크립트 언어를 도입한다.
관련 작업
UE4 ScriptPlugin
• Epic의 순정 코드
• Engine/Plugins/ScriptPlugin
• 거의 모든 UE4 스크립트 플러그인의 레퍼런스로 사용됨
• UHT(Unreal Header Tool)로 Lua 바인딩 코드를 생성하는 코드가 아주 유용함
• 바로 쓸 수 있는 상태는 아님
• 2014년 이후 거의 변경되지 않음
• 문서도 없음
SkookumScript http://skookumscript.com/unreal/
• 자체 텍스트 스크립트 언어를 사용하는 UE4 플러그인
• 다양한 기능을 제공하는 강타입 언어를 사용함
• REPL(Read-Eval-Print-Loop) IDE를 지원
• 2019년 1월에 Epic에 인수됨
Unreal.js https://github.com/ncsoft/Unreal.js/
• Javascript를 통합
• NCSOFT에서 개발한 오픈 소스
• NDC2017 발표 참고(https://www.slideshare.net/crocuis/unrealjs-ue4-75499471)
https://github.com/ncsoft/Unreal.js/blob/master/doc/images/UnrealJs_JavascriptConsole.gif
UE4 Python Editor Script Plugin
• Epic의 순정 코드
• Engine/Plugins/Experimental/PythonScriptPlugin
• Python을 스크립트 언어로 사용 가능
• 문서화됨: http://api.unrealengine.com/KOR/Engine/Editor/ScriptingAndAutomation/Python/
• 주의: 에디터 플러그인
• 런타임 플러그인이 아니라서 게임 플레이 로직에 사용할 수 없음
• 개조하면 될 것 같기도 하다.
MonoUE https://mono-ue.github.io/
• C#을 지원!!
• 오픈 소스(https://github.com/mono-ue)
• 꿈 같다… 너무 좋다…
• 하지만…
• 개발 속도가 다소 늦다(1인 개발)
• 충분히 검증되지 않음
https://mono-ue.github.io/code.png
UnrealEnginePython https://github.com/20tab/UnrealEnginePython
• Python 통합 플러그인
• PythonScriptPlugin 과 달리 게임 플레이 제작을 위해서 개발된 플러그인
• 기능이 풍부함
• 문서화 잘 되어있음
• 엔진의 모든 API가 지원 안됨
• 바인딩 코드를 수동으로 작업해야 함
• 어려운 작업은 아니다(시간이 걸릴 뿐)
unreal.lua https://github.com/asqbtcupid/unreal.lua
• Lua 통합 플러그인
• UE4 ScriptPlugin을 기반으로 제작된 오픈소스 프로젝트
• Lua 플러그인을 구글링하면 가장 잘 검색되는 플러그인
sluaunreal https://github.com/Tencent/sluaunreal
• Lua 통합 플러그인
• 텐센트에서 개발함
• 자체 lua 프로파일러가 들어있다.
https://github.com/Tencent/sluaunreal/blob/master/profiler.png?raw=true
• 바인딩 코드 생성이 불편
• 내부 툴을 이용하는데 소스코드가 없음
SilvervineUE4Lua 소개
SUE4Lua 개발 동기
• Blueprint 지옥에서 탈출하고 싶었다
• 팀 규모가 커지자 문제가 심각해짐
• 한 여름 우유보다 잘 상하는 우리 팀의 Blueprint 코드들
• 체크아웃 전쟁… 끝없는 노드 리프레시… 선 정리…
• C++로 탈출을 시도했으나 만족스럽지 않았다
• 몇 개월에 걸쳐 Blueprint 코드를 C++로 포팅함(일명 BP2CPP)
• BP2CPP 과정에서 오류가 빈번하게 발생
• BP2CPP 작업자가 스트레스를 많이 받음
• 구현 속도 및 작업 난이도 증가
목표
• Blueprint 복잡도를 낮춘다.
• Blueprint를 안 쓸 수는 없다: 빠른 작업 이터레이션에 필수적
• Blueprint 사용을 최소화
• 협업이 쉬워야 한다.
• 공동 작업이 가능해야 한다.
• 브랜치, 머지, 코드 리뷰가 쉬워야 한다. 즉, git과 같은 버전 관리가 가능해야 한다.
• 디버깅이 쉬워야 한다.
달성 방법
• 텍스트 스크립트 언어를 도입
• 복잡한 Blueprint 그래프를 텍스트 스크립트로 표현
• 스크립트를 소스코드로 취급하고 UE4 에디터에서 편집하지 않는다.
• 스크립트 언어로 Lua를 선택
• 따.. 딱히 Lua를 좋아해서 선택한 것은 아님(강타입 언어를 선호함)
• 이전 프로젝트(마비노기 듀얼)에서 Lua를 사용했기 때문에 별 고민 없이 선택
• 충분한 시간과 자원이 있었다면 C#을 선택했을 것
자체 제작을 결심한 이유
• 다른 플러그인들은 스크립트 자유도가 너무 높다
• 스크립트로 파생 타입을 정의할 수 있으면 복잡도 관리가 어려울 것으로 판단
• 객체의 정의는 가급적 C++로 제한
• 문서화 및 코드 품질이 중요
• 영어까지는 괜찮은데 중국어를 할 줄 모름
• UE4 코딩 컨벤션을 지켰으면 함
SilvervineUE4Lua(SUE4Lua)
• 자체 개발한 UE4 Lua 통합 플러그인
• 2018년 6월 부터 개발
• 2019년 4월에 오픈 소스화(https://github.com/devcat-studio/SilvervineUE4Lua)
• ‘드래곤하운드’ 개발에 사용 중
SUE4Lua 특징
• 스크립트를 소스코드와 동등하게 취급
• Lua 파일을 uasset으로 저장하지 않는다.
• 프로젝트 Source 폴더에 스크립트를 둔다.
• Visual Studio나 Visual Studio Code로 편집한다.
SUE4Lua 특징
• Visual Studio Code로 디버깅
• VSCodeLuaDebug 사용(https://github.com/devcat-studio/VSCodeLuaDebug)
• 디버그 로그 리다이렉션
• 브레이크 포인트 및 데이터 검사 지원
SUE4Lua 특징
SUE4Lua 특징
• 함수를 Lua로 쉽게 구현할 수 있다
• 이 기능을 디스패치(Dispatch)라고 부르고 있음
• Blueprint함수와 C++ 함수 모두 디스패치할 수 있다.
드래곤하운드 사례 분석
드래곤하운드 소개
• 말을 타고 용을 사냥하는 액션 게임
• PC 플랫폼으로 출시 예정
사례: AI 커스터마이징
• AI 커스터마이징 데이터를 자체 텍스트 형식에서 Lua 테이블로 변경
• 수동으로 작성한 텍스트 라인 파서 코드를 제거할 수 있었다.
• 문법 오류 검사 및 문법 강조(Syntax Highlight) 기능을 공짜로 얻게 됨
{-- DecisionMaker
Class = "Normal",
Description = "기본피격반응",
bRandomSelection = false,
Weight = 2.0,
Evaluators =
{
{
bGenerateOrganStateActions = true,
},
{
bGenerateLegLimpHelper = true,
},
{
bGenerateStakeResponses = true,
},
{
bGenerateHitActionEffects = true,
Args = {
-- 함포 사격을 받으면 넘어짐
bArtilleryHitFall = true,
},
},
},-- end of evaluators
},
사례: 지스타2018 전투 미션 제작
• 5분 정도의 멀티 플레이 전투 데모
• Lua로 미션 스크립트를 구현함
• 약 3000라인 / 작성자 6명 / 358 커밋
내부 리뷰 자료 일부
ScenarioMission_GSTAR2018.lua 일부
--[[
Phase: 인트로 컷씬
]]
local function SpawnFlyingDragon_IntroCutScene(self)
if 0 < #self.LuaContext.TargetDragons then return end
SUE4Lua.Log("염화룡 등장")
if UDhFieldNetworkFunctionLibrary.IsServer(self) then
-- 염화룡 스폰
local SpawnSpots = {
self.LuaContext.WorldActors['M9Spawn’]
}
for _, Spot in pairs(SpawnSpots) do
local SpawnTM = Spot:GetActorTransform()
SpawnTM.Scale3D = UE4.Vector.new(4, 4, 4)
local Monster = SpawnFireDragonMiddle(self, SpawnTM, false, Spot, "")
table.insert(self.LuaContext.TargetDragons, Monster)
Monster:GetController():GetAIWrapperComponent():ToggleEnableTargeting(0)
end
ScenarioMission_GSTAR2018.lua 일부
--[[
Phase: 관문 보여주기 컷씬
]]
function Mission_GSTAR2018.EnterPhase_GateShowCutScene(self)
SUE4Lua.Log("EnterPhase_GateShowCutScene: "..self.LuaContext.Phases[self.LuaContext.Phase].DebugName)
SetGateClosed(self)
RefreshContextPlayers(self)
TeleportActorsToSpots(self, self.LuaContext.LocalPlayers, self.LuaContext.StartPosList_Gate)
if UDhFieldNetworkFunctionLibrary.IsClient(self) then
-- Town
self.LuaContext.WorldActors['GSTAR_Town']:SetActiveTown(false)
self.LuaContext.WorldActors['GSTAR_Town']:SetActiveTownMesh(false)
self.LuaContext.WorldActors['GSTAR_Town']:SetActiveInteriorProps(false)
self.LuaContext.WorldActors['GSTAR_Town']:SetActiveExteriorProps(false)
self.LuaContext.IsTownMove = false
StopLocalPlayer(self)
SetEnablePlayerInput(self, false)
self.LuaContext.WidgetGSTARMain:HideNPCTracker()
end
사례: 지스타2018 전투 미션 제작
• 엔지니어, 디자이너 모두 Lua를 사용
• 엔지니어는 VS2017이나 VS Code를 사용
• 디자이너는 VS Code를 사용
• 저장소는 git을 사용
ScenarioMission_GSTAR2018.lua 커밋 로그 일부
• 텍스트 스크립트의 효율성을 확인함
• Blueprint로 제작했다면… 체크아웃 병목이 심했을 것
• C++로 제작했다면… 작업 진행 속도가 느렸을 것
• 덕분에 일정에 늦지 않게 작업을 완료할 수 있었다.
사례: UMG 위젯 구현
• 복잡한 위젯 함수 구현을 Lua로 옮김
• SUE4Lua의 디스패치 기능을 사용
• UMG Blueprint는 이벤트 정의와 애니메이션 처리만 담당
• C++은 함수를 정의만 해둠
void UDhTownItemDetailWidgetCpp::ToggleSubStatExpand(FName StatName)
{
SUE4LUA_DISPATCH(GetLuaBridge(), StatName);
}
function TownStatGaugeWidget:ToggleExpand(Params)
if not self:IsValidWidget() then
return
end
self.bSubStatExpanded = not self.bSubStatExpanded
if self.bSubStatExpanded then
self.IMG_ExpandShrink:SetBrushFromTexture(self.ShrinkImageTexture)
self.IMG_ExpandShrink:SetColorAndOpacity(self.SubStatExpandColor)
self.BDR_SubStat:SetVisibility(ESlateVisibility.Visible)
UGameplayStatics.PlaySound2D(self:GetWorld(), self.OnExpandSound)
else
self.IMG_ExpandShrink:SetBrushFromTexture(self.ExpandImageTexture)
self.IMG_ExpandShrink:SetColorAndOpacity(self.SubStatShrinkColor)
self.BDR_SubStat:SetVisibility(ESlateVisibility.Collapsed)
UGameplayStatics.PlaySound2D(self:GetWorld(), self.OnShrinkSound)
end
end 코드 변환 샘플
local function RefreshItemState(self)
self.TXT_ItemState:SetText("")
self.TXT_Remark:SetText("")
self.TXT_Equipped:SetText("")
if self.TargetItem.EquippingCharacter then
local ShortEquippedText, _LongEquippedText = UDhTownFunctionLibrary.G
self.TXT_Equipped:SetText(ShortEquippedText)
self.TXT_Equipped:SetVisibility(ESlateVisibility.SelfHitTestInvisible
else
self.TXT_Equipped:SetVisibility(ESlateVisibility.Collapsed)
end
local ShortLevelRequirementText, LongLevelRequirementText = UDhTownFunctio
self.TXT_ItemState:SetText(ShortLevelRequirementText)
if self.TargetItem:NeedsMoreLevel(UDhSyncedPlayer.Get(self).CurrentCharact
self.TXT_Remark:SetText(LongLevelRequirementText)
self.TXT_ItemState:SetColorAndOpacity(self.NeedMoreLevelStateColor)
else
self.TXT_ItemState:SetColorAndOpacity(self.NotNeedMoreLevelStateColor
end
if self.TargetItem:IsBroken() then
self.BDR_Main:SetBrushColor(self.BrokenBorderColor)
local ShortBrokenText, LongBrokenText, RepairText = UDhTownFunctionLi
self.TXT_ItemState:SetText(ShortBrokenText..".")
self.TXT_ItemState:SetColorAndOpacity(self.BrokenStateColor)
self.TXT_Remark:SetText(LongBrokenText)
if self.ItemViewPurpose == EDhItemViewPurpose2.Equipment then
self.TXT_RightClick:SetText(RepairText)
self:PlayAnimation(self.Anim_ClickBlink)
end
end
end
코드 변환 샘플
void UDhTownTooltipItemWidgetCpp::RefreshItemSet()
{
if (!IsValidWidget())
{
return;
}
FDhCommonSheetTownModifierRowData ModifierRowData;
if (UDhCommonSheetContainerEx::Get()->FindModifierBySetID(TargetItem->SetID, ModifierRowData))
{
SetItemTextBlock->SetVisibility(ESlateVisibility::HitTestInvisible);
SetItemTextBlock->SetText(UDhTownFunctionLibrary::GetModifierFullName2(ModifierRowData));
if (TargetItem->IsBroken())
{
SetItemTextBlock->SetColorAndOpacity(BrokenItemSetColor);
}
else
{
SetItemTextBlock->SetColorAndOpacity(SetItemTextColor);
}
}
else
{
SetItemTextBlock->SetVisibility(ESlateVisibility::Collapsed);
}
}
local function RefreshItemSet(self)
local bModifierFound, ModifierRowData =
UDhSheetManager:GetDhSheetManager().CommonSheetEx:FindModifi
if bModifierFound then
self.TXT_SetItem:SetVisibility(ESlateVisibility.HitTest
self.TXT_SetItem:SetText(UDhTownFunctionLibrary.GetModi
if self.TargetItem:IsBroken() then
self.TXT_SetItem:SetColorAndOpacity(self.BrokenIte
else
self.TXT_SetItem:SetColorAndOpacity(self.SetItemTe
end
else
self.TXT_SetItem:SetVisibility(ESlateVisibility.Collaps
end
end 코드 변환 샘플
사례: UMG 위젯 구현
• Lua로 변경한 결과
• 위젯 코드 변경점을 쉽게 알 수 있었다.
• 컴파일 과정 없이 로직을 바로 변경할 수 있어서 작업 속도가 빨라졌다.
SilvervineUE4Lua 스크립팅 가이드
Lua 프로그래밍 가이드
• GitHub에 문서화
• SUE4Lua의 사용법과 스크립트 작성 가이드를 GitHub에 정리함
• https://github.com/devcat-studio/SilvervineUE4Lua/blob/master/README.md
Lua 코딩 컨벤션
• UE4 코딩 스타일을 따른다.
• UE4 코딩 스타일을 좋아하지 않지만 여러 스타일이 섞이는 것보다 낫다고 판단
function Sedan:OnMoveRight(Params)
--SUE4Lua.Log("Sedan:OnMoveRight() was called.")
local AxisValue = Params.AxisValue
-- Steering inupt
self.VehicleMovement:SetSteeringInput(AxisValue)
end
샘플 프로젝트: SUE4LuaSample
• Vehicle_BP 템플릿을 Lua로 옮긴 예제
SUE4Lua 팁: 기본 라이브러리의 활용
• 기본적인 Blueprint 라이브러리를 연결해 둠
• KismetSystemLibrary, 각종 수학 라이브러리, …
• ‘Find in Files’로 키워드를 검색하면 설명과 함께 샘플 코드를 찾을 수 있다.
SUE4Lua 팁: Main.lua
• VM의 시작 파일을 Main.lua로 설정하는 것을 추천
• 이렇게 하면 Main.lua가 가장 먼저 실행된다.
• 추가로 필요한 파일들을 Main.lua에서 ExecuteFile()로 실행하자.
• 자주 사용하는 타입을 전역변수로 설정해두면 편리하다.
-- Engine 타입 선언
ECollisionChannel = SUE4Lua.GetEnumTable("ECollisionChannel")
ECollisionResponse = SUE4Lua.GetEnumTable("ECollisionResponse")
ECollisionEnabled = SUE4Lua.GetEnumTable("ECollisionEnabled")
UObject = UE4.FindClass("Object")
UGameplayStatics = UE4.FindClass("GameplayStatics")
UWidgetBlueprintLibrary = UE4.FindClass("WidgetBlueprintLibrary")
UWidgetLayoutLibrary = UE4.FindClass("WidgetLayoutLibrary")
ALevelSequenceActor = UE4.FindClass("LevelSequenceActor")
SUE4Lua.ExecuteFile("SUE4Lua/Tests/AllTests.lua")
SUE4Lua 팁: Lua Hot Reloading
• SUE4Lua.OnFileModified() 를 활용
• 파일 변경이 감지되면 SUE4Lua.OnFileModified() 함수가 호출된다(개발 빌드 전용)
• 지정된 파일이 변경되면 다시 실행해서 핫 리로딩을 흉내 낼 수 있다.
• 디스패치 핸들러 파일은 플러그인에서 자동으로 다시 실행해 준다.
local AdditionalExecuteFilenames = {
"Game/Utility.lua",
"Game/UI.lua",
}
-- 개발전용: 파일 변경 처리
SUE4Lua.OnFileModifiled = function (Filename)
for _, ExecutedFilename in pairs(AdditionalExecuteFilenames) do
if Filename:lower() == ExecutedFilename:lower() then
SUE4Lua.Log("Re-Execute", Filename)
SUE4Lua.ExecuteFile(Filename)
break
end
end
end
SUE4Lua 팁: LuaContext
• Lua 상태를 저장하는 변수 이름은 ‘LuaContext’을 사용
• Blueprint나 C++ 클래스에 ‘LuaContext’라는 이름의 LuaValue를 추가하고,
• Lua 구현을 위해 필요한 변수들을 저 곳에 저장해 두면 좋다.
• Lua 값과 나머지 값을 격리할 수 있어서 코드 유지 보수에 유리하다.
self.LuaContext = {
ColumnMax = Params.Column,
CurCol = 0,
CurRow = 0,
}
SUE4Lua 팁: 대소문자 구별
• 함수, 속성 이름의 대소문자를 구별할 수 없다
• UProperty와 UFunction이 내부적으로 FName 해시 테이블에 저장되기 때문
• Lua에서 외부 속성, 함수에 접근할 때 주의할 것
-- self.IsInCar = State 와 결과가 같다
self.isincar = State
SUE4Lua 팁: 이벤트 핸들러의 디스패치
• 디스플레이 이름과 실제 이름이 다르므로 주의할 것
• 예를 들어, Tick 이벤트의 실제 이름은 ReceiveTick
• 이벤트를 추가하면 자동 생성되는 이름도 있다.
• 디스패치 노드의 FunctionName을 활용하면 좋다.
실제 이름은 InpActEvt_ResetVR_K2Node_InputActionEvent_0와 InpActEvt_ResetVR_K2Node_InputActionEvent_1
SUE4Lua 팁: Hard Reference
• SUE4Lua는 Lua 안에 UObject에 대한 강참조를 만들지 않는다
• 어셋 참조가 필요하다면 외부 클래스에 변수를 만들어서 저장하거나,
• 해당 객체를 반환하는 Blueprint 함수를 만들자.
-- Print vehicle speed
self:DrawText({
Text = Sedan.SpeedDisplayString,
TextColor = UE4.LinearColor.new(1.0, 1.0, 1.0, 1.0),
ScreenX = HUDXRatio * 805,
ScreenY = HUDYRatio * 455,
Font = self.Font,
Scale = HUDYRatio * 1.4,
})
SilvervineUE4Lua 설계 리뷰
지원하는 Lua Version
• Lua 5.3.4 사용
• Lua 5.1.5도 사용 가능할 것 같다. 다만 pairs()가 동작하지 않을 것이다.
• Lua JIT는 지원하지 않는다.
• 플러그인 내부에 Lua 소스코드가 포함됨
• 직접 Lua 코드를 구해서 연결할 필요 없다.
• luasocket 및 op_halt 패치가 적용되어 있다.
• https://github.com/devcat-studio/lua-5.3.4-op_halt
Lua 소스코드 관리
• 파일 로더 클래스를 세분화
• LocalFileLoader : git에 저장된 Lua 소스코드를 사용
• BundleFileLoader: 빌드머신에서 배포한 Lua 파일 번들(zip)을 사용
• 사용할 로더는 실행 환경마다 다름
• 엔지니어, 디자이너: LocalFileLoader
• 나머지 개발자: BundleFileLoader
• 배포 빌드: BundleFileLoader
• UE4 ScriptPlugin 모듈과 동일하게 구성되어 있다.
• SilvervineUE4Lua : 런타임 모듈
• SilvervineUE4LuaEditor : 에디터 모듈
• SilvervineUE4LuaCodeGen : 바인딩 코드를 생성하는 UHT 플러그인
Plugin Modules
"CanBeUsedWithUnrealHeaderTool" : true,
"Modules": [
{
"Name": "SilvervineUE4Lua",
"Type": "Runtime",
"LoadingPhase": "PreDefault"
},
{
"Name": "SilvervineUE4LuaEditor",
"Type": "Editor",
"LoadingPhase": "Default"
},
{
"Name" : "SilvervineUE4LuaCodeGen",
"Type" : "Program",
"LoadingPhase" : "PostConfigInit"
}
]
SilvervineUE4LuaEditor
• USUE4LuaVirtualMachineFactory
• VM 어셋을 생성하는 팩토리 클래스
• VM 어셋이 있으면 에디터에서 VM을 간단하게 지정할 수 있다.
SilvervineUE4LuaCodeGen
• UHT(Unreal Header Tool) 플러그인
• 프로젝트 모듈을 빌드하기 전에 먼저 실행된다.
• 스태틱 바인딩 코드와 함수 디폴트 파라메터 테이블을 생성한다.
1>------ Build started: Project: SUE4LuaSample, Configuration: DebugGame_Editor x64 ------
1>Performing full C++ include scan (building a new target)
1>Using 'git status' to determine working set for adaptive non-unity build (D:devgithubSilvervineUE4Lua).
1>Creating makefile for SUE4LuaSampleEditor (source directory changed)
1>Using Visual Studio 2017 14.16.27023 toolchain (C:Program Files (x86)Microsoft Visual Studio2017...
1>UnrealBuildTool : warning : Missing binary: D:devEpic GamesUE_4.21EngineSource$(ProjectDir)Plugins...
1>Building UnrealHeaderTool...
1>Performing full C++ include scan (building a new target)
1>Using 'git status' to determine working set for adaptive non-unity build (D:devgithubSilvervineUE4Lua).
1>Creating makefile for UnrealHeaderTool (ini files are newer than UBTMakefile)
1>Using Visual Studio 2017 14.16.27023 toolchain (C:Program Files (x86)Microsoft Visual Studio2017...
1>Parsing headers for SUE4LuaSampleEditor
1> Running UnrealHeaderTool "D:devgithubSilvervineUE4LuaSUE4LuaSample.uproject" "D:devgithubSilvervineUE4Lua...
1>Reflection code generated for SUE4LuaSampleEditor in 11.5833797 seconds
1>Target is up to date
1>Deploying SUE4LuaSampleEditor Win64 DebugGame...
1>Total build time: 59.99 seconds (NoActionsToExecute executor: 0.00 seconds)
1>Done building project "SUE4LuaSample.vcxproj".
========== Build: 1 succeeded, 0 failed, 0 up-to-date, 0 skipped ==========
SilvervineUE4LuaCodeGen
• 스태틱 바인딩 코드 생성
• IScriptGeneratorPluginInterface를 사용함
• 엔진 및 게임 클래스의 UFunction을 호출하는 함수를 생성
• 엔진 및 게임 클래스, 구조체의 UProperty 접근자 생성
• 두 개의 (거대한) inl 파일을 생성
• SilvervineUE4LuaCodeGen_Engine.g.inl : 약 80k 라인(3.9MB)
• SilvervineUE4LuaCodeGen_Game.g.inl : 게임 마다 다름
static int32 LuaCall_K2_AddRelativeLocation(lua_State* L, void* Self)
{
USceneComponent* CastedSelf = (USceneComponent*)Self;
FSUE4LuaFunctionStaticBindingContext Context(L, 2, TEXT("K2_AddRelativeLocation"));
FVector PARAM_DeltaLocation;
bool PARAM_bSweep;
FHitResult PARAM_SweepHitResult;
bool PARAM_bTeleport;
Context.Get("DeltaLocation", 0, PARAM_DeltaLocation, true);
Context.Get("bSweep", 1, PARAM_bSweep, true);
Context.Get("SweepHitResult", 2, PARAM_SweepHitResult, false);
Context.Get("bTeleport", 3, PARAM_bTeleport, true);
CastedSelf->K2_AddRelativeLocation(PARAM_DeltaLocation, PARAM_bSweep, PARAM_SweepHitResult, PARAM_bTeleport);
Context.ModifyUStructIfAble("SweepHitResult", 2, PARAM_SweepHitResult);
Context.Push("SweepHitResult", 2, PARAM_SweepHitResult);
return 1;
}
생성된 코드 샘플
생성된 코드 샘플
static int32 LuaGet_RelativeLocation(lua_State* L, void* Self)
{
UStaticMeshSocket* CastedSelf = (UStaticMeshSocket*)Self;
FSUE4LuaStack::Push(L, CastedSelf->RelativeLocation);
return 1;
}
static int32 LuaSet_RelativeLocation(lua_State* L, void* Self)
{
UStaticMeshSocket* CastedSelf = (UStaticMeshSocket*)Self;
CastedSelf->RelativeLocation = FSUE4LuaStack::To<FVector>(L, 3);
return 0;
}
static int32 LuaGet_RelativeRotation(lua_State* L, void* Self)
{
UStaticMeshSocket* CastedSelf = (UStaticMeshSocket*)Self;
FSUE4LuaStack::Push(L, CastedSelf->RelativeRotation);
return 1;
}
static int32 LuaSet_RelativeRotation(lua_State* L, void* Self)
{
UStaticMeshSocket* CastedSelf = (UStaticMeshSocket*)Self;
CastedSelf->RelativeRotation = FSUE4LuaStack::To<FRotator>(L, 3);
return 0;
}
SilvervineUE4LuaCodeGen
• 간단한 성능 비교
• 평균적으로 스태틱 바인딩 코드 패스가 리플렉션 코드 패스에 비해 빠르다.
• Scripts/Test/PerformanceTest.lua 참고
0 0.01 0.02 0.03 0.04 0.05 0.06
UObject* Getter
UObject* Setter
int32 Getter
int32 Setter
TestArg(…)
TestArg(Args)
Reflection Static Binding
SilvervineUE4LuaCodeGen
• 스태틱 바인딩 활성화가 기본값
• 실행 속도가 빠르기 때문에 기본값이 True
• 대신, 빌드 속도가 느리다(10~30초 추가)
• 원한다면 비활성화 할 수 있다(DefaultSilvervineUE4Lua.ini 수정)
[/Script/SilvervineUE4Lua.SUE4LuaSettings]
bEnableStaticBinding = False
SilvervineUE4LuaCodeGen
• 디폴트 파라메터 테이블
• 함수 호출 시 생략 가능한 파라메터의 기본값이 저장되어 있는 Lua 테이블을 생성한다.
• 함수 파라메터가 생략되면 Lua 테이블에서 기본값을 찾는다.
• 메타 정보가 에디터 빌드에서만 접근 가능하기 때문에 이와 같은 파일이 필요하다.
• 모듈 의존성을 제거하기 위해 C++이 아닌 Lua 코드로 생성한다.
--SpawnDecalAttached
DefaultParameters.GameplayStatics.SpawnDecalAttached = Class(DefaultParameterClass)
DefaultParameters.GameplayStatics.SpawnDecalAttached.AttachPointName = "None"
DefaultParameters.GameplayStatics.SpawnDecalAttached.LocationType = 0 --EAttachLocation::Type::KeepRelativeOffset
DefaultParameters.GameplayStatics.SpawnDecalAttached.LifeSpan = 0.000000
생성된 코드 샘플
SilvervineUE4Lua
• 예외 처리
• VM에 에러 핸들러가 구현되어 있음
• C++에서 Lua 함수를 호출할 때는 항상 lua_pcall() 사용
• Lua xpcall에서 사용 가능(SUE4Lua.EventHandler)
[Log] [Game/Main.lua:10] DispatchHandlerFactory: Sedan_C
[Log] [SUE4Lua/Framework/SUE4LuaBinding.lua:103] Dispatch Handler Registered: Sedan_C
Game/Sedan.lua
[Log] [Game/Sedan.lua:62] Sedan:ReceiveBeginPlay() was called.
[Log] [Game/Main.lua:10] DispatchHandlerFactory: CameraComponent
[Error] [Game/Sedan.lua:23] 'Activatee': is not a member of 'CameraComponent'.
[Error] [Game/Sedan.lua:23] FATAL: attempt to call a nil value (method 'Activatee')
[Log] [Game/Main.lua:10] DispatchHandlerFactory: VehicleHUD_C
[Log] [SUE4Lua/Framework/SUE4LuaBinding.lua:103] Dispatch Handler Registered: VehicleHUD_C
Game/VehicleHUD.lua
[Log] [FSUE4LuaVMContext::Dispose] Disposing '00000153CEEA5608'...
SilvervineUE4Lua
• UE4 Automation으로 유닛 테스트 실행
• 에디터 시작 시 자동으로 유닛테스트가 실행된다.
• 이후에는 세션 프론트엔드에서 실행할 수 있다.
SilvervineUE4Lua
• 디버깅
• VSCodeLuaDebug에 크게 의존하고 있다.
• 디버기 설정은 샘플 프로젝트의 Main.lua를 참고(SUE4LuaSample/Scripts/Main.lua)
• 파일 로딩 전에 설치된 브레이크포인트가 작동하지 않는 문제가 있다.
• 개발 빌드는 시작할 때 모든 Lua 파일을 미리 로딩해 둠
SilvervineUE4Lua
• Lua 객체를 C++에 저장하기
• LuaValue(USUE4LuaValue)를 통해 모든 Lua 값을 C++에 저장할 수 있다.
• 저장된 값은 LuaValue 파괴 전까지 gc되지 않는다.
• 저장된 값을 C++에서 사용하기
• boolean, integer, number, string 면 해당 값을 C++ 타입으로 반환
• 테이블 필드에도 접근 가능하다.
• 함수면 직접 호출할 수 있다.
• UObject(userdata)는 UObject*로 반환
• UStruct, TArray 등은 (아직) 지원 안함
SilvervineUE4Lua
• Lua 스택에 Push 할 수 있는 타입
• C++ 기본 타입: (u)int8/16/32/64, float/double, bool, char*, TChar*(wchar)
• UE4 스트링: FName, FString, FText
• Enum : C++ enum, enum class, UEnum
• UObject: UObject 및 모든 파생 클래스 -> userdata
• UStruct: FVector, FColor 등의 구조체는 미리 정의된 table, 나머지는 userdata
• 그리고 LuaValue: 저장된 Lua 값을 푸시
• TArray 등의 컨테이너 타입은 지원하지 않는다.
• 하지만 함수 파라메터로는 전달할 수 있다.
• UFunction이 UStruct의 파생 클래스이기 때문
SilvervineUE4Lua
• Lua에서 UProperty에 접근
• Lua에서 UObject, UStruct의 UProperty를 읽고 쓸 수 있다.
• UE4 리플렉션 시스템 및 스태틱 바인딩을 사용해서 구현
• 배열 및 컨테이너 지원
• 배열(int32[]), 컨테이너(TArray, TMap, TSet) 모두 지원한다.
• pairs()로 원소 순회 가능
SilvervineUE4Lua
• 기본 타입이 아닌 UProperty는 프록시 객체를 생성
• UObject, UStruct, 배열, TArray, TMap, TSet, Delegate가 해당
• userdata 형식의 프록시를 생성하고 weak 테이블에 캐싱함
• 프록시 객체는 소유자 UObject에 대한 약참조를 생성
• C++은 Lua 값에 대한 강참조 가능
• Lua는 C++에 대한 약참조만 가능
• Lua에서 강참조가 필요하다면 C++에 저장하면 된다.
SilvervineUE4Lua
• 배열과 컨테이너의 원소 반환
• 값을 반환 : 안전하지만 복사 비용이 발생
• 참조를 반환 : 위험하지만 비용 부담이 없다.
• 고정 크기 배열은 참조를 반환해도 안전
• 메모리가 재할당되지 않기 때문
• TArray 등은 참조를 반환하면 위험
• 내부 버퍼가 재할당될 수 있기 때문
• 재할당이 발생하지 않는 경우에만 참조 반환을 쓰자.
SilvervineUE4Lua
• Lua에서 클래스 함수 호출
• C++, Blueprint 함수 모두 호출할 수 있다.
• UE4 리플렉션 및 코드젠된 스태틱 바인딩 코드를 사용함
• 파라메터 전달 과정이 약간 복잡한데 이후 슬라이드에서 설명
• 코딩 편의를 위한 추가 기능
• UClass 타입은 편의상 대상 클래스의 UFunction을 바로 호출할 수 있다.
• 이름에 ‘K2_’ 접두사가 붙은 함수는 접두사 없는 이름으로 호출 가능
SilvervineUE4Lua
• Lua에서 UFunction이 아닌 클래스 함수 호출
• 예를 들면 UObject::IsA()
• 간단하게 바인딩 함수를 구현할 수 있다
• Public/Bindings/*.h 참고
//
// UObject에 대한 lua 바인딩
//
UCLASS(NotBlueprintType)
class SILVERVINEUE4LUA_API USUE4LuaObjectBinding : public USUE4LuaBinding
{
GENERATED_BODY()
public:
// Begin USUE4LuaBinding Interface
virtual UClass* GetBindingClass() const override;
// End USUE4LuaBinding Interface
UFUNCTION()
static FString LuaGetName(UObject* InSelf);
UFUNCTION()
static UClass* LuaGetClass(UObject* InSelf);
UFUNCTION()
static bool LuaIsA(UObject* InSelf, FName ClassName);
UFUNCTION()
static class UWorld* LuaGetWorld(UObject* InSelf);
};
function VehicleHUD:ReceiveDrawHUD(Params)
--SUE4Lua.Log("VehicleHUD:ReceiveDrawHUD() was called.")
local SizeX = Params.SizeX
local SizeY = Params.SizeY
local OwningPawn = self:GetOwningPawn()
local Sedan = (UE4.IsValid(OwningPawn) and OwningPawn:IsA('Sedan_C’)) …
SilvervineUE4Lua
• Lua에서 클래스 함수 호출 시 파라메터 및 반환값 전달
• (거의) 모든 타입을 지원: int32부터 TArray까지
• 파라메터는 테이블로 전달할 수 있다.
• 참조형 파라메터(출력값)도 지원(파라메터가 테이블 값이 갱신된다).
• 반환값 및 출력값은 순서대로 Lua 함수의 반환값으로 전달된다.
UFUNCTION()
int32 TestArgs(int32 InIntArg1, int32 InIntArg2, const int32& InIntArg3, int32& OutIntArg1, int32& OutIntArg2);
local Ret, OutIntArg1, OutIntArg2 = self:TestArgs({
InIntArg1 = 1,
InIntArg2 = 2,
InIntArg3 = 3,
OutIntArg1 = 4,
OutIntArg2 = nil,-- 생략 가능
})
SilvervineUE4Lua
• C++에서 Lua 함수 호출
• FSUE4LuaFunction 클래스를 사용하거나,
• 딜리게이트에 Lua 함수를 바인딩해서 호출할 수 있다.
• 딜리게이트 Lua 바인딩 구현이 약간 특이함
• 일단, 딜리게이트에 비어 있는 더미 함수를 바인딩 해둔다.
• ProcessEvent() 함수를 오버라이드한 후 그 안에서 Lua 함수를 호출
• 자세한 사항은 USUE4LuaValue::ProcessEvent() 구현을 참고
SilvervineUE4Lua
• Blueprint 디스패치
• 다른 스크립트 플러그인에는 없는 독특한 기능.
• Blueprint 스택을 읽어서 Lua 스택에 바로 푸시한다.
• 때문에 Blueprint 노드 파라메터를 디스패치 노드로 연결하는 작업이 필요없다.
function SomeClass:Func(Params)
local InParams1 = Params.InParam1
local InParams2 = Params.InParam2
local InParams3 = Params.InParam3
-- ...
Params.OutParam1 = ...
Params.OutParam2 = ...
end
SilvervineUE4Lua
• 네이티브(C++) 디스패치
• Blueprint 디스패치와 비슷한 기능
• 디스패치라고 부르고 있지만 사실 단순한 LuaFunction 호출이다.
• 리플렉션을 사용하지 않기 때문에 파라메터를 배열로 Lua에 전달한다.
// NativeDispatch()를 쉽게 사용하기 위한 매크로입니다.
//
// 사용 예:
//void UMyClass::Foo(int32 P1, int32 P2)
//{
// SUE4LUA_DISPATCH(LuaBridge, P1, P2);
//}
#define SUE4LUA_DISPATCH(LuaBridge, ...)
if( LuaBridge)
{
LuaBridge->NativeDispatch(this, ANSI_TO_TCHAR(__func__), __VA_ARGS__);
}
SilvervineUE4Lua
• 디스패치 핸들러 팩토리
• 클래스의 디스패치에 사용할 Lua 파일(디스패치 핸들러) 이름을 반환하는 함수를 말한다.
• Lua로 구현해서 VM에 설정한다.
SUE4Lua.SetDispatchHandlerFactory(function (CallerClass)
local ClassName = CallerClass:GetName()
SUE4Lua.Log("DispatchHandlerFactory: ", ClassName)
local Filenames = {
Sedan_C = "Game/Sedan.lua",
VehicleHUD_C = "Game/VehicleHUD.lua",
}
return Filenames[ClassName] or ""
end)
SilvervineUE4Lua
• 디스패치 핸들러 직접 호출
• 디스패치 핸들러 Lua 함수에서 다른 디스패치 핸들러의 Lua 함수를 바로 부를 수 있다.
• 구조적으로 마음에 들지 않지만 확실히 컨텐츠 구현할 때 유용하다...
• 최소한 함수 네이밍이라도 다르게 해야 할 것 같다(내부 논의 중)
function ClassA:FuncA(Params)
self.ObjectB:FuncB(1, 2, 3)
end
function ClassB:FuncB(P1, P2, P3)
SUE4Lua.Log(P1, P2, P3) -- 1 2 3
end
SilvervineUE4Lua
• 코루틴 및 멀티스레드
• 멀티스레드는 지원하지 않는다. 필요하다면 VM을 분리해서 사용.
• 최근에 코루틴을 지원하기 시작했다. 아직 불안정함.
SilvervineUE4Lua
• 알고 있는 문제들
• UE4 핫 리로딩 이후에 Lua에서 잘못된 함수를 호출하는 문제
• 딜리게이트에 시그니처가 맞지 않는 함수를 바인딩하면 호출할 때 크래시
• SUE4Lua 오류 메시지가 너무 불친절함
• 이후 작업
• 오류 메시지를 이해하기 쉽게 수정
• REPL(Read-Eval-Print-Loop) 지원
요약
SilvervineUE4Lua
• UE4 Blueprint의 단점을 보완하기 위해 Lua를 사용
• Lua와 같은 텍스트 스크립트 언어를 사용하여 Blueprint 복잡도를 낮췄다.
• 텍스트 자료형을 사용하여 협업에 어려움이 없도록 개선했다.
• 실제 업무에 적용하여 좋은 결과를 얻고 있다.
• 플러그인 소스코드 공개
• GitHub에 소스코드를 공개함. 많은 피드백 부탁 드립니다!
• 스크립트 플러그인을 제작할 때 도움이 될 만한 경험을 공유
참고자료
• 일반
• UE4 Blueprint 문서: http://api.unrealengine.com/KOR/Engine/Blueprints/GettingStarted/
• VPL Wiki: https://en.wikipedia.org/wiki/Visual_programming_language
• BlueprintsFromHell : https://blueprintsfromhell.tumblr.com/
• 스크립트 플러그인
• SkookumScript: http://skookumscript.com/unreal/
• UE4 Python Plugin : http://api.unrealengine.com/KOR/Engine/Editor/ScriptingAndAutomation/Python/
• MonoUE: https://mono-ue.github.io/
• UnrealEnginePython: https://github.com/20tab/UnrealEnginePython
• unreal.lua: https://github.com/asqbtcupid/unreal.lua
• sluaunreal: https://github.com/Tencent/sluaunreal
QnA

Weitere ähnliche Inhalte

Was ist angesagt?

MMOG Server-Side 충돌 및 이동처리 설계와 구현
MMOG Server-Side 충돌 및 이동처리 설계와 구현MMOG Server-Side 충돌 및 이동처리 설계와 구현
MMOG Server-Side 충돌 및 이동처리 설계와 구현YEONG-CHEON YOU
 
임태현, MMO 서버 개발 포스트 모템, NDC2012
임태현, MMO 서버 개발 포스트 모템, NDC2012임태현, MMO 서버 개발 포스트 모템, NDC2012
임태현, MMO 서버 개발 포스트 모템, NDC2012devCAT Studio, NEXON
 
게임프로젝트에 적용하는 GPGPU
게임프로젝트에 적용하는 GPGPU게임프로젝트에 적용하는 GPGPU
게임프로젝트에 적용하는 GPGPUYEONG-CHEON YOU
 
나만의 엔진 개발하기
나만의 엔진 개발하기나만의 엔진 개발하기
나만의 엔진 개발하기YEONG-CHEON YOU
 
이무림, Enum의 Boxing을 어찌할꼬? 편리하고 성능좋게 Enum 사용하기, NDC2019
이무림, Enum의 Boxing을 어찌할꼬? 편리하고 성능좋게 Enum 사용하기, NDC2019이무림, Enum의 Boxing을 어찌할꼬? 편리하고 성능좋게 Enum 사용하기, NDC2019
이무림, Enum의 Boxing을 어찌할꼬? 편리하고 성능좋게 Enum 사용하기, NDC2019devCAT Studio, NEXON
 
조정훈, 게임 프로그래머를 위한 클래스 설계, NDC2012
조정훈, 게임 프로그래머를 위한 클래스 설계, NDC2012조정훈, 게임 프로그래머를 위한 클래스 설계, NDC2012
조정훈, 게임 프로그래머를 위한 클래스 설계, NDC2012devCAT Studio, NEXON
 
[IGC 2017] 펄어비스 민경인 - Mmorpg를 위한 voxel 기반 네비게이션 라이브러리 개발기
[IGC 2017] 펄어비스 민경인 - Mmorpg를 위한 voxel 기반 네비게이션 라이브러리 개발기[IGC 2017] 펄어비스 민경인 - Mmorpg를 위한 voxel 기반 네비게이션 라이브러리 개발기
[IGC 2017] 펄어비스 민경인 - Mmorpg를 위한 voxel 기반 네비게이션 라이브러리 개발기강 민우
 
Akka.NET 으로 만드는 온라인 게임 서버 (NDC2016)
Akka.NET 으로 만드는 온라인 게임 서버 (NDC2016)Akka.NET 으로 만드는 온라인 게임 서버 (NDC2016)
Akka.NET 으로 만드는 온라인 게임 서버 (NDC2016)Esun Kim
 
NDC12_Lockless게임서버설계와구현
NDC12_Lockless게임서버설계와구현NDC12_Lockless게임서버설계와구현
NDC12_Lockless게임서버설계와구현noerror
 
홍성우, 게임 서버의 목차 - 시작부터 출시까지, NDC2019
홍성우, 게임 서버의 목차 - 시작부터 출시까지, NDC2019홍성우, 게임 서버의 목차 - 시작부터 출시까지, NDC2019
홍성우, 게임 서버의 목차 - 시작부터 출시까지, NDC2019devCAT Studio, NEXON
 
테라로 살펴본 MMORPG의 논타겟팅 시스템
테라로 살펴본 MMORPG의 논타겟팅 시스템테라로 살펴본 MMORPG의 논타겟팅 시스템
테라로 살펴본 MMORPG의 논타겟팅 시스템QooJuice
 
GameInstance에 대해서 알아보자
GameInstance에 대해서 알아보자GameInstance에 대해서 알아보자
GameInstance에 대해서 알아보자TonyCms
 
임태현, 게임 서버 디자인 가이드, NDC2013
임태현, 게임 서버 디자인 가이드, NDC2013임태현, 게임 서버 디자인 가이드, NDC2013
임태현, 게임 서버 디자인 가이드, NDC2013devCAT Studio, NEXON
 
UI아트 작업자를 위한 언리얼엔진4 UMG #1
UI아트 작업자를 위한 언리얼엔진4 UMG #1UI아트 작업자를 위한 언리얼엔진4 UMG #1
UI아트 작업자를 위한 언리얼엔진4 UMG #1Hong-Gi Joe
 
덤프 파일을 통한 사후 디버깅 실용 테크닉 NDC2012
덤프 파일을 통한 사후 디버깅 실용 테크닉 NDC2012덤프 파일을 통한 사후 디버깅 실용 테크닉 NDC2012
덤프 파일을 통한 사후 디버깅 실용 테크닉 NDC2012Esun Kim
 
NDC2017 언리얼엔진4 디버깅 101 - 게임 기획자, 프로그래머가 버그와 만났을 때 사용할 수 있는 지침들
NDC2017 언리얼엔진4 디버깅 101 - 게임 기획자, 프로그래머가 버그와 만났을 때 사용할 수 있는 지침들NDC2017 언리얼엔진4 디버깅 101 - 게임 기획자, 프로그래머가 버그와 만났을 때 사용할 수 있는 지침들
NDC2017 언리얼엔진4 디버깅 101 - 게임 기획자, 프로그래머가 버그와 만났을 때 사용할 수 있는 지침들영욱 오
 
프레임레이트 향상을 위한 공간분할 및 오브젝트 컬링 기법
프레임레이트 향상을 위한 공간분할 및 오브젝트 컬링 기법프레임레이트 향상을 위한 공간분할 및 오브젝트 컬링 기법
프레임레이트 향상을 위한 공간분할 및 오브젝트 컬링 기법YEONG-CHEON YOU
 
언리얼을 활용한 오브젝트 풀링
언리얼을 활용한 오브젝트 풀링언리얼을 활용한 오브젝트 풀링
언리얼을 활용한 오브젝트 풀링TonyCms
 
[150124 박민근] 모바일 게임 개발에서 루아 스크립트 활용하기
[150124 박민근] 모바일 게임 개발에서 루아 스크립트 활용하기[150124 박민근] 모바일 게임 개발에서 루아 스크립트 활용하기
[150124 박민근] 모바일 게임 개발에서 루아 스크립트 활용하기MinGeun Park
 
ndc 2017 어쩌다 신입 - 초보 게임 개발자 2년 간의 포스트모템
ndc 2017 어쩌다 신입 - 초보 게임 개발자 2년 간의 포스트모템ndc 2017 어쩌다 신입 - 초보 게임 개발자 2년 간의 포스트모템
ndc 2017 어쩌다 신입 - 초보 게임 개발자 2년 간의 포스트모템Chaeone Son
 

Was ist angesagt? (20)

MMOG Server-Side 충돌 및 이동처리 설계와 구현
MMOG Server-Side 충돌 및 이동처리 설계와 구현MMOG Server-Side 충돌 및 이동처리 설계와 구현
MMOG Server-Side 충돌 및 이동처리 설계와 구현
 
임태현, MMO 서버 개발 포스트 모템, NDC2012
임태현, MMO 서버 개발 포스트 모템, NDC2012임태현, MMO 서버 개발 포스트 모템, NDC2012
임태현, MMO 서버 개발 포스트 모템, NDC2012
 
게임프로젝트에 적용하는 GPGPU
게임프로젝트에 적용하는 GPGPU게임프로젝트에 적용하는 GPGPU
게임프로젝트에 적용하는 GPGPU
 
나만의 엔진 개발하기
나만의 엔진 개발하기나만의 엔진 개발하기
나만의 엔진 개발하기
 
이무림, Enum의 Boxing을 어찌할꼬? 편리하고 성능좋게 Enum 사용하기, NDC2019
이무림, Enum의 Boxing을 어찌할꼬? 편리하고 성능좋게 Enum 사용하기, NDC2019이무림, Enum의 Boxing을 어찌할꼬? 편리하고 성능좋게 Enum 사용하기, NDC2019
이무림, Enum의 Boxing을 어찌할꼬? 편리하고 성능좋게 Enum 사용하기, NDC2019
 
조정훈, 게임 프로그래머를 위한 클래스 설계, NDC2012
조정훈, 게임 프로그래머를 위한 클래스 설계, NDC2012조정훈, 게임 프로그래머를 위한 클래스 설계, NDC2012
조정훈, 게임 프로그래머를 위한 클래스 설계, NDC2012
 
[IGC 2017] 펄어비스 민경인 - Mmorpg를 위한 voxel 기반 네비게이션 라이브러리 개발기
[IGC 2017] 펄어비스 민경인 - Mmorpg를 위한 voxel 기반 네비게이션 라이브러리 개발기[IGC 2017] 펄어비스 민경인 - Mmorpg를 위한 voxel 기반 네비게이션 라이브러리 개발기
[IGC 2017] 펄어비스 민경인 - Mmorpg를 위한 voxel 기반 네비게이션 라이브러리 개발기
 
Akka.NET 으로 만드는 온라인 게임 서버 (NDC2016)
Akka.NET 으로 만드는 온라인 게임 서버 (NDC2016)Akka.NET 으로 만드는 온라인 게임 서버 (NDC2016)
Akka.NET 으로 만드는 온라인 게임 서버 (NDC2016)
 
NDC12_Lockless게임서버설계와구현
NDC12_Lockless게임서버설계와구현NDC12_Lockless게임서버설계와구현
NDC12_Lockless게임서버설계와구현
 
홍성우, 게임 서버의 목차 - 시작부터 출시까지, NDC2019
홍성우, 게임 서버의 목차 - 시작부터 출시까지, NDC2019홍성우, 게임 서버의 목차 - 시작부터 출시까지, NDC2019
홍성우, 게임 서버의 목차 - 시작부터 출시까지, NDC2019
 
테라로 살펴본 MMORPG의 논타겟팅 시스템
테라로 살펴본 MMORPG의 논타겟팅 시스템테라로 살펴본 MMORPG의 논타겟팅 시스템
테라로 살펴본 MMORPG의 논타겟팅 시스템
 
GameInstance에 대해서 알아보자
GameInstance에 대해서 알아보자GameInstance에 대해서 알아보자
GameInstance에 대해서 알아보자
 
임태현, 게임 서버 디자인 가이드, NDC2013
임태현, 게임 서버 디자인 가이드, NDC2013임태현, 게임 서버 디자인 가이드, NDC2013
임태현, 게임 서버 디자인 가이드, NDC2013
 
UI아트 작업자를 위한 언리얼엔진4 UMG #1
UI아트 작업자를 위한 언리얼엔진4 UMG #1UI아트 작업자를 위한 언리얼엔진4 UMG #1
UI아트 작업자를 위한 언리얼엔진4 UMG #1
 
덤프 파일을 통한 사후 디버깅 실용 테크닉 NDC2012
덤프 파일을 통한 사후 디버깅 실용 테크닉 NDC2012덤프 파일을 통한 사후 디버깅 실용 테크닉 NDC2012
덤프 파일을 통한 사후 디버깅 실용 테크닉 NDC2012
 
NDC2017 언리얼엔진4 디버깅 101 - 게임 기획자, 프로그래머가 버그와 만났을 때 사용할 수 있는 지침들
NDC2017 언리얼엔진4 디버깅 101 - 게임 기획자, 프로그래머가 버그와 만났을 때 사용할 수 있는 지침들NDC2017 언리얼엔진4 디버깅 101 - 게임 기획자, 프로그래머가 버그와 만났을 때 사용할 수 있는 지침들
NDC2017 언리얼엔진4 디버깅 101 - 게임 기획자, 프로그래머가 버그와 만났을 때 사용할 수 있는 지침들
 
프레임레이트 향상을 위한 공간분할 및 오브젝트 컬링 기법
프레임레이트 향상을 위한 공간분할 및 오브젝트 컬링 기법프레임레이트 향상을 위한 공간분할 및 오브젝트 컬링 기법
프레임레이트 향상을 위한 공간분할 및 오브젝트 컬링 기법
 
언리얼을 활용한 오브젝트 풀링
언리얼을 활용한 오브젝트 풀링언리얼을 활용한 오브젝트 풀링
언리얼을 활용한 오브젝트 풀링
 
[150124 박민근] 모바일 게임 개발에서 루아 스크립트 활용하기
[150124 박민근] 모바일 게임 개발에서 루아 스크립트 활용하기[150124 박민근] 모바일 게임 개발에서 루아 스크립트 활용하기
[150124 박민근] 모바일 게임 개발에서 루아 스크립트 활용하기
 
ndc 2017 어쩌다 신입 - 초보 게임 개발자 2년 간의 포스트모템
ndc 2017 어쩌다 신입 - 초보 게임 개발자 2년 간의 포스트모템ndc 2017 어쩌다 신입 - 초보 게임 개발자 2년 간의 포스트모템
ndc 2017 어쩌다 신입 - 초보 게임 개발자 2년 간의 포스트모템
 

Ähnlich wie 전형규, SilvervineUE4Lua: UE4에서 Lua 사용하기, NDC2019

객체지향프로그래밍 특강
객체지향프로그래밍 특강객체지향프로그래밍 특강
객체지향프로그래밍 특강uEngine Solutions
 
[야생의 땅: 듀랑고] 지형 관리 완전 자동화 - 생생한 AWS와 Docker 체험기
[야생의 땅: 듀랑고] 지형 관리 완전 자동화 - 생생한 AWS와 Docker 체험기[야생의 땅: 듀랑고] 지형 관리 완전 자동화 - 생생한 AWS와 Docker 체험기
[야생의 땅: 듀랑고] 지형 관리 완전 자동화 - 생생한 AWS와 Docker 체험기Sumin Byeon
 
청강대 특강 - 프로젝트 제대로 해보기
청강대 특강 - 프로젝트 제대로 해보기청강대 특강 - 프로젝트 제대로 해보기
청강대 특강 - 프로젝트 제대로 해보기Chris Ohk
 
차정민 (소프트웨어 엔지니어) 이력서 + 경력기술서
차정민 (소프트웨어 엔지니어) 이력서 + 경력기술서차정민 (소프트웨어 엔지니어) 이력서 + 경력기술서
차정민 (소프트웨어 엔지니어) 이력서 + 경력기술서Jeongmin Cha
 
[123] electron 김성훈
[123] electron 김성훈[123] electron 김성훈
[123] electron 김성훈NAVER D2
 
윤석주, 인하우스 웹 프레임워크 Jul8 제작기, NDC2018
윤석주, 인하우스 웹 프레임워크 Jul8 제작기, NDC2018윤석주, 인하우스 웹 프레임워크 Jul8 제작기, NDC2018
윤석주, 인하우스 웹 프레임워크 Jul8 제작기, NDC2018devCAT Studio, NEXON
 
오픈소스 컨트리뷰톤 2020 backend.ai 발표자료
오픈소스 컨트리뷰톤 2020 backend.ai 발표자료오픈소스 컨트리뷰톤 2020 backend.ai 발표자료
오픈소스 컨트리뷰톤 2020 backend.ai 발표자료지원 정
 
VSTS와 Azure를 이용한 팀 프로세스 관리
VSTS와 Azure를 이용한 팀 프로세스 관리VSTS와 Azure를 이용한 팀 프로세스 관리
VSTS와 Azure를 이용한 팀 프로세스 관리Gyuwon Yi
 
AngularJS In Production
AngularJS In ProductionAngularJS In Production
AngularJS In ProductionMooYeol Lee
 
생산성을 높여주는 iOS 개발 방법들.pdf
생산성을 높여주는 iOS 개발 방법들.pdf생산성을 높여주는 iOS 개발 방법들.pdf
생산성을 높여주는 iOS 개발 방법들.pdfssuserb942d2
 
[네이버오픈소스세미나] egjs-view360 개발기 - 김희재
[네이버오픈소스세미나] egjs-view360 개발기 - 김희재[네이버오픈소스세미나] egjs-view360 개발기 - 김희재
[네이버오픈소스세미나] egjs-view360 개발기 - 김희재NAVER D2
 
프로젝트 관리 및 지켜야 할 사항들
프로젝트 관리 및 지켜야 할 사항들프로젝트 관리 및 지켜야 할 사항들
프로젝트 관리 및 지켜야 할 사항들Lee Geonhee
 
H사 개인화 Approach
H사 개인화 ApproachH사 개인화 Approach
H사 개인화 Approachssuser9a50211
 
Docker 로 Linux 없이 Linux 환경에서 개발하기
Docker 로 Linux 없이 Linux 환경에서 개발하기Docker 로 Linux 없이 Linux 환경에서 개발하기
Docker 로 Linux 없이 Linux 환경에서 개발하기iFunFactory Inc.
 
Github 으로 학교 팀 프로젝트 하기
Github 으로 학교 팀 프로젝트 하기Github 으로 학교 팀 프로젝트 하기
Github 으로 학교 팀 프로젝트 하기nexusz99
 
경희대 해커 기술 세미나 - Git hub으로 학교 팀프로젝트 하기(조성수)
경희대 해커 기술 세미나 - Git hub으로 학교 팀프로젝트 하기(조성수)경희대 해커 기술 세미나 - Git hub으로 학교 팀프로젝트 하기(조성수)
경희대 해커 기술 세미나 - Git hub으로 학교 팀프로젝트 하기(조성수)NAVER D2
 
이승재, 강성훈, 내가 만든 언어의 개발환경을 Visual Studio Code로 빠르고 쉽게 구축하기 #1, NDC2017
이승재, 강성훈, 내가 만든 언어의 개발환경을 Visual Studio Code로 빠르고 쉽게 구축하기 #1, NDC2017이승재, 강성훈, 내가 만든 언어의 개발환경을 Visual Studio Code로 빠르고 쉽게 구축하기 #1, NDC2017
이승재, 강성훈, 내가 만든 언어의 개발환경을 Visual Studio Code로 빠르고 쉽게 구축하기 #1, NDC2017devCAT Studio, NEXON
 
LinqPad for DevOps
LinqPad for DevOpsLinqPad for DevOps
LinqPad for DevOps성수 이
 
웹 IDE 비교
웹 IDE 비교웹 IDE 비교
웹 IDE 비교Junyoung Lee
 

Ähnlich wie 전형규, SilvervineUE4Lua: UE4에서 Lua 사용하기, NDC2019 (20)

객체지향프로그래밍 특강
객체지향프로그래밍 특강객체지향프로그래밍 특강
객체지향프로그래밍 특강
 
[야생의 땅: 듀랑고] 지형 관리 완전 자동화 - 생생한 AWS와 Docker 체험기
[야생의 땅: 듀랑고] 지형 관리 완전 자동화 - 생생한 AWS와 Docker 체험기[야생의 땅: 듀랑고] 지형 관리 완전 자동화 - 생생한 AWS와 Docker 체험기
[야생의 땅: 듀랑고] 지형 관리 완전 자동화 - 생생한 AWS와 Docker 체험기
 
청강대 특강 - 프로젝트 제대로 해보기
청강대 특강 - 프로젝트 제대로 해보기청강대 특강 - 프로젝트 제대로 해보기
청강대 특강 - 프로젝트 제대로 해보기
 
차정민 (소프트웨어 엔지니어) 이력서 + 경력기술서
차정민 (소프트웨어 엔지니어) 이력서 + 경력기술서차정민 (소프트웨어 엔지니어) 이력서 + 경력기술서
차정민 (소프트웨어 엔지니어) 이력서 + 경력기술서
 
[123] electron 김성훈
[123] electron 김성훈[123] electron 김성훈
[123] electron 김성훈
 
윤석주, 인하우스 웹 프레임워크 Jul8 제작기, NDC2018
윤석주, 인하우스 웹 프레임워크 Jul8 제작기, NDC2018윤석주, 인하우스 웹 프레임워크 Jul8 제작기, NDC2018
윤석주, 인하우스 웹 프레임워크 Jul8 제작기, NDC2018
 
오픈소스 컨트리뷰톤 2020 backend.ai 발표자료
오픈소스 컨트리뷰톤 2020 backend.ai 발표자료오픈소스 컨트리뷰톤 2020 backend.ai 발표자료
오픈소스 컨트리뷰톤 2020 backend.ai 발표자료
 
VSTS와 Azure를 이용한 팀 프로세스 관리
VSTS와 Azure를 이용한 팀 프로세스 관리VSTS와 Azure를 이용한 팀 프로세스 관리
VSTS와 Azure를 이용한 팀 프로세스 관리
 
AngularJS In Production
AngularJS In ProductionAngularJS In Production
AngularJS In Production
 
생산성을 높여주는 iOS 개발 방법들.pdf
생산성을 높여주는 iOS 개발 방법들.pdf생산성을 높여주는 iOS 개발 방법들.pdf
생산성을 높여주는 iOS 개발 방법들.pdf
 
[네이버오픈소스세미나] egjs-view360 개발기 - 김희재
[네이버오픈소스세미나] egjs-view360 개발기 - 김희재[네이버오픈소스세미나] egjs-view360 개발기 - 김희재
[네이버오픈소스세미나] egjs-view360 개발기 - 김희재
 
프로젝트 관리 및 지켜야 할 사항들
프로젝트 관리 및 지켜야 할 사항들프로젝트 관리 및 지켜야 할 사항들
프로젝트 관리 및 지켜야 할 사항들
 
Approach
ApproachApproach
Approach
 
H사 개인화 Approach
H사 개인화 ApproachH사 개인화 Approach
H사 개인화 Approach
 
Docker 로 Linux 없이 Linux 환경에서 개발하기
Docker 로 Linux 없이 Linux 환경에서 개발하기Docker 로 Linux 없이 Linux 환경에서 개발하기
Docker 로 Linux 없이 Linux 환경에서 개발하기
 
Github 으로 학교 팀 프로젝트 하기
Github 으로 학교 팀 프로젝트 하기Github 으로 학교 팀 프로젝트 하기
Github 으로 학교 팀 프로젝트 하기
 
경희대 해커 기술 세미나 - Git hub으로 학교 팀프로젝트 하기(조성수)
경희대 해커 기술 세미나 - Git hub으로 학교 팀프로젝트 하기(조성수)경희대 해커 기술 세미나 - Git hub으로 학교 팀프로젝트 하기(조성수)
경희대 해커 기술 세미나 - Git hub으로 학교 팀프로젝트 하기(조성수)
 
이승재, 강성훈, 내가 만든 언어의 개발환경을 Visual Studio Code로 빠르고 쉽게 구축하기 #1, NDC2017
이승재, 강성훈, 내가 만든 언어의 개발환경을 Visual Studio Code로 빠르고 쉽게 구축하기 #1, NDC2017이승재, 강성훈, 내가 만든 언어의 개발환경을 Visual Studio Code로 빠르고 쉽게 구축하기 #1, NDC2017
이승재, 강성훈, 내가 만든 언어의 개발환경을 Visual Studio Code로 빠르고 쉽게 구축하기 #1, NDC2017
 
LinqPad for DevOps
LinqPad for DevOpsLinqPad for DevOps
LinqPad for DevOps
 
웹 IDE 비교
웹 IDE 비교웹 IDE 비교
웹 IDE 비교
 

Mehr von devCAT Studio, NEXON

김동건, 할머니가 들려주신 마비노기 개발 전설, NDC2019
김동건, 할머니가 들려주신 마비노기 개발 전설, NDC2019김동건, 할머니가 들려주신 마비노기 개발 전설, NDC2019
김동건, 할머니가 들려주신 마비노기 개발 전설, NDC2019devCAT Studio, NEXON
 
이봄, 스토리텔링으로 즐기는 콘서트 - 시나리오 기획자를 위한 TRPG의 세계, NDC2019
이봄, 스토리텔링으로 즐기는 콘서트 - 시나리오 기획자를 위한 TRPG의 세계, NDC2019이봄, 스토리텔링으로 즐기는 콘서트 - 시나리오 기획자를 위한 TRPG의 세계, NDC2019
이봄, 스토리텔링으로 즐기는 콘서트 - 시나리오 기획자를 위한 TRPG의 세계, NDC2019devCAT Studio, NEXON
 
유인호, <드래곤하운드>비주얼이펙트 연출, NDC2019
유인호, <드래곤하운드>비주얼이펙트 연출, NDC2019유인호, <드래곤하운드>비주얼이펙트 연출, NDC2019
유인호, <드래곤하운드>비주얼이펙트 연출, NDC2019devCAT Studio, NEXON
 
윤석주, 신입 게임 프로그래머가 되는 법 - 넥슨 채용 프로세스 단계별 분석, NDC2019
윤석주, 신입 게임 프로그래머가 되는 법 - 넥슨 채용 프로세스 단계별 분석, NDC2019윤석주, 신입 게임 프로그래머가 되는 법 - 넥슨 채용 프로세스 단계별 분석, NDC2019
윤석주, 신입 게임 프로그래머가 되는 법 - 넥슨 채용 프로세스 단계별 분석, NDC2019devCAT Studio, NEXON
 
이현기, <드래곤하운드> 새로움과의 새로운 싸움, NDC2019
이현기, <드래곤하운드> 새로움과의 새로운 싸움, NDC2019이현기, <드래곤하운드> 새로움과의 새로운 싸움, NDC2019
이현기, <드래곤하운드> 새로움과의 새로운 싸움, NDC2019devCAT Studio, NEXON
 
강성훈, 실버바인 대기열 서버 설계 리뷰, NDC2019
강성훈, 실버바인 대기열 서버 설계 리뷰, NDC2019강성훈, 실버바인 대기열 서버 설계 리뷰, NDC2019
강성훈, 실버바인 대기열 서버 설계 리뷰, NDC2019devCAT Studio, NEXON
 
김호용, 드래곤하운드 비주얼 개발기 - 프로젝트 킥오프부터 현재까지, 아트의 기둥 세우기, NDC2019
김호용, 드래곤하운드 비주얼 개발기 - 프로젝트 킥오프부터 현재까지, 아트의 기둥 세우기, NDC2019김호용, 드래곤하운드 비주얼 개발기 - 프로젝트 킥오프부터 현재까지, 아트의 기둥 세우기, NDC2019
김호용, 드래곤하운드 비주얼 개발기 - 프로젝트 킥오프부터 현재까지, 아트의 기둥 세우기, NDC2019devCAT Studio, NEXON
 
김혁, <드래곤 하운드>의 PBR과 레이트레이싱 렌더링 기법, NDC2019
김혁, <드래곤 하운드>의 PBR과 레이트레이싱 렌더링 기법, NDC2019김혁, <드래곤 하운드>의 PBR과 레이트레이싱 렌더링 기법, NDC2019
김혁, <드래곤 하운드>의 PBR과 레이트레이싱 렌더링 기법, NDC2019devCAT Studio, NEXON
 
홍성우, 게임 프로그래머는 어떻게 가르치나요?, NDC2018
홍성우, 게임 프로그래머는 어떻게 가르치나요?, NDC2018홍성우, 게임 프로그래머는 어떻게 가르치나요?, NDC2018
홍성우, 게임 프로그래머는 어떻게 가르치나요?, NDC2018devCAT Studio, NEXON
 
문석진, 프로젝트DH의 절차적 애니메이션 시스템 Ⅱ, NDC2018
문석진, 프로젝트DH의 절차적 애니메이션 시스템 Ⅱ, NDC2018문석진, 프로젝트DH의 절차적 애니메이션 시스템 Ⅱ, NDC2018
문석진, 프로젝트DH의 절차적 애니메이션 시스템 Ⅱ, NDC2018devCAT Studio, NEXON
 
이승재, 실버바인 서버엔진 2 설계 리뷰, NDC2018
이승재, 실버바인 서버엔진 2 설계 리뷰, NDC2018이승재, 실버바인 서버엔진 2 설계 리뷰, NDC2018
이승재, 실버바인 서버엔진 2 설계 리뷰, NDC2018devCAT Studio, NEXON
 
모광택, 모바일 TCG 게임의 라이브 서비스에 대한 경험 공유, NDC2018
모광택, 모바일 TCG 게임의 라이브 서비스에 대한 경험 공유, NDC2018모광택, 모바일 TCG 게임의 라이브 서비스에 대한 경험 공유, NDC2018
모광택, 모바일 TCG 게임의 라이브 서비스에 대한 경험 공유, NDC2018devCAT Studio, NEXON
 
전형규, 좋은 이름, 나쁜 이름, 이상한 이름, NDC2018
전형규, 좋은 이름, 나쁜 이름, 이상한 이름, NDC2018전형규, 좋은 이름, 나쁜 이름, 이상한 이름, NDC2018
전형규, 좋은 이름, 나쁜 이름, 이상한 이름, NDC2018devCAT Studio, NEXON
 
백승엽, 매직 더 개더링 20년간의 게임디자인 엿보기, NDC2012
백승엽, 매직 더 개더링 20년간의 게임디자인 엿보기, NDC2012백승엽, 매직 더 개더링 20년간의 게임디자인 엿보기, NDC2012
백승엽, 매직 더 개더링 20년간의 게임디자인 엿보기, NDC2012devCAT Studio, NEXON
 
백승엽, M2프로젝트의 애니메이션 로딩 전략, NDC2011
백승엽, M2프로젝트의 애니메이션 로딩 전략, NDC2011백승엽, M2프로젝트의 애니메이션 로딩 전략, NDC2011
백승엽, M2프로젝트의 애니메이션 로딩 전략, NDC2011devCAT Studio, NEXON
 
백승엽, M2프로젝트의 오류보고시스템, NDC2010
백승엽, M2프로젝트의 오류보고시스템, NDC2010백승엽, M2프로젝트의 오류보고시스템, NDC2010
백승엽, M2프로젝트의 오류보고시스템, NDC2010devCAT Studio, NEXON
 
홍성우, 내가 만든 언어로 게임 만들기, NDC2017
홍성우, 내가 만든 언어로 게임 만들기, NDC2017홍성우, 내가 만든 언어로 게임 만들기, NDC2017
홍성우, 내가 만든 언어로 게임 만들기, NDC2017devCAT Studio, NEXON
 
이승재, 강성훈, 내가 만든 언어의 개발환경을 Visual Studio Code로 빠르고 쉽게 구축하기 #2, NDC2017
이승재, 강성훈, 내가 만든 언어의 개발환경을 Visual Studio Code로 빠르고 쉽게 구축하기 #2, NDC2017이승재, 강성훈, 내가 만든 언어의 개발환경을 Visual Studio Code로 빠르고 쉽게 구축하기 #2, NDC2017
이승재, 강성훈, 내가 만든 언어의 개발환경을 Visual Studio Code로 빠르고 쉽게 구축하기 #2, NDC2017devCAT Studio, NEXON
 
노기태, 김대우, 모바일 게임 데이터에 입각한 머신러닝 예측 분석 도입 및 삽질 후기, NDC2017
노기태, 김대우, 모바일 게임 데이터에 입각한 머신러닝 예측 분석 도입 및 삽질 후기, NDC2017노기태, 김대우, 모바일 게임 데이터에 입각한 머신러닝 예측 분석 도입 및 삽질 후기, NDC2017
노기태, 김대우, 모바일 게임 데이터에 입각한 머신러닝 예측 분석 도입 및 삽질 후기, NDC2017devCAT Studio, NEXON
 
이승재, 일정대로 출시하기 왜 & 어떻게: 개발자를 위한 제작진행개론, NDC2017
이승재, 일정대로 출시하기 왜 & 어떻게: 개발자를 위한 제작진행개론, NDC2017이승재, 일정대로 출시하기 왜 & 어떻게: 개발자를 위한 제작진행개론, NDC2017
이승재, 일정대로 출시하기 왜 & 어떻게: 개발자를 위한 제작진행개론, NDC2017devCAT Studio, NEXON
 

Mehr von devCAT Studio, NEXON (20)

김동건, 할머니가 들려주신 마비노기 개발 전설, NDC2019
김동건, 할머니가 들려주신 마비노기 개발 전설, NDC2019김동건, 할머니가 들려주신 마비노기 개발 전설, NDC2019
김동건, 할머니가 들려주신 마비노기 개발 전설, NDC2019
 
이봄, 스토리텔링으로 즐기는 콘서트 - 시나리오 기획자를 위한 TRPG의 세계, NDC2019
이봄, 스토리텔링으로 즐기는 콘서트 - 시나리오 기획자를 위한 TRPG의 세계, NDC2019이봄, 스토리텔링으로 즐기는 콘서트 - 시나리오 기획자를 위한 TRPG의 세계, NDC2019
이봄, 스토리텔링으로 즐기는 콘서트 - 시나리오 기획자를 위한 TRPG의 세계, NDC2019
 
유인호, <드래곤하운드>비주얼이펙트 연출, NDC2019
유인호, <드래곤하운드>비주얼이펙트 연출, NDC2019유인호, <드래곤하운드>비주얼이펙트 연출, NDC2019
유인호, <드래곤하운드>비주얼이펙트 연출, NDC2019
 
윤석주, 신입 게임 프로그래머가 되는 법 - 넥슨 채용 프로세스 단계별 분석, NDC2019
윤석주, 신입 게임 프로그래머가 되는 법 - 넥슨 채용 프로세스 단계별 분석, NDC2019윤석주, 신입 게임 프로그래머가 되는 법 - 넥슨 채용 프로세스 단계별 분석, NDC2019
윤석주, 신입 게임 프로그래머가 되는 법 - 넥슨 채용 프로세스 단계별 분석, NDC2019
 
이현기, <드래곤하운드> 새로움과의 새로운 싸움, NDC2019
이현기, <드래곤하운드> 새로움과의 새로운 싸움, NDC2019이현기, <드래곤하운드> 새로움과의 새로운 싸움, NDC2019
이현기, <드래곤하운드> 새로움과의 새로운 싸움, NDC2019
 
강성훈, 실버바인 대기열 서버 설계 리뷰, NDC2019
강성훈, 실버바인 대기열 서버 설계 리뷰, NDC2019강성훈, 실버바인 대기열 서버 설계 리뷰, NDC2019
강성훈, 실버바인 대기열 서버 설계 리뷰, NDC2019
 
김호용, 드래곤하운드 비주얼 개발기 - 프로젝트 킥오프부터 현재까지, 아트의 기둥 세우기, NDC2019
김호용, 드래곤하운드 비주얼 개발기 - 프로젝트 킥오프부터 현재까지, 아트의 기둥 세우기, NDC2019김호용, 드래곤하운드 비주얼 개발기 - 프로젝트 킥오프부터 현재까지, 아트의 기둥 세우기, NDC2019
김호용, 드래곤하운드 비주얼 개발기 - 프로젝트 킥오프부터 현재까지, 아트의 기둥 세우기, NDC2019
 
김혁, <드래곤 하운드>의 PBR과 레이트레이싱 렌더링 기법, NDC2019
김혁, <드래곤 하운드>의 PBR과 레이트레이싱 렌더링 기법, NDC2019김혁, <드래곤 하운드>의 PBR과 레이트레이싱 렌더링 기법, NDC2019
김혁, <드래곤 하운드>의 PBR과 레이트레이싱 렌더링 기법, NDC2019
 
홍성우, 게임 프로그래머는 어떻게 가르치나요?, NDC2018
홍성우, 게임 프로그래머는 어떻게 가르치나요?, NDC2018홍성우, 게임 프로그래머는 어떻게 가르치나요?, NDC2018
홍성우, 게임 프로그래머는 어떻게 가르치나요?, NDC2018
 
문석진, 프로젝트DH의 절차적 애니메이션 시스템 Ⅱ, NDC2018
문석진, 프로젝트DH의 절차적 애니메이션 시스템 Ⅱ, NDC2018문석진, 프로젝트DH의 절차적 애니메이션 시스템 Ⅱ, NDC2018
문석진, 프로젝트DH의 절차적 애니메이션 시스템 Ⅱ, NDC2018
 
이승재, 실버바인 서버엔진 2 설계 리뷰, NDC2018
이승재, 실버바인 서버엔진 2 설계 리뷰, NDC2018이승재, 실버바인 서버엔진 2 설계 리뷰, NDC2018
이승재, 실버바인 서버엔진 2 설계 리뷰, NDC2018
 
모광택, 모바일 TCG 게임의 라이브 서비스에 대한 경험 공유, NDC2018
모광택, 모바일 TCG 게임의 라이브 서비스에 대한 경험 공유, NDC2018모광택, 모바일 TCG 게임의 라이브 서비스에 대한 경험 공유, NDC2018
모광택, 모바일 TCG 게임의 라이브 서비스에 대한 경험 공유, NDC2018
 
전형규, 좋은 이름, 나쁜 이름, 이상한 이름, NDC2018
전형규, 좋은 이름, 나쁜 이름, 이상한 이름, NDC2018전형규, 좋은 이름, 나쁜 이름, 이상한 이름, NDC2018
전형규, 좋은 이름, 나쁜 이름, 이상한 이름, NDC2018
 
백승엽, 매직 더 개더링 20년간의 게임디자인 엿보기, NDC2012
백승엽, 매직 더 개더링 20년간의 게임디자인 엿보기, NDC2012백승엽, 매직 더 개더링 20년간의 게임디자인 엿보기, NDC2012
백승엽, 매직 더 개더링 20년간의 게임디자인 엿보기, NDC2012
 
백승엽, M2프로젝트의 애니메이션 로딩 전략, NDC2011
백승엽, M2프로젝트의 애니메이션 로딩 전략, NDC2011백승엽, M2프로젝트의 애니메이션 로딩 전략, NDC2011
백승엽, M2프로젝트의 애니메이션 로딩 전략, NDC2011
 
백승엽, M2프로젝트의 오류보고시스템, NDC2010
백승엽, M2프로젝트의 오류보고시스템, NDC2010백승엽, M2프로젝트의 오류보고시스템, NDC2010
백승엽, M2프로젝트의 오류보고시스템, NDC2010
 
홍성우, 내가 만든 언어로 게임 만들기, NDC2017
홍성우, 내가 만든 언어로 게임 만들기, NDC2017홍성우, 내가 만든 언어로 게임 만들기, NDC2017
홍성우, 내가 만든 언어로 게임 만들기, NDC2017
 
이승재, 강성훈, 내가 만든 언어의 개발환경을 Visual Studio Code로 빠르고 쉽게 구축하기 #2, NDC2017
이승재, 강성훈, 내가 만든 언어의 개발환경을 Visual Studio Code로 빠르고 쉽게 구축하기 #2, NDC2017이승재, 강성훈, 내가 만든 언어의 개발환경을 Visual Studio Code로 빠르고 쉽게 구축하기 #2, NDC2017
이승재, 강성훈, 내가 만든 언어의 개발환경을 Visual Studio Code로 빠르고 쉽게 구축하기 #2, NDC2017
 
노기태, 김대우, 모바일 게임 데이터에 입각한 머신러닝 예측 분석 도입 및 삽질 후기, NDC2017
노기태, 김대우, 모바일 게임 데이터에 입각한 머신러닝 예측 분석 도입 및 삽질 후기, NDC2017노기태, 김대우, 모바일 게임 데이터에 입각한 머신러닝 예측 분석 도입 및 삽질 후기, NDC2017
노기태, 김대우, 모바일 게임 데이터에 입각한 머신러닝 예측 분석 도입 및 삽질 후기, NDC2017
 
이승재, 일정대로 출시하기 왜 & 어떻게: 개발자를 위한 제작진행개론, NDC2017
이승재, 일정대로 출시하기 왜 & 어떻게: 개발자를 위한 제작진행개론, NDC2017이승재, 일정대로 출시하기 왜 & 어떻게: 개발자를 위한 제작진행개론, NDC2017
이승재, 일정대로 출시하기 왜 & 어떻게: 개발자를 위한 제작진행개론, NDC2017
 

Kürzlich hochgeladen

Grid Layout (Kitworks Team Study 장현정 발표자료)
Grid Layout (Kitworks Team Study 장현정 발표자료)Grid Layout (Kitworks Team Study 장현정 발표자료)
Grid Layout (Kitworks Team Study 장현정 발표자료)Wonjun Hwang
 
Continual Active Learning for Efficient Adaptation of Machine LearningModels ...
Continual Active Learning for Efficient Adaptation of Machine LearningModels ...Continual Active Learning for Efficient Adaptation of Machine LearningModels ...
Continual Active Learning for Efficient Adaptation of Machine LearningModels ...Kim Daeun
 
A future that integrates LLMs and LAMs (Symposium)
A future that integrates LLMs and LAMs (Symposium)A future that integrates LLMs and LAMs (Symposium)
A future that integrates LLMs and LAMs (Symposium)Tae Young Lee
 
캐드앤그래픽스 2024년 5월호 목차
캐드앤그래픽스 2024년 5월호 목차캐드앤그래픽스 2024년 5월호 목차
캐드앤그래픽스 2024년 5월호 목차캐드앤그래픽스
 
도심 하늘에서 시속 200km로 비행할 수 있는 미래 항공 모빌리티 'S-A2'
도심 하늘에서 시속 200km로 비행할 수 있는 미래 항공 모빌리티 'S-A2'도심 하늘에서 시속 200km로 비행할 수 있는 미래 항공 모빌리티 'S-A2'
도심 하늘에서 시속 200km로 비행할 수 있는 미래 항공 모빌리티 'S-A2'Hyundai Motor Group
 
MOODv2 : Masked Image Modeling for Out-of-Distribution Detection
MOODv2 : Masked Image Modeling for Out-of-Distribution DetectionMOODv2 : Masked Image Modeling for Out-of-Distribution Detection
MOODv2 : Masked Image Modeling for Out-of-Distribution DetectionKim Daeun
 
[Terra] Terra Money: Stability and Adoption
[Terra] Terra Money: Stability and Adoption[Terra] Terra Money: Stability and Adoption
[Terra] Terra Money: Stability and AdoptionSeung-chan Baeg
 

Kürzlich hochgeladen (7)

Grid Layout (Kitworks Team Study 장현정 발표자료)
Grid Layout (Kitworks Team Study 장현정 발표자료)Grid Layout (Kitworks Team Study 장현정 발표자료)
Grid Layout (Kitworks Team Study 장현정 발표자료)
 
Continual Active Learning for Efficient Adaptation of Machine LearningModels ...
Continual Active Learning for Efficient Adaptation of Machine LearningModels ...Continual Active Learning for Efficient Adaptation of Machine LearningModels ...
Continual Active Learning for Efficient Adaptation of Machine LearningModels ...
 
A future that integrates LLMs and LAMs (Symposium)
A future that integrates LLMs and LAMs (Symposium)A future that integrates LLMs and LAMs (Symposium)
A future that integrates LLMs and LAMs (Symposium)
 
캐드앤그래픽스 2024년 5월호 목차
캐드앤그래픽스 2024년 5월호 목차캐드앤그래픽스 2024년 5월호 목차
캐드앤그래픽스 2024년 5월호 목차
 
도심 하늘에서 시속 200km로 비행할 수 있는 미래 항공 모빌리티 'S-A2'
도심 하늘에서 시속 200km로 비행할 수 있는 미래 항공 모빌리티 'S-A2'도심 하늘에서 시속 200km로 비행할 수 있는 미래 항공 모빌리티 'S-A2'
도심 하늘에서 시속 200km로 비행할 수 있는 미래 항공 모빌리티 'S-A2'
 
MOODv2 : Masked Image Modeling for Out-of-Distribution Detection
MOODv2 : Masked Image Modeling for Out-of-Distribution DetectionMOODv2 : Masked Image Modeling for Out-of-Distribution Detection
MOODv2 : Masked Image Modeling for Out-of-Distribution Detection
 
[Terra] Terra Money: Stability and Adoption
[Terra] Terra Money: Stability and Adoption[Terra] Terra Money: Stability and Adoption
[Terra] Terra Money: Stability and Adoption
 

전형규, SilvervineUE4Lua: UE4에서 Lua 사용하기, NDC2019

  • 1. 넥슨 코리아 데브캣 스튜디오 드래곤하운드(프로젝트DH) 개발팀 전형규(henjeon@nexon.co.kr) UE4에서 Lua 사용하기 SilvervineUE4Lua NDC2019
  • 2. • 현재, 드래곤하운드(프로젝트DH) 개발팀 엔지니어링 책임자 발표자 소개 • 참여 프로젝트 • GEARS(2001) • 마비노기(2004), 마비노기 XBOX360, 마비노기2 • 링토스 세계여행(2014) • 마비노기 듀얼(2015) • 주요 관심사: UE4, 육아, 그리고 AI • 자율 주행 엔지니어를 찾고 있습니다(농담아님).
  • 3. 발표 내용 • UE4 Blueprint Overview • Blueprint의 장점과 단점 요약 • 관련 작업 • UE4 스크립트 플러그인 몇 가지 소개 • SilvervineUE4Lua 소개 • 개발 동기 및 특징 설명
  • 4. 발표 내용 • 드래곤하운드 사례 분석 • Lua를 적용한 작업 몇 가지를 예로 들어서 설명 • SilvervineUE4Lua 스크립팅 가이드 • 플러그인 사용 방법과 유용한 팁 소개 • SilvervineUE4Lua 설계 리뷰 • 스크립트 플러그인 제작 시 참고할 만한 경험을 공유
  • 5. 발표 자료 URL • NDC 다시 보기 • http://ndcreplay.nexon.com/# • 데브캣 스튜디오 슬라이드셰어 • https://www.slideshare.net/devcatpublications • 올해부터 다른 곳에 올릴 가능성이 있음(구글 프리젠테이션, GitHub, …)
  • 7. UE4 Blueprint • 노드 기반의 비주얼 스크립팅 시스템 • 엔지니어의 도움 없이 디자이너가 직접 기능을 구현할 수 있다. http://api.unrealengine.com/images/Engine/Blueprints/GettingStarted/Level_Blueprint_Main.jpg
  • 8. UE4 Blueprint의 장점 • 사용자 관점에서 • 배우기 쉽다. • 사용법이 간단하다. • 작업 진행 속도가 빠르다(프로토타이핑에 유리). • 언어 관점에서 • 데이터의 흐름, 상태를 기술할 때 편하다 • [+] 셰이더(머티리얼) 프로그래밍 • [+] 애니메이션 상태 기계 프로그래밍
  • 9. UE4 Blueprint의 단점 • 복잡도 관리가 어렵다 • 시간이 지나면... 괴물이 된다. https://blueprintsfromhell.tumblr.com/image/180629779201
  • 10. UE4 Blueprint의 단점 • 공동 작업이 어렵다. • 바이너리 형식이라서 ‘브랜치 후 머지’ 방식을 쓸 수 없다. • 배타적 체크아웃으로 인한 작업 병목이 심하다.
  • 11. UE4 Blueprint의 단점 • 코드 리뷰가 어렵다 • 변경점을 찾기 불편하다.
  • 12. UE4 Blueprint의 단점 • 디버깅이 어렵다 • 눈을 크게 뜨고 디버깅해야 한다.
  • 13. UE4 Blueprint의 장점과 단점 • 쓰기 쉽다. • 그러나 협업이 어렵다. • 해결 방법은? • [-] Blueprint를 쓰지 않는다. • [+] 텍스트 스크립트 언어를 도입한다.
  • 15. UE4 ScriptPlugin • Epic의 순정 코드 • Engine/Plugins/ScriptPlugin • 거의 모든 UE4 스크립트 플러그인의 레퍼런스로 사용됨 • UHT(Unreal Header Tool)로 Lua 바인딩 코드를 생성하는 코드가 아주 유용함 • 바로 쓸 수 있는 상태는 아님 • 2014년 이후 거의 변경되지 않음 • 문서도 없음
  • 16. SkookumScript http://skookumscript.com/unreal/ • 자체 텍스트 스크립트 언어를 사용하는 UE4 플러그인 • 다양한 기능을 제공하는 강타입 언어를 사용함 • REPL(Read-Eval-Print-Loop) IDE를 지원 • 2019년 1월에 Epic에 인수됨
  • 17. Unreal.js https://github.com/ncsoft/Unreal.js/ • Javascript를 통합 • NCSOFT에서 개발한 오픈 소스 • NDC2017 발표 참고(https://www.slideshare.net/crocuis/unrealjs-ue4-75499471) https://github.com/ncsoft/Unreal.js/blob/master/doc/images/UnrealJs_JavascriptConsole.gif
  • 18. UE4 Python Editor Script Plugin • Epic의 순정 코드 • Engine/Plugins/Experimental/PythonScriptPlugin • Python을 스크립트 언어로 사용 가능 • 문서화됨: http://api.unrealengine.com/KOR/Engine/Editor/ScriptingAndAutomation/Python/ • 주의: 에디터 플러그인 • 런타임 플러그인이 아니라서 게임 플레이 로직에 사용할 수 없음 • 개조하면 될 것 같기도 하다.
  • 19. MonoUE https://mono-ue.github.io/ • C#을 지원!! • 오픈 소스(https://github.com/mono-ue) • 꿈 같다… 너무 좋다… • 하지만… • 개발 속도가 다소 늦다(1인 개발) • 충분히 검증되지 않음 https://mono-ue.github.io/code.png
  • 20. UnrealEnginePython https://github.com/20tab/UnrealEnginePython • Python 통합 플러그인 • PythonScriptPlugin 과 달리 게임 플레이 제작을 위해서 개발된 플러그인 • 기능이 풍부함 • 문서화 잘 되어있음 • 엔진의 모든 API가 지원 안됨 • 바인딩 코드를 수동으로 작업해야 함 • 어려운 작업은 아니다(시간이 걸릴 뿐)
  • 21. unreal.lua https://github.com/asqbtcupid/unreal.lua • Lua 통합 플러그인 • UE4 ScriptPlugin을 기반으로 제작된 오픈소스 프로젝트 • Lua 플러그인을 구글링하면 가장 잘 검색되는 플러그인
  • 22. sluaunreal https://github.com/Tencent/sluaunreal • Lua 통합 플러그인 • 텐센트에서 개발함 • 자체 lua 프로파일러가 들어있다. https://github.com/Tencent/sluaunreal/blob/master/profiler.png?raw=true • 바인딩 코드 생성이 불편 • 내부 툴을 이용하는데 소스코드가 없음
  • 24. SUE4Lua 개발 동기 • Blueprint 지옥에서 탈출하고 싶었다 • 팀 규모가 커지자 문제가 심각해짐 • 한 여름 우유보다 잘 상하는 우리 팀의 Blueprint 코드들 • 체크아웃 전쟁… 끝없는 노드 리프레시… 선 정리… • C++로 탈출을 시도했으나 만족스럽지 않았다 • 몇 개월에 걸쳐 Blueprint 코드를 C++로 포팅함(일명 BP2CPP) • BP2CPP 과정에서 오류가 빈번하게 발생 • BP2CPP 작업자가 스트레스를 많이 받음 • 구현 속도 및 작업 난이도 증가
  • 25. 목표 • Blueprint 복잡도를 낮춘다. • Blueprint를 안 쓸 수는 없다: 빠른 작업 이터레이션에 필수적 • Blueprint 사용을 최소화 • 협업이 쉬워야 한다. • 공동 작업이 가능해야 한다. • 브랜치, 머지, 코드 리뷰가 쉬워야 한다. 즉, git과 같은 버전 관리가 가능해야 한다. • 디버깅이 쉬워야 한다.
  • 26. 달성 방법 • 텍스트 스크립트 언어를 도입 • 복잡한 Blueprint 그래프를 텍스트 스크립트로 표현 • 스크립트를 소스코드로 취급하고 UE4 에디터에서 편집하지 않는다. • 스크립트 언어로 Lua를 선택 • 따.. 딱히 Lua를 좋아해서 선택한 것은 아님(강타입 언어를 선호함) • 이전 프로젝트(마비노기 듀얼)에서 Lua를 사용했기 때문에 별 고민 없이 선택 • 충분한 시간과 자원이 있었다면 C#을 선택했을 것
  • 27. 자체 제작을 결심한 이유 • 다른 플러그인들은 스크립트 자유도가 너무 높다 • 스크립트로 파생 타입을 정의할 수 있으면 복잡도 관리가 어려울 것으로 판단 • 객체의 정의는 가급적 C++로 제한 • 문서화 및 코드 품질이 중요 • 영어까지는 괜찮은데 중국어를 할 줄 모름 • UE4 코딩 컨벤션을 지켰으면 함
  • 28. SilvervineUE4Lua(SUE4Lua) • 자체 개발한 UE4 Lua 통합 플러그인 • 2018년 6월 부터 개발 • 2019년 4월에 오픈 소스화(https://github.com/devcat-studio/SilvervineUE4Lua) • ‘드래곤하운드’ 개발에 사용 중
  • 29. SUE4Lua 특징 • 스크립트를 소스코드와 동등하게 취급 • Lua 파일을 uasset으로 저장하지 않는다. • 프로젝트 Source 폴더에 스크립트를 둔다. • Visual Studio나 Visual Studio Code로 편집한다.
  • 30. SUE4Lua 특징 • Visual Studio Code로 디버깅 • VSCodeLuaDebug 사용(https://github.com/devcat-studio/VSCodeLuaDebug) • 디버그 로그 리다이렉션 • 브레이크 포인트 및 데이터 검사 지원
  • 32. SUE4Lua 특징 • 함수를 Lua로 쉽게 구현할 수 있다 • 이 기능을 디스패치(Dispatch)라고 부르고 있음 • Blueprint함수와 C++ 함수 모두 디스패치할 수 있다.
  • 34. 드래곤하운드 소개 • 말을 타고 용을 사냥하는 액션 게임 • PC 플랫폼으로 출시 예정
  • 35. 사례: AI 커스터마이징 • AI 커스터마이징 데이터를 자체 텍스트 형식에서 Lua 테이블로 변경 • 수동으로 작성한 텍스트 라인 파서 코드를 제거할 수 있었다. • 문법 오류 검사 및 문법 강조(Syntax Highlight) 기능을 공짜로 얻게 됨 {-- DecisionMaker Class = "Normal", Description = "기본피격반응", bRandomSelection = false, Weight = 2.0, Evaluators = { { bGenerateOrganStateActions = true, }, { bGenerateLegLimpHelper = true, }, { bGenerateStakeResponses = true, }, { bGenerateHitActionEffects = true, Args = { -- 함포 사격을 받으면 넘어짐 bArtilleryHitFall = true, }, }, },-- end of evaluators },
  • 36. 사례: 지스타2018 전투 미션 제작 • 5분 정도의 멀티 플레이 전투 데모 • Lua로 미션 스크립트를 구현함 • 약 3000라인 / 작성자 6명 / 358 커밋 내부 리뷰 자료 일부
  • 37. ScenarioMission_GSTAR2018.lua 일부 --[[ Phase: 인트로 컷씬 ]] local function SpawnFlyingDragon_IntroCutScene(self) if 0 < #self.LuaContext.TargetDragons then return end SUE4Lua.Log("염화룡 등장") if UDhFieldNetworkFunctionLibrary.IsServer(self) then -- 염화룡 스폰 local SpawnSpots = { self.LuaContext.WorldActors['M9Spawn’] } for _, Spot in pairs(SpawnSpots) do local SpawnTM = Spot:GetActorTransform() SpawnTM.Scale3D = UE4.Vector.new(4, 4, 4) local Monster = SpawnFireDragonMiddle(self, SpawnTM, false, Spot, "") table.insert(self.LuaContext.TargetDragons, Monster) Monster:GetController():GetAIWrapperComponent():ToggleEnableTargeting(0) end
  • 38. ScenarioMission_GSTAR2018.lua 일부 --[[ Phase: 관문 보여주기 컷씬 ]] function Mission_GSTAR2018.EnterPhase_GateShowCutScene(self) SUE4Lua.Log("EnterPhase_GateShowCutScene: "..self.LuaContext.Phases[self.LuaContext.Phase].DebugName) SetGateClosed(self) RefreshContextPlayers(self) TeleportActorsToSpots(self, self.LuaContext.LocalPlayers, self.LuaContext.StartPosList_Gate) if UDhFieldNetworkFunctionLibrary.IsClient(self) then -- Town self.LuaContext.WorldActors['GSTAR_Town']:SetActiveTown(false) self.LuaContext.WorldActors['GSTAR_Town']:SetActiveTownMesh(false) self.LuaContext.WorldActors['GSTAR_Town']:SetActiveInteriorProps(false) self.LuaContext.WorldActors['GSTAR_Town']:SetActiveExteriorProps(false) self.LuaContext.IsTownMove = false StopLocalPlayer(self) SetEnablePlayerInput(self, false) self.LuaContext.WidgetGSTARMain:HideNPCTracker() end
  • 39. 사례: 지스타2018 전투 미션 제작 • 엔지니어, 디자이너 모두 Lua를 사용 • 엔지니어는 VS2017이나 VS Code를 사용 • 디자이너는 VS Code를 사용 • 저장소는 git을 사용 ScenarioMission_GSTAR2018.lua 커밋 로그 일부 • 텍스트 스크립트의 효율성을 확인함 • Blueprint로 제작했다면… 체크아웃 병목이 심했을 것 • C++로 제작했다면… 작업 진행 속도가 느렸을 것 • 덕분에 일정에 늦지 않게 작업을 완료할 수 있었다.
  • 40. 사례: UMG 위젯 구현 • 복잡한 위젯 함수 구현을 Lua로 옮김 • SUE4Lua의 디스패치 기능을 사용 • UMG Blueprint는 이벤트 정의와 애니메이션 처리만 담당 • C++은 함수를 정의만 해둠 void UDhTownItemDetailWidgetCpp::ToggleSubStatExpand(FName StatName) { SUE4LUA_DISPATCH(GetLuaBridge(), StatName); }
  • 41. function TownStatGaugeWidget:ToggleExpand(Params) if not self:IsValidWidget() then return end self.bSubStatExpanded = not self.bSubStatExpanded if self.bSubStatExpanded then self.IMG_ExpandShrink:SetBrushFromTexture(self.ShrinkImageTexture) self.IMG_ExpandShrink:SetColorAndOpacity(self.SubStatExpandColor) self.BDR_SubStat:SetVisibility(ESlateVisibility.Visible) UGameplayStatics.PlaySound2D(self:GetWorld(), self.OnExpandSound) else self.IMG_ExpandShrink:SetBrushFromTexture(self.ExpandImageTexture) self.IMG_ExpandShrink:SetColorAndOpacity(self.SubStatShrinkColor) self.BDR_SubStat:SetVisibility(ESlateVisibility.Collapsed) UGameplayStatics.PlaySound2D(self:GetWorld(), self.OnShrinkSound) end end 코드 변환 샘플
  • 42. local function RefreshItemState(self) self.TXT_ItemState:SetText("") self.TXT_Remark:SetText("") self.TXT_Equipped:SetText("") if self.TargetItem.EquippingCharacter then local ShortEquippedText, _LongEquippedText = UDhTownFunctionLibrary.G self.TXT_Equipped:SetText(ShortEquippedText) self.TXT_Equipped:SetVisibility(ESlateVisibility.SelfHitTestInvisible else self.TXT_Equipped:SetVisibility(ESlateVisibility.Collapsed) end local ShortLevelRequirementText, LongLevelRequirementText = UDhTownFunctio self.TXT_ItemState:SetText(ShortLevelRequirementText) if self.TargetItem:NeedsMoreLevel(UDhSyncedPlayer.Get(self).CurrentCharact self.TXT_Remark:SetText(LongLevelRequirementText) self.TXT_ItemState:SetColorAndOpacity(self.NeedMoreLevelStateColor) else self.TXT_ItemState:SetColorAndOpacity(self.NotNeedMoreLevelStateColor end if self.TargetItem:IsBroken() then self.BDR_Main:SetBrushColor(self.BrokenBorderColor) local ShortBrokenText, LongBrokenText, RepairText = UDhTownFunctionLi self.TXT_ItemState:SetText(ShortBrokenText..".") self.TXT_ItemState:SetColorAndOpacity(self.BrokenStateColor) self.TXT_Remark:SetText(LongBrokenText) if self.ItemViewPurpose == EDhItemViewPurpose2.Equipment then self.TXT_RightClick:SetText(RepairText) self:PlayAnimation(self.Anim_ClickBlink) end end end 코드 변환 샘플
  • 43. void UDhTownTooltipItemWidgetCpp::RefreshItemSet() { if (!IsValidWidget()) { return; } FDhCommonSheetTownModifierRowData ModifierRowData; if (UDhCommonSheetContainerEx::Get()->FindModifierBySetID(TargetItem->SetID, ModifierRowData)) { SetItemTextBlock->SetVisibility(ESlateVisibility::HitTestInvisible); SetItemTextBlock->SetText(UDhTownFunctionLibrary::GetModifierFullName2(ModifierRowData)); if (TargetItem->IsBroken()) { SetItemTextBlock->SetColorAndOpacity(BrokenItemSetColor); } else { SetItemTextBlock->SetColorAndOpacity(SetItemTextColor); } } else { SetItemTextBlock->SetVisibility(ESlateVisibility::Collapsed); } } local function RefreshItemSet(self) local bModifierFound, ModifierRowData = UDhSheetManager:GetDhSheetManager().CommonSheetEx:FindModifi if bModifierFound then self.TXT_SetItem:SetVisibility(ESlateVisibility.HitTest self.TXT_SetItem:SetText(UDhTownFunctionLibrary.GetModi if self.TargetItem:IsBroken() then self.TXT_SetItem:SetColorAndOpacity(self.BrokenIte else self.TXT_SetItem:SetColorAndOpacity(self.SetItemTe end else self.TXT_SetItem:SetVisibility(ESlateVisibility.Collaps end end 코드 변환 샘플
  • 44. 사례: UMG 위젯 구현 • Lua로 변경한 결과 • 위젯 코드 변경점을 쉽게 알 수 있었다. • 컴파일 과정 없이 로직을 바로 변경할 수 있어서 작업 속도가 빨라졌다.
  • 46. Lua 프로그래밍 가이드 • GitHub에 문서화 • SUE4Lua의 사용법과 스크립트 작성 가이드를 GitHub에 정리함 • https://github.com/devcat-studio/SilvervineUE4Lua/blob/master/README.md
  • 47. Lua 코딩 컨벤션 • UE4 코딩 스타일을 따른다. • UE4 코딩 스타일을 좋아하지 않지만 여러 스타일이 섞이는 것보다 낫다고 판단 function Sedan:OnMoveRight(Params) --SUE4Lua.Log("Sedan:OnMoveRight() was called.") local AxisValue = Params.AxisValue -- Steering inupt self.VehicleMovement:SetSteeringInput(AxisValue) end
  • 48. 샘플 프로젝트: SUE4LuaSample • Vehicle_BP 템플릿을 Lua로 옮긴 예제
  • 49. SUE4Lua 팁: 기본 라이브러리의 활용 • 기본적인 Blueprint 라이브러리를 연결해 둠 • KismetSystemLibrary, 각종 수학 라이브러리, … • ‘Find in Files’로 키워드를 검색하면 설명과 함께 샘플 코드를 찾을 수 있다.
  • 50. SUE4Lua 팁: Main.lua • VM의 시작 파일을 Main.lua로 설정하는 것을 추천 • 이렇게 하면 Main.lua가 가장 먼저 실행된다. • 추가로 필요한 파일들을 Main.lua에서 ExecuteFile()로 실행하자. • 자주 사용하는 타입을 전역변수로 설정해두면 편리하다. -- Engine 타입 선언 ECollisionChannel = SUE4Lua.GetEnumTable("ECollisionChannel") ECollisionResponse = SUE4Lua.GetEnumTable("ECollisionResponse") ECollisionEnabled = SUE4Lua.GetEnumTable("ECollisionEnabled") UObject = UE4.FindClass("Object") UGameplayStatics = UE4.FindClass("GameplayStatics") UWidgetBlueprintLibrary = UE4.FindClass("WidgetBlueprintLibrary") UWidgetLayoutLibrary = UE4.FindClass("WidgetLayoutLibrary") ALevelSequenceActor = UE4.FindClass("LevelSequenceActor") SUE4Lua.ExecuteFile("SUE4Lua/Tests/AllTests.lua")
  • 51. SUE4Lua 팁: Lua Hot Reloading • SUE4Lua.OnFileModified() 를 활용 • 파일 변경이 감지되면 SUE4Lua.OnFileModified() 함수가 호출된다(개발 빌드 전용) • 지정된 파일이 변경되면 다시 실행해서 핫 리로딩을 흉내 낼 수 있다. • 디스패치 핸들러 파일은 플러그인에서 자동으로 다시 실행해 준다. local AdditionalExecuteFilenames = { "Game/Utility.lua", "Game/UI.lua", } -- 개발전용: 파일 변경 처리 SUE4Lua.OnFileModifiled = function (Filename) for _, ExecutedFilename in pairs(AdditionalExecuteFilenames) do if Filename:lower() == ExecutedFilename:lower() then SUE4Lua.Log("Re-Execute", Filename) SUE4Lua.ExecuteFile(Filename) break end end end
  • 52. SUE4Lua 팁: LuaContext • Lua 상태를 저장하는 변수 이름은 ‘LuaContext’을 사용 • Blueprint나 C++ 클래스에 ‘LuaContext’라는 이름의 LuaValue를 추가하고, • Lua 구현을 위해 필요한 변수들을 저 곳에 저장해 두면 좋다. • Lua 값과 나머지 값을 격리할 수 있어서 코드 유지 보수에 유리하다. self.LuaContext = { ColumnMax = Params.Column, CurCol = 0, CurRow = 0, }
  • 53. SUE4Lua 팁: 대소문자 구별 • 함수, 속성 이름의 대소문자를 구별할 수 없다 • UProperty와 UFunction이 내부적으로 FName 해시 테이블에 저장되기 때문 • Lua에서 외부 속성, 함수에 접근할 때 주의할 것 -- self.IsInCar = State 와 결과가 같다 self.isincar = State
  • 54. SUE4Lua 팁: 이벤트 핸들러의 디스패치 • 디스플레이 이름과 실제 이름이 다르므로 주의할 것 • 예를 들어, Tick 이벤트의 실제 이름은 ReceiveTick • 이벤트를 추가하면 자동 생성되는 이름도 있다. • 디스패치 노드의 FunctionName을 활용하면 좋다. 실제 이름은 InpActEvt_ResetVR_K2Node_InputActionEvent_0와 InpActEvt_ResetVR_K2Node_InputActionEvent_1
  • 55. SUE4Lua 팁: Hard Reference • SUE4Lua는 Lua 안에 UObject에 대한 강참조를 만들지 않는다 • 어셋 참조가 필요하다면 외부 클래스에 변수를 만들어서 저장하거나, • 해당 객체를 반환하는 Blueprint 함수를 만들자. -- Print vehicle speed self:DrawText({ Text = Sedan.SpeedDisplayString, TextColor = UE4.LinearColor.new(1.0, 1.0, 1.0, 1.0), ScreenX = HUDXRatio * 805, ScreenY = HUDYRatio * 455, Font = self.Font, Scale = HUDYRatio * 1.4, })
  • 57. 지원하는 Lua Version • Lua 5.3.4 사용 • Lua 5.1.5도 사용 가능할 것 같다. 다만 pairs()가 동작하지 않을 것이다. • Lua JIT는 지원하지 않는다. • 플러그인 내부에 Lua 소스코드가 포함됨 • 직접 Lua 코드를 구해서 연결할 필요 없다. • luasocket 및 op_halt 패치가 적용되어 있다. • https://github.com/devcat-studio/lua-5.3.4-op_halt
  • 58. Lua 소스코드 관리 • 파일 로더 클래스를 세분화 • LocalFileLoader : git에 저장된 Lua 소스코드를 사용 • BundleFileLoader: 빌드머신에서 배포한 Lua 파일 번들(zip)을 사용 • 사용할 로더는 실행 환경마다 다름 • 엔지니어, 디자이너: LocalFileLoader • 나머지 개발자: BundleFileLoader • 배포 빌드: BundleFileLoader
  • 59. • UE4 ScriptPlugin 모듈과 동일하게 구성되어 있다. • SilvervineUE4Lua : 런타임 모듈 • SilvervineUE4LuaEditor : 에디터 모듈 • SilvervineUE4LuaCodeGen : 바인딩 코드를 생성하는 UHT 플러그인 Plugin Modules "CanBeUsedWithUnrealHeaderTool" : true, "Modules": [ { "Name": "SilvervineUE4Lua", "Type": "Runtime", "LoadingPhase": "PreDefault" }, { "Name": "SilvervineUE4LuaEditor", "Type": "Editor", "LoadingPhase": "Default" }, { "Name" : "SilvervineUE4LuaCodeGen", "Type" : "Program", "LoadingPhase" : "PostConfigInit" } ]
  • 60. SilvervineUE4LuaEditor • USUE4LuaVirtualMachineFactory • VM 어셋을 생성하는 팩토리 클래스 • VM 어셋이 있으면 에디터에서 VM을 간단하게 지정할 수 있다.
  • 61. SilvervineUE4LuaCodeGen • UHT(Unreal Header Tool) 플러그인 • 프로젝트 모듈을 빌드하기 전에 먼저 실행된다. • 스태틱 바인딩 코드와 함수 디폴트 파라메터 테이블을 생성한다. 1>------ Build started: Project: SUE4LuaSample, Configuration: DebugGame_Editor x64 ------ 1>Performing full C++ include scan (building a new target) 1>Using 'git status' to determine working set for adaptive non-unity build (D:devgithubSilvervineUE4Lua). 1>Creating makefile for SUE4LuaSampleEditor (source directory changed) 1>Using Visual Studio 2017 14.16.27023 toolchain (C:Program Files (x86)Microsoft Visual Studio2017... 1>UnrealBuildTool : warning : Missing binary: D:devEpic GamesUE_4.21EngineSource$(ProjectDir)Plugins... 1>Building UnrealHeaderTool... 1>Performing full C++ include scan (building a new target) 1>Using 'git status' to determine working set for adaptive non-unity build (D:devgithubSilvervineUE4Lua). 1>Creating makefile for UnrealHeaderTool (ini files are newer than UBTMakefile) 1>Using Visual Studio 2017 14.16.27023 toolchain (C:Program Files (x86)Microsoft Visual Studio2017... 1>Parsing headers for SUE4LuaSampleEditor 1> Running UnrealHeaderTool "D:devgithubSilvervineUE4LuaSUE4LuaSample.uproject" "D:devgithubSilvervineUE4Lua... 1>Reflection code generated for SUE4LuaSampleEditor in 11.5833797 seconds 1>Target is up to date 1>Deploying SUE4LuaSampleEditor Win64 DebugGame... 1>Total build time: 59.99 seconds (NoActionsToExecute executor: 0.00 seconds) 1>Done building project "SUE4LuaSample.vcxproj". ========== Build: 1 succeeded, 0 failed, 0 up-to-date, 0 skipped ==========
  • 62. SilvervineUE4LuaCodeGen • 스태틱 바인딩 코드 생성 • IScriptGeneratorPluginInterface를 사용함 • 엔진 및 게임 클래스의 UFunction을 호출하는 함수를 생성 • 엔진 및 게임 클래스, 구조체의 UProperty 접근자 생성 • 두 개의 (거대한) inl 파일을 생성 • SilvervineUE4LuaCodeGen_Engine.g.inl : 약 80k 라인(3.9MB) • SilvervineUE4LuaCodeGen_Game.g.inl : 게임 마다 다름
  • 63. static int32 LuaCall_K2_AddRelativeLocation(lua_State* L, void* Self) { USceneComponent* CastedSelf = (USceneComponent*)Self; FSUE4LuaFunctionStaticBindingContext Context(L, 2, TEXT("K2_AddRelativeLocation")); FVector PARAM_DeltaLocation; bool PARAM_bSweep; FHitResult PARAM_SweepHitResult; bool PARAM_bTeleport; Context.Get("DeltaLocation", 0, PARAM_DeltaLocation, true); Context.Get("bSweep", 1, PARAM_bSweep, true); Context.Get("SweepHitResult", 2, PARAM_SweepHitResult, false); Context.Get("bTeleport", 3, PARAM_bTeleport, true); CastedSelf->K2_AddRelativeLocation(PARAM_DeltaLocation, PARAM_bSweep, PARAM_SweepHitResult, PARAM_bTeleport); Context.ModifyUStructIfAble("SweepHitResult", 2, PARAM_SweepHitResult); Context.Push("SweepHitResult", 2, PARAM_SweepHitResult); return 1; } 생성된 코드 샘플
  • 64. 생성된 코드 샘플 static int32 LuaGet_RelativeLocation(lua_State* L, void* Self) { UStaticMeshSocket* CastedSelf = (UStaticMeshSocket*)Self; FSUE4LuaStack::Push(L, CastedSelf->RelativeLocation); return 1; } static int32 LuaSet_RelativeLocation(lua_State* L, void* Self) { UStaticMeshSocket* CastedSelf = (UStaticMeshSocket*)Self; CastedSelf->RelativeLocation = FSUE4LuaStack::To<FVector>(L, 3); return 0; } static int32 LuaGet_RelativeRotation(lua_State* L, void* Self) { UStaticMeshSocket* CastedSelf = (UStaticMeshSocket*)Self; FSUE4LuaStack::Push(L, CastedSelf->RelativeRotation); return 1; } static int32 LuaSet_RelativeRotation(lua_State* L, void* Self) { UStaticMeshSocket* CastedSelf = (UStaticMeshSocket*)Self; CastedSelf->RelativeRotation = FSUE4LuaStack::To<FRotator>(L, 3); return 0; }
  • 65. SilvervineUE4LuaCodeGen • 간단한 성능 비교 • 평균적으로 스태틱 바인딩 코드 패스가 리플렉션 코드 패스에 비해 빠르다. • Scripts/Test/PerformanceTest.lua 참고 0 0.01 0.02 0.03 0.04 0.05 0.06 UObject* Getter UObject* Setter int32 Getter int32 Setter TestArg(…) TestArg(Args) Reflection Static Binding
  • 66. SilvervineUE4LuaCodeGen • 스태틱 바인딩 활성화가 기본값 • 실행 속도가 빠르기 때문에 기본값이 True • 대신, 빌드 속도가 느리다(10~30초 추가) • 원한다면 비활성화 할 수 있다(DefaultSilvervineUE4Lua.ini 수정) [/Script/SilvervineUE4Lua.SUE4LuaSettings] bEnableStaticBinding = False
  • 67. SilvervineUE4LuaCodeGen • 디폴트 파라메터 테이블 • 함수 호출 시 생략 가능한 파라메터의 기본값이 저장되어 있는 Lua 테이블을 생성한다. • 함수 파라메터가 생략되면 Lua 테이블에서 기본값을 찾는다. • 메타 정보가 에디터 빌드에서만 접근 가능하기 때문에 이와 같은 파일이 필요하다. • 모듈 의존성을 제거하기 위해 C++이 아닌 Lua 코드로 생성한다. --SpawnDecalAttached DefaultParameters.GameplayStatics.SpawnDecalAttached = Class(DefaultParameterClass) DefaultParameters.GameplayStatics.SpawnDecalAttached.AttachPointName = "None" DefaultParameters.GameplayStatics.SpawnDecalAttached.LocationType = 0 --EAttachLocation::Type::KeepRelativeOffset DefaultParameters.GameplayStatics.SpawnDecalAttached.LifeSpan = 0.000000 생성된 코드 샘플
  • 68. SilvervineUE4Lua • 예외 처리 • VM에 에러 핸들러가 구현되어 있음 • C++에서 Lua 함수를 호출할 때는 항상 lua_pcall() 사용 • Lua xpcall에서 사용 가능(SUE4Lua.EventHandler) [Log] [Game/Main.lua:10] DispatchHandlerFactory: Sedan_C [Log] [SUE4Lua/Framework/SUE4LuaBinding.lua:103] Dispatch Handler Registered: Sedan_C Game/Sedan.lua [Log] [Game/Sedan.lua:62] Sedan:ReceiveBeginPlay() was called. [Log] [Game/Main.lua:10] DispatchHandlerFactory: CameraComponent [Error] [Game/Sedan.lua:23] 'Activatee': is not a member of 'CameraComponent'. [Error] [Game/Sedan.lua:23] FATAL: attempt to call a nil value (method 'Activatee') [Log] [Game/Main.lua:10] DispatchHandlerFactory: VehicleHUD_C [Log] [SUE4Lua/Framework/SUE4LuaBinding.lua:103] Dispatch Handler Registered: VehicleHUD_C Game/VehicleHUD.lua [Log] [FSUE4LuaVMContext::Dispose] Disposing '00000153CEEA5608'...
  • 69. SilvervineUE4Lua • UE4 Automation으로 유닛 테스트 실행 • 에디터 시작 시 자동으로 유닛테스트가 실행된다. • 이후에는 세션 프론트엔드에서 실행할 수 있다.
  • 70. SilvervineUE4Lua • 디버깅 • VSCodeLuaDebug에 크게 의존하고 있다. • 디버기 설정은 샘플 프로젝트의 Main.lua를 참고(SUE4LuaSample/Scripts/Main.lua) • 파일 로딩 전에 설치된 브레이크포인트가 작동하지 않는 문제가 있다. • 개발 빌드는 시작할 때 모든 Lua 파일을 미리 로딩해 둠
  • 71. SilvervineUE4Lua • Lua 객체를 C++에 저장하기 • LuaValue(USUE4LuaValue)를 통해 모든 Lua 값을 C++에 저장할 수 있다. • 저장된 값은 LuaValue 파괴 전까지 gc되지 않는다. • 저장된 값을 C++에서 사용하기 • boolean, integer, number, string 면 해당 값을 C++ 타입으로 반환 • 테이블 필드에도 접근 가능하다. • 함수면 직접 호출할 수 있다. • UObject(userdata)는 UObject*로 반환 • UStruct, TArray 등은 (아직) 지원 안함
  • 72. SilvervineUE4Lua • Lua 스택에 Push 할 수 있는 타입 • C++ 기본 타입: (u)int8/16/32/64, float/double, bool, char*, TChar*(wchar) • UE4 스트링: FName, FString, FText • Enum : C++ enum, enum class, UEnum • UObject: UObject 및 모든 파생 클래스 -> userdata • UStruct: FVector, FColor 등의 구조체는 미리 정의된 table, 나머지는 userdata • 그리고 LuaValue: 저장된 Lua 값을 푸시 • TArray 등의 컨테이너 타입은 지원하지 않는다. • 하지만 함수 파라메터로는 전달할 수 있다. • UFunction이 UStruct의 파생 클래스이기 때문
  • 73. SilvervineUE4Lua • Lua에서 UProperty에 접근 • Lua에서 UObject, UStruct의 UProperty를 읽고 쓸 수 있다. • UE4 리플렉션 시스템 및 스태틱 바인딩을 사용해서 구현 • 배열 및 컨테이너 지원 • 배열(int32[]), 컨테이너(TArray, TMap, TSet) 모두 지원한다. • pairs()로 원소 순회 가능
  • 74. SilvervineUE4Lua • 기본 타입이 아닌 UProperty는 프록시 객체를 생성 • UObject, UStruct, 배열, TArray, TMap, TSet, Delegate가 해당 • userdata 형식의 프록시를 생성하고 weak 테이블에 캐싱함 • 프록시 객체는 소유자 UObject에 대한 약참조를 생성 • C++은 Lua 값에 대한 강참조 가능 • Lua는 C++에 대한 약참조만 가능 • Lua에서 강참조가 필요하다면 C++에 저장하면 된다.
  • 75. SilvervineUE4Lua • 배열과 컨테이너의 원소 반환 • 값을 반환 : 안전하지만 복사 비용이 발생 • 참조를 반환 : 위험하지만 비용 부담이 없다. • 고정 크기 배열은 참조를 반환해도 안전 • 메모리가 재할당되지 않기 때문 • TArray 등은 참조를 반환하면 위험 • 내부 버퍼가 재할당될 수 있기 때문 • 재할당이 발생하지 않는 경우에만 참조 반환을 쓰자.
  • 76. SilvervineUE4Lua • Lua에서 클래스 함수 호출 • C++, Blueprint 함수 모두 호출할 수 있다. • UE4 리플렉션 및 코드젠된 스태틱 바인딩 코드를 사용함 • 파라메터 전달 과정이 약간 복잡한데 이후 슬라이드에서 설명 • 코딩 편의를 위한 추가 기능 • UClass 타입은 편의상 대상 클래스의 UFunction을 바로 호출할 수 있다. • 이름에 ‘K2_’ 접두사가 붙은 함수는 접두사 없는 이름으로 호출 가능
  • 77. SilvervineUE4Lua • Lua에서 UFunction이 아닌 클래스 함수 호출 • 예를 들면 UObject::IsA() • 간단하게 바인딩 함수를 구현할 수 있다 • Public/Bindings/*.h 참고 // // UObject에 대한 lua 바인딩 // UCLASS(NotBlueprintType) class SILVERVINEUE4LUA_API USUE4LuaObjectBinding : public USUE4LuaBinding { GENERATED_BODY() public: // Begin USUE4LuaBinding Interface virtual UClass* GetBindingClass() const override; // End USUE4LuaBinding Interface UFUNCTION() static FString LuaGetName(UObject* InSelf); UFUNCTION() static UClass* LuaGetClass(UObject* InSelf); UFUNCTION() static bool LuaIsA(UObject* InSelf, FName ClassName); UFUNCTION() static class UWorld* LuaGetWorld(UObject* InSelf); }; function VehicleHUD:ReceiveDrawHUD(Params) --SUE4Lua.Log("VehicleHUD:ReceiveDrawHUD() was called.") local SizeX = Params.SizeX local SizeY = Params.SizeY local OwningPawn = self:GetOwningPawn() local Sedan = (UE4.IsValid(OwningPawn) and OwningPawn:IsA('Sedan_C’)) …
  • 78. SilvervineUE4Lua • Lua에서 클래스 함수 호출 시 파라메터 및 반환값 전달 • (거의) 모든 타입을 지원: int32부터 TArray까지 • 파라메터는 테이블로 전달할 수 있다. • 참조형 파라메터(출력값)도 지원(파라메터가 테이블 값이 갱신된다). • 반환값 및 출력값은 순서대로 Lua 함수의 반환값으로 전달된다. UFUNCTION() int32 TestArgs(int32 InIntArg1, int32 InIntArg2, const int32& InIntArg3, int32& OutIntArg1, int32& OutIntArg2); local Ret, OutIntArg1, OutIntArg2 = self:TestArgs({ InIntArg1 = 1, InIntArg2 = 2, InIntArg3 = 3, OutIntArg1 = 4, OutIntArg2 = nil,-- 생략 가능 })
  • 79. SilvervineUE4Lua • C++에서 Lua 함수 호출 • FSUE4LuaFunction 클래스를 사용하거나, • 딜리게이트에 Lua 함수를 바인딩해서 호출할 수 있다. • 딜리게이트 Lua 바인딩 구현이 약간 특이함 • 일단, 딜리게이트에 비어 있는 더미 함수를 바인딩 해둔다. • ProcessEvent() 함수를 오버라이드한 후 그 안에서 Lua 함수를 호출 • 자세한 사항은 USUE4LuaValue::ProcessEvent() 구현을 참고
  • 80. SilvervineUE4Lua • Blueprint 디스패치 • 다른 스크립트 플러그인에는 없는 독특한 기능. • Blueprint 스택을 읽어서 Lua 스택에 바로 푸시한다. • 때문에 Blueprint 노드 파라메터를 디스패치 노드로 연결하는 작업이 필요없다. function SomeClass:Func(Params) local InParams1 = Params.InParam1 local InParams2 = Params.InParam2 local InParams3 = Params.InParam3 -- ... Params.OutParam1 = ... Params.OutParam2 = ... end
  • 81. SilvervineUE4Lua • 네이티브(C++) 디스패치 • Blueprint 디스패치와 비슷한 기능 • 디스패치라고 부르고 있지만 사실 단순한 LuaFunction 호출이다. • 리플렉션을 사용하지 않기 때문에 파라메터를 배열로 Lua에 전달한다. // NativeDispatch()를 쉽게 사용하기 위한 매크로입니다. // // 사용 예: //void UMyClass::Foo(int32 P1, int32 P2) //{ // SUE4LUA_DISPATCH(LuaBridge, P1, P2); //} #define SUE4LUA_DISPATCH(LuaBridge, ...) if( LuaBridge) { LuaBridge->NativeDispatch(this, ANSI_TO_TCHAR(__func__), __VA_ARGS__); }
  • 82. SilvervineUE4Lua • 디스패치 핸들러 팩토리 • 클래스의 디스패치에 사용할 Lua 파일(디스패치 핸들러) 이름을 반환하는 함수를 말한다. • Lua로 구현해서 VM에 설정한다. SUE4Lua.SetDispatchHandlerFactory(function (CallerClass) local ClassName = CallerClass:GetName() SUE4Lua.Log("DispatchHandlerFactory: ", ClassName) local Filenames = { Sedan_C = "Game/Sedan.lua", VehicleHUD_C = "Game/VehicleHUD.lua", } return Filenames[ClassName] or "" end)
  • 83. SilvervineUE4Lua • 디스패치 핸들러 직접 호출 • 디스패치 핸들러 Lua 함수에서 다른 디스패치 핸들러의 Lua 함수를 바로 부를 수 있다. • 구조적으로 마음에 들지 않지만 확실히 컨텐츠 구현할 때 유용하다... • 최소한 함수 네이밍이라도 다르게 해야 할 것 같다(내부 논의 중) function ClassA:FuncA(Params) self.ObjectB:FuncB(1, 2, 3) end function ClassB:FuncB(P1, P2, P3) SUE4Lua.Log(P1, P2, P3) -- 1 2 3 end
  • 84. SilvervineUE4Lua • 코루틴 및 멀티스레드 • 멀티스레드는 지원하지 않는다. 필요하다면 VM을 분리해서 사용. • 최근에 코루틴을 지원하기 시작했다. 아직 불안정함.
  • 85. SilvervineUE4Lua • 알고 있는 문제들 • UE4 핫 리로딩 이후에 Lua에서 잘못된 함수를 호출하는 문제 • 딜리게이트에 시그니처가 맞지 않는 함수를 바인딩하면 호출할 때 크래시 • SUE4Lua 오류 메시지가 너무 불친절함 • 이후 작업 • 오류 메시지를 이해하기 쉽게 수정 • REPL(Read-Eval-Print-Loop) 지원
  • 87. SilvervineUE4Lua • UE4 Blueprint의 단점을 보완하기 위해 Lua를 사용 • Lua와 같은 텍스트 스크립트 언어를 사용하여 Blueprint 복잡도를 낮췄다. • 텍스트 자료형을 사용하여 협업에 어려움이 없도록 개선했다. • 실제 업무에 적용하여 좋은 결과를 얻고 있다. • 플러그인 소스코드 공개 • GitHub에 소스코드를 공개함. 많은 피드백 부탁 드립니다! • 스크립트 플러그인을 제작할 때 도움이 될 만한 경험을 공유
  • 88. 참고자료 • 일반 • UE4 Blueprint 문서: http://api.unrealengine.com/KOR/Engine/Blueprints/GettingStarted/ • VPL Wiki: https://en.wikipedia.org/wiki/Visual_programming_language • BlueprintsFromHell : https://blueprintsfromhell.tumblr.com/ • 스크립트 플러그인 • SkookumScript: http://skookumscript.com/unreal/ • UE4 Python Plugin : http://api.unrealengine.com/KOR/Engine/Editor/ScriptingAndAutomation/Python/ • MonoUE: https://mono-ue.github.io/ • UnrealEnginePython: https://github.com/20tab/UnrealEnginePython • unreal.lua: https://github.com/asqbtcupid/unreal.lua • sluaunreal: https://github.com/Tencent/sluaunreal
  • 89. QnA