이제 플레이어가 동전을 수집했을 때 이를 감지할 수 있으므로, 플레이어가 수집한 동전의 수를 세고 그 수치를 리더보드에 표시해야 합니다.
동전 수집 기록을 위한 모듈 스크립트 만들기
각 플레이어의 동전 수집 데이터를 저장하고 관리하기 위해, 모든 플레이어의 동전 수집 데이터에 접근할 수 있는 데이터 구조와 함수를 포함하는 ModuleScript 객체를 생성해야 합니다. 모듈 스크립트는 다른 스크립트에서 요구할 수 있는 재사용 가능한 코드입니다. 이 경우, CoinService는 플레이어가 동전을 터치할 때 동전 수집 데이터를 업데이트할 수 있도록 이 모듈 스크립트를 요구합니다.
ServerStorage에서 PlayerData라는 이름의 ModuleScript를 생성하고 다음 코드를 입력합니다:
```lua
local PlayerData = {}
PlayerData.COIN_KEY_NAME = "Coins"
local playerData = {
--[[
[userId: string] = {
["Coins"] = coinAmount: number
}
]]
}
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
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
return PlayerData
```모듈 스크립트는 플레이어의 동전 수집 데이터를 나타내는 여러 개의 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 테이블의 데이터를 검색하는 로컬 함수입니다. 플레이어가 동전을 수집하지 않았다면, 모든 플레이어가 그들과 관련된 데이터를 가지도록 보장하기 위해 defaultPlayerData() 함수에서 테이블을 반환합니다. 일반적인 관례는 간단한 공개 함수들을 만들어 로컬 스코프의 함수들에 로직을 오프로드하여 무거운 작업을 수행하게 하는 것입니다.
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를 사용하여 자동으로 리더보드를 생성하는 내장 시스템을 포함하고 있습니다.
ServerStorage에서 Leaderboard라는 이름의 ModuleScript를 생성하고 다음 코드를 입력합니다:
```lua
local Leaderboard = {}
-- 새로운 리더보드 생성
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
-- 플레이어의 통계 값 업데이트
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
return Leaderboard
```다음 섹션에서는 리더보드가 어떻게 작동하는지에 대해 더 자세히 설명합니다.
리더보드 생성
setupLeaderboard() 함수는 leaderstats라는 이름의 새로운 폴더 인스턴스를 생성하고 이를 지정된 플레이어의 자식으로 설정합니다. Roblox는 leaderstats라는 이름의 폴더를 통계의 컨테이너로 자동으로 인식하고 통계를 표시하기 위한 UI 요소를 생성합니다. leaderstats에 있는 값은 "값" 객체(예: 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 스크립트에서 이를 요구하여 플레이어 동전 데이터를 관리하고 표시합니다.
ServerScriptService에서 기존 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.Coins
local coins = coinsFolder:GetChildren()
local COIN_KEY_NAME = PlayerData.COIN_KEY_NAME
local COOLDOWN = 10
local COIN_AMOUNT_TO_ADD = 1
local 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") then
local character = otherPart.Parent
local player = Players:GetPlayerFromCharacter(character)
if player then
-- 플레이어가 동전을 터치함
coin.Transparency = 1
coin:SetAttribute("Enabled", false)
updatePlayerCoins(player, function(oldCoinAmount)
oldCoinAmount = oldCoinAmount or 0
return oldCoinAmount + COIN_AMOUNT_TO_ADD
end)
task.wait(COOLDOWN)
coin.Transparency = 0
coin:SetAttribute("Enabled", true)
end
end
end
-- 이벤트 리스너 설정
for _, coin in coins do
coin: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() 호출로 교체합니다.
플레이 테스트
드롭다운에서 Test를 선택하고 Play를 클릭합니다. 동전 안으로 걸어 들어가 리더보드가 모서리에 나타나고 동전을 더 수집할수록 동전 수가 증가하는지 확인합니다.