로블록스 게임 개발을 위한 5가지 코딩 패턴

Image not Found

안녕하세요. wasd팀에 IRoblian입니다.
한국에서도 좀 심화적으로 스크립팅 하시는분이 계실 것 같아, 제가 보던 자료 하나를 정리해서 공유합니다.
조금 전문적으로 로블록스 게임에 도전해보시거나, 심화적으로 다가가실때 도움이 될 것 같습니다.

이 글은 RDC20에서 공유됐던, 아래의 영상을 정리한 글입니다.
5 Powerful Code Patterns Behind Top Roblox Game(RDC 20)

Overview


로블록스에서 사용하는 모든 패턴은 비동기를 다루기 위해 사용됩니다.

  1. Signals - 유저 입력과 이벤트를 처리 돕습니다. (Your Boat 에서 제작 및 사용)
  2. Maids - 메모리 릭을 막으줍니다. (Jailbreak에서 제작 및 사용)
  3. Promises - 데이터를 저장하고, 웹 요청을 지원합니다. (Adopt me에서 제작 및 사용)
  4. Springs - 애니메이션을 안전하게 만들어줍니다.
  5. Binders - 프로그래밍으로 오브젝트 스트리밍하는걸 가능하게 줍니다.

이런 도구들은 무엇보다 코드의 디커플링을 돕습니다. 실제로 Top 레벨 게임에서 이 패턴을 안쓰는 경우는 없다고 장담합니다.

1. Signals


함께보면 좋은 자료

철학

Observe the world, don’t query it.
질의(query)하지 말고, 세상을 관찰하자.

사용법

기본적인 사용법

signal:Connect(callback)

연결하고, 끊기

local conn = event:Connect(function()...end)
conn:Disconnect()

이벤트를 호출하기

event:Fire()

쿼리와 다른점

Querying

Wait를 이용해서 계속 기다려줘야합니다.

while true do
    wait(0.5)
    print(Players:GetPlayers())
end

Signals

이벤트가 호출될 때를 감지할 수 있습니다.

local players = {}
players.PlayerAdded:Connect(function(player)
    players[player] = true
end)
players.PlayerRemoving:Connect(function(player)
   players[player] = nil
end)

Signal의 장점

  • 이벤트에 즉시 반응합니다.
  • 연결을 취소할 수 있습니다.
  • Signal 안에서 에러가 발생해도, 게임 루프에 영향을 주지 않습니다.(전파되지 않음)

Signal의 단점

  • 간접 호출로 디버깅이 어렵습니다.
  • 연산이 조금 비쌉니다.
  • 연결을 취소하지 않으면 메모리 릭이 발생할 수 있습니다.

정리하면, 많은 프로그래밍에 있는 이벤트를 구현한 구현체라고 볼 수 있습니다.

2. Maids


함께보면 좋은 자료

철학

Have an object to clean everything up!
모든 것을 정리하는 오브젝트를 가져라!

사용법

local maid = Maid:new()
maid:GiveTask(task)

--정리가 필요할 때
maid:DoCleaning()

Maid에 넣을 수 있는 Tasks의 종류

  • 함수(Functions)
  • 커넥션(Connections)
  • :Destory() 를 가진 모든 것

예시

function RocketLauncher.new(Player, ItemData)
  local self = Gun.new(Player, ItemData)
  setmetatable(self, RocketLauncher)
  -- ...self.RocketWorld = RocketWorld.new()
  -- ...self.Maid:GiveTask(self.RocketWorld)
  return self
end

정리하면, 다른 프로그래밍 언어에서 사용하는 가비지컬렉터 같은 개념입니다. Maid에 넣고, 깔끔하게 치울때 사용하면 좋아요.

3. Promises


함께 보면 좋은 자료

Roblox에서 yield의 문제

  • Roblox에서 yielding을 다루는건 실수를 많이 만듭니다.
  • yielding 할때 다른 코드가 돌아가면 동시성 문제가 발생할 수 있습니다.

Promises의 정의

  • 프라미스는 태스크를 표현하는 방법입니다.

사용법

local promise = Promise.new(function(resolve)
    resolve(HttpService:GetAsync("https://playadopt.me"))
end)

Promise의 유용한 패턴

  • cancel() : promises가 취소되도록 요청할 수 있습니다. 요청한 결과가 더 이상 필요 없을 때 사용합니다.
local promise = DownloadAndStreamScoreboardToUser(player)
PlayerClosedScoreboard.OnServerEvent:Connect(function(playerWhoClosedScoreboard)
  if player == playerWhoClosedScoreboard then
       promise:cancel()
  end
end)
  • endThen() : 해당 작업이 완료된 후 다음 스케줄을 등록하고 싶을때 사용합니다. 이전에 있던 작업을 활용 할 수도 있습니다.
local promise = Promise.new(function(resolve)
  resolve(HttpService:GetAsync("https://playadopt.me"))
end)
promise:andThen(function(result)
  print("playadopt.me's response was " .. result)
end)
  • all : 여러개의 task를 한번에 수행하나라도 실패하면 실패모든 태스크가 모두 성공하면 완료됩니다.
local userLoadPromise =Promise.all({
    loadUserHousePromise,
    loadUserMoneyPromise,
    loadUserPetsPromise
})
userLoadPromise:andThen(function()
  -- Spawn the user into the game
    End):catch(function()
  -- Tell the user we failed to load their save
    End)

정리하면, Javascript나 C#에 있는 async/awake 문법을 가져온 거라고 할 수 있습니다.
정말 잘 구현되어 있습니다.

4. Springs


여기서부턴 선택적인 패턴이라 가볍게 설명합니다.

함께 보면 좋은 자료

Springs란?

  • Tween을 더욱 쉽게 만들 수 있습니다.
  • 자동차나 탈것 같은거 카메라 웍에 자주 사용됩니다.

사용 팁

  • 물리 기반에서 Damping을 구현하는 방법입니다.
  • Speed/Damping 파라미터를 활용해 쉽게 조정이 가능합니다.
  • Value를 요청할때만 값을 사용하기 때문에 최적화에 좋습니다.

5. Binders


함께보면 좋은 자료

Binders란?

  • 태그 시스템을 이용해 동적으로 오브젝트에 속성을 부여할 수 있습니다.
  • 테스트를 쉽게 만듭니다.

사용팁

  • 바인더는 오브젝트 스트리밍에 사용하기 좋습니다.
  • CollectionService에 Tag 기반으로 동작합니다.

정리하며,

이 발표를 했던 분들이 Nevermore Engine 제작자여서 그런가 본인들의 내부 구현체를 많이 차용해서 관련 레퍼런스도 가져왔습니다.
이 영상이나 패턴이 개발하시는데 혹은 전문 스크립터로 성장하는데 도움이 되셨으면 좋겠네요 :)

많은 부분이 “비동기 처리"와 “메모리"나 “이벤트"와 같은 높은 수준의 프로그래밍 언어에서 사용되는 것들이여서 혹시나 Lua를 처음 언어로 접하신 분들이라면 “동시성 프로그래밍” 관련 된 책이나 글들을 찾아보시면 도움이 많이 될거예요!!

그럼 또 찾아뵙겠습니다.(_ _)

✅ 본래의 영상은 아래에서 확인해 볼 수 있습니다.

You May Also Like

펫 & 몬스터 메타포 결정

펫 & 몬스터 메타포 결정

안녕하세요. Wasd Games에 hobi 입니다. 현재 개발 중인 게임에 디시전 관련 내용을 공유하려고 합니다. 💡 목적 : 펫&몬스터 메타포를 결정합니다. R&D 결과 내용 공유 : 결정과정중 겪은 내용 먼저 알려드리고, …