ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 로블록스 코딩 실습 30 - 간단 상점(Shop) 시스템
    Roblox 코딩 2026. 1. 5. 19:47

    클릭 한 번으로 구매되는 간단 상점(Shop) 시스템 만들기

    이번 30번째 실습에서는 로블록스에서 가장 많이 쓰이는 기능 중 하나인 상점(Shop) 을 구현한다.
    구현 목표는 다음과 같다.

    • 맵에 상점 NPC(또는 버튼)를 두고
    • 플레이어가 클릭하면 상점 UI가 열리고
    • 버튼을 누르면 코인 차감 후 아이템 지급이 된다

    구조는 단순하지만, 이후에 카테고리/인벤토리/스킨/게임패스로 확장하기 쉬운 방식으로 구성한다.


    1. 실습 결과물 구조

    이번 실습은 “서버 권한(구매 처리)”과 “클라이언트(UI)”를 분리한다.

    • 클라이언트(LocalScript): UI 열기/닫기, 구매 버튼 클릭 → 서버에 요청
    • 서버(Script): 코인 체크, 차감, 아이템 지급(또는 효과 적용)

    핵심은 다음 한 줄이다.

    “구매/재화 변경은 반드시 서버에서 처리한다.”


    2. 준비물 (Studio에서 만들 것)

    (1) 리더보드 코인(leaderstats) 만들기

    ServerScriptService에 Script 생성: Leaderstats

    local Players = game:GetService("Players")
    
    Players.PlayerAdded:Connect(function(player)
    	local leaderstats = Instance.new("Folder")
    	leaderstats.Name = "leaderstats"
    	leaderstats.Parent = player
    
    	local coins = Instance.new("IntValue")
    	coins.Name = "Coins"
    	coins.Value = 100 -- 시작 코인
    	coins.Parent = leaderstats
    end)
    

    (2) 구매할 아이템 준비

    가장 간단하게는 Tool을 지급하는 방식이 좋다.

    1. StarterPack에 Tool 하나 만들기(또는 기존 Tool 사용)
    2. 그 Tool을 ServerStorage로 옮기고 이름을 Sword로 맞춘다
    • ServerStorage/Sword (Tool)

    (3) RemoteEvent 만들기

    ReplicatedStorage에 RemoteEvent 생성
    이름: ShopPurchase


    3. 상점 UI 만들기

    (1) ScreenGui 생성

    StarterGui에 다음 구조로 만들기:

    • ShopGui (ScreenGui)
      • Frame
        • Title (TextLabel) : “SHOP”
        • BuySword (TextButton) : “Buy Sword (50)”
        • Close (TextButton) : “X”

    UI는 단순하게 텍스트만 있어도 된다.


    (2) 상점 열기용 ClickDetector 만들기

    Workspace에 Part 하나 생성
    이름: ShopButton (Anchored=true 추천)

    ShopButton 안에 ClickDetector 추가


    4. 클라이언트 코드 (UI 열기 + 구매 요청)

    StarterPlayer > StarterPlayerScripts에 LocalScript 생성: ShopClient

    local Players = game:GetService("Players")
    local ReplicatedStorage = game:GetService("ReplicatedStorage")
    
    local player = Players.LocalPlayer
    local purchaseEvent = ReplicatedStorage:WaitForChild("ShopPurchase")
    
    local shopGui = player:WaitForChild("PlayerGui"):WaitForChild("ShopGui")
    local frame = shopGui:WaitForChild("Frame")
    local buySwordBtn = frame:WaitForChild("BuySword")
    local closeBtn = frame:WaitForChild("Close")
    
    -- 기본은 닫힌 상태
    shopGui.Enabled = false
    
    -- 상점 열기(클릭)
    local shopButton = workspace:WaitForChild("ShopButton")
    local clickDetector = shopButton:WaitForChild("ClickDetector")
    
    clickDetector.MouseClick:Connect(function(clickedPlayer)
    	-- 로컬 플레이어만 열리게 보장
    	if clickedPlayer ~= player then return end
    	shopGui.Enabled = true
    end)
    
    -- 닫기
    closeBtn.MouseButton1Click:Connect(function()
    	shopGui.Enabled = false
    end)
    
    -- 구매 버튼
    buySwordBtn.MouseButton1Click:Connect(function()
    	-- 서버에 "무엇을" 살지 식별자 전달
    	purchaseEvent:FireServer("Sword")
    end)
    

    5. 서버 코드 (코인 차감 + 지급 처리)

    ServerScriptService에 Script 생성: ShopServer

    local ReplicatedStorage = game:GetService("ReplicatedStorage")
    local ServerStorage = game:GetService("ServerStorage")
    
    local purchaseEvent = ReplicatedStorage:WaitForChild("ShopPurchase")
    
    -- 상품 테이블(가격/지급 아이템)
    local PRODUCTS = {
    	Sword = {
    		price = 50,
    		toolName = "Sword"
    	},
    }
    
    local function getCoinsValue(player)
    	local leaderstats = player:FindFirstChild("leaderstats")
    	if not leaderstats then return nil end
    	return leaderstats:FindFirstChild("Coins")
    end
    
    purchaseEvent.OnServerEvent:Connect(function(player, productId)
    	local product = PRODUCTS[productId]
    	if not product then return end
    
    	local coins = getCoinsValue(player)
    	if not coins then return end
    
    	-- 코인 부족
    	if coins.Value < product.price then
    		return
    	end
    
    	-- 차감(서버 권한)
    	coins.Value -= product.price
    
    	-- 아이템 지급
    	local toolTemplate = ServerStorage:FindFirstChild(product.toolName)
    	if not toolTemplate then return end
    
    	local backpack = player:FindFirstChild("Backpack")
    	if not backpack then return end
    
    	local tool = toolTemplate:Clone()
    	tool.Parent = backpack
    end)
    

    6. 동작 확인 체크리스트

    1. 플레이어 입장 시 Coins = 100 표시됨
    2. ShopButton 클릭 → ShopGui 열림
    3. Buy Sword (50) 클릭 → Coins가 50 감소
    4. Backpack에 Sword Tool이 들어옴
    5. Coins < 50이면 더 이상 구매되지 않음

     

    반응형
Designed by Tistory.