이제 플레이어가 동전을 수집할 때 이를 감지할 수 있으므로, 플레이어가 수집한 동전의 수를 세고 이를 리더보드에 표시해야 합니다.
동전 수집을 기록하기 위한 모듈 스크립트 만들기
각 플레이어의 동전 수집 데이터를 저장하고 관리하기 위해, 모든 플레이어의 동전 수집 데이터에 접근할 수 있는 데이터 구조와 함수들을 포함하는 ModuleScript 객체를 만들어야 합니다. 모듈 스크립트는 다른 스크립트가 요구할 수 있는 재사용 가능한 코드입니다. 이 경우, CoinService는 플레이어가 동전에 닿을 때 동전 수집 데이터를 업데이트할 수 있도록 이 모듈 스크립트를 요구합니다.
Create PlayerDataServerStorage에서 다음 코드를 가진 PlayerData라는 ModuleScript를 만듭니다:```lualocal PlayerData = {}PlayerData.COIN_KEY_NAME = "Coins"local playerData = {--[[[userId: string] = {["Coins"] = coinAmount: number}]]}local function defaultPlayerData()return {[PlayerData.COIN_KEY_NAME] = 0}endlocal function getData(player)local data = playerData[tostring(player.UserId)] or defaultPlayerData()playerData[tostring(player.UserId)] = datareturn dataendfunction PlayerData.getValue(player, key)return getData(player)[key]endfunction PlayerData.updateValue(player, key, updateFunction)local data = getData(player)local oldValue = data[key]local newValue = updateFunction(oldValue)data[key] = newValuereturn newValueendreturn PlayerData```
모듈 스크립트는 플레이어의 동전 수집 데이터를 나타내는 0개 이상의 playerData 테이블을 포함하는 PlayerData 테이블을 정의합니다. 이 모듈 스크립트를 요구하는 모든 스크립트는 동일한 PlayerData 테이블의 사본을 받아 여러 스크립트가 동전 수집 데이터를 수정하고 공유할 수 있습니다.
데이터 구조 선언
모듈 스크립트는 빈 테이블 PlayerData의 선언으로 시작하며, 이 테이블은 스크립트의 끝에서 반환됩니다. 또한 테이블의 값에 접근하고 설정하는 접근자 메서드를 포함합니다.
playerData 테이블은 테이블 구조를 설명하는 주석을 포함하고 있어 코드를 이해하기 쉽게 만듭니다. 이 경우, playerData 테이블은 userId와 해당 플레이어가 수집한 동전의 수를 나타내는 Coins라는 필드를 포함합니다.
local PlayerData = {}PlayerData.COIN_KEY_NAME = "Coins"local playerData = {--[[[userId: string] = {["Coins"] = coinAmount: number}]]}...return PlayerData
로컬 데이터 접근자 정의
getData()는 특정 playerData 테이블의 데이터를 가져오는 로컬 함수입니다. 플레이어가 동전을 수집하지 않았다면 모든 플레이어와 연결된 데이터가 있도록 기본 데이터 테이블을 반환합니다. 일반적인 관례는 간단한 공개 함수들을 만들어 로컬 범위의 함수들이 주요 로직을 처리하도록 오프로딩하는 것입니다.
local function defaultPlayerData()
return {
[PlayerData.COIN_KEY_NAME] = 0
}
end
local function getData(player)
local data = playerData[tostring(player.UserId)] or defaultPlayerData()
playerData[tostring(player.UserId)] = data
return data
end
공개 데이터 접근자 정의
getValue()와 updateValue()는 다른 스크립트가 이 모듈 스크립트를 요구할 때 호출할 수 있는 공개 함수입니다. 우리의 경우, CoinService는 해당 플레이어가 동전과 접촉할 때마다 이 함수들을 사용하여 플레이어의 동전 수집 데이터를 업데이트합니다.
function PlayerData.getValue(player, key)
return getData(player)[key]
end
function PlayerData.updateValue(player, key, updateFunction)
local data = getData(player)
local oldValue = data[key]
local newValue = updateFunction(oldValue)
data[key] = newValue
return newValue
end
리더보드 구현
화면상의 리더보드를 통해 동전 수집 데이터를 시각적으로 표현할 수 있습니다. Roblox에는 기본 UI를 사용하여 리더보드를 자동으로 생성하는 내장 시스템이 포함되어 있습니다.
Create LeaderboardServerStorage에서 Leaderboard라는 ModuleScript를 다음 코드로 생성합니다:```lualocal Leaderboard = {}-- 새로운 리더보드 생성local function setupLeaderboard(player)local leaderstats = Instance.new("Folder")-- 'leaderstats'는 Roblox가 리더보드를 생성하기 위해 인식하는 예약 이름입니다.leaderstats.Name = "leaderstats"leaderstats.Parent = playerreturn leaderstatsend-- 새로운 리더보드 통계 값 생성local function setupStat(leaderstats, statName)local stat = Instance.new("IntValue")stat.Name = statNamestat.Value = 0stat.Parent = leaderstatsreturn statend-- 플레이어의 통계 값 업데이트function Leaderboard.setStat(player, statName, value)local leaderstats = player:FindFirstChild("leaderstats")if not leaderstats thenleaderstats = setupLeaderboard(player)endlocal stat = leaderstats:FindFirstChild(statName)if not stat thenstat = setupStat(leaderstats, statName)endstat.Value = valueendreturn Leaderboard```
다음 섹션은 리더보드가 어떻게 작동하는지에 대해 더 자세히 설명합니다.
리더보드 생성
setupLeaderboard() 함수는 leaderstats라는 새로운 폴더 인스턴스를 생성하고 이를 지정된 플레이어의 자식으로 설정합니다. Roblox는 leaderstats라는 폴더를 자동으로 통계의 컨테이너로 인식하고 통계를 표시하기 위한 UI 요소를 생성합니다. leaderstats의 값은 "value" 객체(예: StringValue, IntValue 또는 NumberValue)로 저장해야 합니다.
-- 새로운 리더보드 생성
local function setupLeaderboard(player)
local leaderstats = Instance.new("Folder")
-- 'leaderstats'는 Roblox가 리더보드를 생성하기 위해 인식하는 예약 이름입니다.
leaderstats.Name = "leaderstats"
leaderstats.Parent = player
return leaderstats
end
-- 새로운 리더보드 통계 값 생성
local function setupStat(leaderstats, statName)
local stat = Instance.new("IntValue")
stat.Name = statName
stat.Value = 0
stat.Parent = leaderstats
return stat
end
플레이어 통계 업데이트
setStat()는 Leaderboard 모듈의 유일한 공개 함수입니다. 이는 지정된 플레이어 또는 리더보드 자체에 대한 통계 값을 생성하여 그것이 이미 존재하지 않는 경우입니다.
FindFirstChild()는 객체의 이름을 받아 해당 객체가 존재하면 반환하고, 존재하지 않으면 nil을 반환합니다. 이는 객체를 사용하기 전에 존재 여부를 안전하게 확인하는 일반적인 방법입니다.
-- 플레이어의 통계 값 업데이트
function Leaderboard.setStat(player, statName, value)
local leaderstats = player:FindFirstChild("leaderstats")
if not leaderstats then
leaderstats = setupLeaderboard(player)
end
local stat = leaderstats:FindFirstChild(statName)
if not stat then
stat = setupStat(leaderstats, statName)
end
stat.Value = value
end
모듈 스크립트 통합
두 모듈이 모두 준비되었으므로, CoinService 스크립트에서 이를 요구하여 플레이어 동전 데이터를 관리하고 표시합니다.
Update CoinServiceServerScriptService에서 기존 CoinService 스크립트의 코드를 다음으로 교체합니다:```lua-- 서비스와 변수 초기화local Workspace = game:GetService("Workspace")local Players = game:GetService("Players")local ServerStorage = game:GetService("ServerStorage")-- 모듈local Leaderboard = require(ServerStorage.Leaderboard)local PlayerData = require(ServerStorage.PlayerData)local coinsFolder = Workspace.World.Coinslocal coins = coinsFolder:GetChildren()local COIN_KEY_NAME = PlayerData.COIN_KEY_NAMElocal COOLDOWN = 10local COIN_AMOUNT_TO_ADD = 1local function updatePlayerCoins(player, updateFunction)-- 동전 테이블 업데이트local newCoinAmount = PlayerData.updateValue(player, COIN_KEY_NAME, updateFunction)-- 동전 리더보드 업데이트Leaderboard.setStat(player, COIN_KEY_NAME, newCoinAmount)end-- 이벤트 핸들러 정의local function onCoinTouched(otherPart, coin)if coin:GetAttribute("Enabled") thenlocal character = otherPart.Parentlocal player = Players:GetPlayerFromCharacter(character)if player then-- 플레이어가 동전을 터치함coin.Transparency = 1coin:SetAttribute("Enabled", false)updatePlayerCoins(player, function(oldCoinAmount)oldCoinAmount = oldCoinAmount or 0return oldCoinAmount + COIN_AMOUNT_TO_ADDend)task.wait(COOLDOWN)coin.Transparency = 0coin:SetAttribute("Enabled", true)endendend-- 이벤트 리스너 설정for _, coin in coins docoin:SetAttribute("Enabled", true)coin.Touched:Connect(function(otherPart)onCoinTouched(otherPart, coin)end)end```
원래의 CoinService 스크립트에 대한 변경 사항은 다음과 같습니다:
- 플레이어가 동전을 수집할 때 추가할 동전의 수를 나타내는 COIN_AMOUNT_TO_ADD와 PlayerData에서 정의된 키 이름인 COIN_KEY_NAME을 선언합니다.
- 플레이어의 동전 수와 관련된 리더보드 통계를 업데이트하기 위한 도우미 함수인 updatePlayerCoins()를 만듭니다.
- onCoinTouched()에서 자리 표시자 print() 문을 updatePlayerCoins() 호출로 교체합니다.
플레이 테스트
드롭다운에서 테스트를 선택하고 재생을 클릭합니다. 동전 안으로 걸어가서 리더보드가 모서리에 나타나고, 동전을 수집할수록 동전 수가 증가하는지 확인합니다.