คู่มือการใช้งานระดับกลาง

สร้างกระดานผู้นำแบบกำหนดเองด้วยข้อมูลที่เรียงลำดับ

*เนื้อหานี้แปลโดยใช้ AI (เวอร์ชัน Beta) และอาจมีข้อผิดพลาด หากต้องการดูหน้านี้เป็นภาษาอังกฤษ ให้คลิกที่นี่

Data stores เป็นบริการที่คุณสามารถใช้เพื่อบันทึกและโหลด ข้อมูลของผู้เล่นที่คงอยู่ ระหว่างเซสชันของผู้เล่นต่าง ๆ พวกมันเก็บข้อมูลที่สำคัญ เช่น ความก้าวหน้าของผู้เล่นหรือสิ่งของในคลังและอนุญาตให้คุณดึงข้อมูลนี้มาเพื่อผู้เล่นในครั้งถัดไปที่พวกเขาเข้าร่วมเกมส์ของคุณ หากไม่มี Data Store ผู้เล่นจะสูญเสียความก้าวหน้าทั้งหมดทุกครั้งเมื่อพวกเขาออกจากเกม

มี Data Store สองประเภท: มาตรฐานและเรียงลำดับ. บทช่วยสอนนี้ใช้ Data Store ที่เรียงลำดับ ซึ่งจะเก็บข้อมูลที่คุณสามารถจัดอันดับและเรียงลำดับแบบตัวเลขและดึงข้อมูลตามลำดับที่เก็บอย่างเพิ่มขึ้นหรือลดลงตามค่าตัวเลขที่เก็บไว้

ใช้ไฟล์ Gold Rush create leaderboard tutorial - Start .rbxl เป็นจุดเริ่มต้นและไฟล์ Gold Rush create leaderboard tutorial - Complete .rbxl เป็นข้อมูลอ้างอิง บทช่วยสอนนี้จะให้พื้นฐานที่คุณต้องการในการสร้างกระดานผู้นำของผู้เล่นแบบกำหนดเอง รวมถึงคำแนะนำใน:

  • การจัดเก็บคะแนนทองใน Data Store ที่เป็นระเบียบเรียบร้อย
  • การดึงและจัดเรียงคะแนนสูงสุดในระดับโลกจากเซิร์ฟเวอร์ต่าง ๆ
  • การแสดงคะแนนสูงสุดในกระดานผู้นำแบบกำหนดเองใน UI
  • การรีเฟรชกระดานผู้นำแบบกำหนดเองโดยอัตโนมัติทุก ๆ ไม่กี่วินาที

เมื่อสิ้นสุดบทช่วยสอนนี้ คุณควรมีดังนี้:

  1. ภายใต้ ServerScriptService:
    1. สคริปต์ GoldManager ที่อัปเดตซึ่งบันทึกคะแนนของผู้เล่นไปยัง Data Store ที่เรียงลำดับสำหรับกระดานผู้นำ
    2. โมดูลสคริปต์ใหม่ LeaderboardRemoteHandler ที่ดึงและส่งกลับรายการคะแนนสูงสุดที่เรียงลำดับจากกระดานผู้นำ
    3. สคริปต์ใหม่ LeaderboardManager ที่ตอบสนองต่อตำแหน่งข้อมูลกระดานผู้นำจากไคลเอนต์ ทำหน้าที่เป็นสะพานเชื่อมร่วมกับไคลเอนต์ใน LeaderboardGuiScript และเซิร์ฟเวอร์ใน LeaderboardManager
  2. ภายใต้ StarterGui เป็นสคริปต์ท้องถิ่นใหม่ LeaderboardGuiScript ที่แสดงผล UI กระดานผู้นำสำหรับผู้เล่น

เปิดใช้งานการเข้าถึง Studio ไปยังบริการ API

Data stores ไม่ได้ถูกเก็บไว้ในอุปกรณ์ของคุณ ดังนั้นเกมของคุณจึงขึ้นอยู่กับการสื่อสารจากเซิร์ฟเวอร์ไปยังเซิร์ฟเวอร์กับแบ็คเอนด์ของ Roblox เพื่อที่จะใช้มัน โดยค่าเริ่มต้น Studio จะจำกัดการสื่อสารนี้เพื่อป้องกันการละเมิดหรือการใช้งานโดยไม่ได้ตั้งใจ การเข้าถึงบริการ API ใน Studio ถูกปิดใช้งานจนกว่าคุณจะเปิดใช้งานอย่างชัดเจนเพื่อให้แน่ใจว่าเกมที่เชื่อถือได้เท่านั้นที่สามารถอ่านและเขียนจากเซิร์ฟเวอร์แบ็คเอนด์ของ Roblox ได้

เพื่อเปิดใช้งานการเข้าถึง Studio ไปยังบริการ API เพื่อให้คุณสามารถใช้ Data Store ได้:

  1. เปิดไฟล์ Gold Rush create leaderboard tutorial - Start ใน Studio ไฟล์จุดเริ่มต้นนี้มีโค้ดจากบทช่วยสอน บันทึกข้อมูลผู้เล่น และโครง UI สำหรับกระดานผู้นำของผู้เล่นแล้ว
  2. กลับไปที่ Studio ไปที่ FileExperience SettingsSecurity.
  3. เปิด Enable Studio Access to API Services.
  4. บันทึกการเปลี่ยนแปลงของคุณ.

สร้าง Data Store ที่เรียงลำดับ

เมื่อคุณสร้าง Data Store คุณควรเรียกใช้ DataStoreService จาก Script ด้านเซิร์ฟเวอร์เสมอ การทำเช่นนี้สำคัญเพราะ:

  • Roblox จะบล็อกการเข้าถึง Data Store จากไคลเอนต์เพื่อให้เฉพาะเซิร์ฟเวอร์เท่านั้นที่มีสิทธิ์เข้าถึงและแก้ไขข้อมูลผู้เล่นที่คงอยู่
  • สคริปต์ด้านเซิร์ฟเวอร์ทำงานในสภาพแวดล้อมที่รวมศูนย์ เพื่อให้มั่นใจว่าข้อมูลที่อ่านและเขียนลงใน Data Store ของคุณแม่นยำและถูกต้อง
  • เนื่องจากสคริปต์ด้านไคลเอนต์ทำงานบนอุปกรณ์ของผู้เล่น ผู้เล่นใดสามารถหาประโยชน์จากเกมและขโมยหรือเขียนข้อมูลของผู้เล่นอื่นได้หากไคลเอนต์มีการเข้าถึง Data Store ของคุณ

คุณยังควรตั้งชื่อ Data Store ให้เป็นเอกลักษณ์เพื่อทำให้ข้อมูลของคุณจัดระเบียบและเพื่อป้องกันไม่ให้ข้อมูลซ้อนทับหรือขัดแย้งใน Data Store ต่าง ๆ ในบทช่วยสอนนี้ Data Store สำหรับกระดานผู้นำเรียกว่า GlobalLeaderboard.

ในการสร้าง Data Store ที่เรียงลำดับ GlobalLeaderboard:

  1. เปิดสคริปต์ GoldManager ที่มีอยู่ภายใต้ ServerScriptService.

  2. ใต้ Data Store PlayerGold ที่มีอยู่ เรียกใช้ GetOrderedDataStore โดยใช้สตริง "GlobalLeaderboard" นี่จะสร้าง Data Store ที่เรียงลำดับเพื่อบันทึกคะแนนของผู้เล่นเมื่อพวกเขาได้รับทองคำ


    local leaderboardStore = DataStoreService:GetOrderedDataStore("GlobalLeaderboard")

หลังจากสร้าง Data Store แล้ว คุณสามารถอ้างอิง Data Store นี้ในสคริปต์ต่าง ๆ ได้ ตัวอย่างเช่น คุณสามารถเรียกใช้ GetOrderedDataStore ในทั้งสคริปต์ GoldManager และโมดูลสคริปต์ LeaderboardManager ที่คุณจะสร้างต่อไปในบทช่วยสอนนี้ การอ้างอิง Data Store เดียวกันในสองที่ไม่ได้หมายความว่าคุณกำลังทำให้ข้อมูลซ้ำซ้อน; แค่หมายความว่าสคริปต์สองตัวกำลังเข้าถึงการจัดเก็บข้อมูลที่รวมศูนย์เดียวกัน เหมือนกับเพื่อนร่วมทีมสองคนที่ใช้โฟลเดอร์เดียวกันเพื่อแชร์ข้อมูล

ส่งข้อมูลผู้เล่นไปยังกระดานผู้นำ

Data Store ประกอบด้วยคีย์ซึ่งใช้ระบุข้อมูล และค่าซึ่งใช้บันทึกข้อมูล ไม่เหมือนกับ Data Store มาตรฐาน Data Store ที่เรียงลำดับช่วยให้คุณจัดเรียงข้อมูลตาม ค่า ซึ่งทำให้เหมาะสมสำหรับการสร้างสิ่งของเช่นกระดานผู้นำ

แต่ละรายการใน Data Store ที่เรียงลำดับจะถูกเก็บไว้ภายใต้คีย์ที่ไม่ซ้ำกันซึ่งคุณสามารถจัดอันดับและเรียงลำดับแบบตัวเลขได้ จากนั้นดึงข้อมูลในลำดับเพิ่มหรือ ลดลงตามค่าตัวเลขที่เก็บไว้ นี่หมายความว่าคุณสามารถใช้ Data Store ที่เรียงลำดับเพื่อแสดงรายการ 3 อันดับที่อัปเดตแบบเรียลไทม์เมื่อผู้เล่นในเกมของคุณเก็บทองคำมากขึ้น

คีย์ค่า
คำอธิบายคีย์คือสตริงที่ไม่ซ้ำกันที่คุณสามารถใช้เพื่อเข้าถึงข้อมูลเฉพาะอย่างเช่น ID ผู้ใช้ของผู้เล่น

คีย์ช่วยให้คุณจัดระเบียบข้อมูลเพื่อให้คุณจัดการและดีบักได้ง่าย
ค่าเป็นข้อมูลเชิงตัวเลขจริงที่คุณต้องการบันทึกหรือโหลด เช่น คะแนนของผู้เล่น

ค่าช่วยให้คุณจัดเก็บความก้าวหน้าระหว่างเซสชัน รวมถึงดึงข้อมูลของผู้เล่นในการเข้าร่วมเกมในครั้งถัดไป
รูปแบบที่อนุญาตเป็นสตริงเท่านั้น หากคุณใช้หมายเลข เช่น ID ผู้ใช้ ให้แปลงเป็นสตริงโดยใช้ tostring().เป็นตัวเลขเท่านั้น
ตัวอย่าง"Player_A", "TopScore", "123456" (userID เป็นสตริง)100, 3.14, 0, -25

เมื่อคุณสร้าง Data Store GlobalLeaderboard แล้ว ให้ปรับปรุงฟังก์ชัน saveGold ที่มีอยู่ในสคริปต์ GoldManager เพื่อส่งคะแนนทองของผู้เล่นไปยังกระดานผู้นำที่กำหนดเองของคุณด้วย SetAsync:


local function saveGold(player, value)
local userId = player.UserId
local success, err = pcall(function()
goldStore:SetAsync(userId, value)
leaderboardStore:SetAsync(tostring(userId), value)
end)
if not success then
warn("ไม่สามารถบันทึกทองคำสำหรับ", player.Name, ":", err)
end
end

คุณสามารถคิดถึง Data Store ที่เรียงลำดับ GlobalLeaderboard เหมือนโฟลเดอร์ที่แชร์: SetAsync จะเพิ่มเนื้อหาในโฟลเดอร์ ในขณะที่ GetSortedAsync (ซึ่งคุณจะสร้างในโมดูลสคริปต์ LeaderboardManager ในภายหลัง) จะอ่านเนื้อหาในโฟลเดอร์และจัดเรียงตามคะแนน

ดึงคะแนนจากกระดานผู้นำ

ในการดึงคะแนนจากกระดานผู้นำ คุณควรใช้ ModuleScript. โมดูลสคริปต์ช่วยให้คุณจัดระเบียบและนำกลับมาใช้ใหม่โค้ดของคุณข้ามสคริปต์หลายตัว แทนที่จะคัดลอกตรรกะเดียวกันไปยังหลายที่ คุณสามารถเขียนโค้ดครั้งเดียวในโมดูลสคริปต์และเรียกใช้จากทุกที่ที่ต้องการ

เมื่อคุณจัดเก็บตรรกะกระดานผู้นำของคุณในโมดูล ไคลเอนต์แฮนด์เลอร์และสคริปต์เซิร์ฟเวอร์ต่าง ๆ สามารถใช้ฟังก์ชันเดียวกันเพื่อดึงคะแนนผู้เล่นสูงสุด หากคุณต้องการอัปเดตว่า ดึงชื่อผู้ใช้หรือจัดเรียงคะแนนอย่างไร คุณเพียงแค่ต้องเปลี่ยนโค้ดในที่เดียว หลังจากที่คุณปรับปรุงโมดูล สคริปต์อื่น ๆ ที่ใช้มันก็จะได้พฤติกรรมแบบอัปเดตโดยอัตโนมัติ

กระดานผู้นำที่กำหนดเองของคุณใช้วิธี Data Store ที่เรียงลำดับดังต่อไปนี้ในการแชร์ข้อมูลระหว่างเซิร์ฟเวอร์ต่าง ๆ:

  • SetAsync (จากสคริปต์ GoldManager) เพื่อส่งคะแนนผู้เล่นไปยัง Data Store ที่เรียงลำดับ GlobalLeaderboard
  • GetSortedAsync (ในโมดูลสคริปต์) เพื่อดึงคะแนนสูงสุดจากเซิร์ฟเวอร์ทั้งหมดจาก Data Store เดียวกัน วิธี GetSortedAsync เป็นเอกลักษณ์ของ Data Store ที่เรียงลำดับและสามารถดึงคีย์ที่เรียงลำดับหลายตัวตามลำดับการจัดเรียงเฉพาะ ขนาดหน้า และค่าต่ำสุดและสูงสุด

ในการดึงคะแนนจากกระดานผู้นำ:

  1. ภายใต้ ServerScriptService ให้สร้าง ModuleScript ใหม่ชื่อ LeaderboardManager.

  2. ที่ด้านบนของโมดูลสคริปต์ เรียกใช้ GetOrderedDataStore ด้วยสตริง "GlobalLeaderboard" การอ้างอิง Data Store ที่เรียงลำดับเดียวกันที่คุณสร้างในสคริปต์ GoldManager จะช่วยให้ UI ของกระดานผู้นำดึงและจัดเรียงคะแนนผู้เล่นสูงสุดได้ในภายหลัง


    local DataStoreService = game:GetService("DataStoreService")
    local Players = game:GetService("Players")
    local leaderboardStore = DataStoreService:GetOrderedDataStore("GlobalLeaderboard")
  3. เตรียมตารางโมดูลเพื่อเก็บฟังก์ชันและข้อมูลทั้งหมดที่คุณต้องการเปิดเผยให้กับสคริปต์อื่น


    local leaderboardManager = {}
  4. สร้างฟังก์ชันที่เรียกว่า GetTopScores เพื่อดึงคะแนนผู้เล่นสูงสุด ฟังก์ชันนี้จะ:

    • เรียกใช้ GetSortedAsync เพื่อดึงคะแนนสูงสุดจำนวน limit ในลำดับลดลง หากการเรียกไม่สำเร็จ จะส่งกลับการแจ้งเตือนว่างเพื่อป้องกันไม่ให้โค้ดของคุณล้มเหลว
    • วนรอบผ่านกระดานผู้นำเพื่อให้ได้ตารางของรายชื่อด้วย GetCurrentPage และชื่อผู้เล่นด้วย GetNameFromUserIdAsync
    • เพิ่มผลลัพธ์แต่ละรายการลงในรายการสุดท้ายและสร้างตารางกระดานผู้นำที่มีชื่อผู้เล่นและคะแนนของพวกเขา
    • ส่งกลับรายการสุดท้ายของผู้เล่นและส่งข้อมูลกระดานผู้นำกลับไปยังสคริปต์ใด ๆ ที่เรียกฟังก์ชัน leaderboardManager.GetTopScores

    function leaderboardManager.GetTopScores(limit)
    local success, pages = pcall(function()
    return leaderboardStore:GetSortedAsync(false, limit)
    end)
    if not success or not pages then
    return {}
    end
    local results = {}
    for _, entry in ipairs(pages:GetCurrentPage()) do
    local userId = tonumber(entry.key)
    local score = entry.value
    local username = "Unknown"
    local ok, name = pcall(function()
    return Players:GetNameFromUserIdAsync(userId)
    end)
    if ok then
    username = name
    end
    table.insert(results, {
    Username = username,
    Score = score
    })
    end
    return results
    end
  5. ทำให้โมดูลใช้งานได้โดยการส่งคืนตารางโมดูลที่คุณสร้างขึ้นก่อนหน้านี้ เมื่อตั้งค่าโมดูลสคริปต์ คุณต้องส่งคืนตารางโมดูลเพื่อให้สคริปต์อื่นสามารถเข้าถึงมันและเรียกฟังก์ชันภายใน


    return leaderboardManager

ขอข้อมูลกระดานผู้นำจากเซิร์ฟเวอร์

เพื่อให้ UI ของไคลเอนต์แสดงคะแนนจากกระดานผู้นำ เซิร์ฟเวอร์ต้องตอบสนองเมื่อไคลเอนต์ขอข้อมูล RemoteFunction ช่วยให้ไคลเอนต์สามารถร้องขอข้อมูลจากเซิร์ฟเวอร์และรอคำตอบได้

ร้องขอข้อมูลจากกระดานผู้นำจากเซิร์ฟเวอร์:

  1. ภายใต้ ReplicatedStorage ใส่ RemoteFunction ที่เรียกว่า LeaderboardRemote ฟังก์ชันระยะไกลนี้ทำหน้าที่เป็นสะพานเชื่อมระหว่างสคริปต์ UI บนไคลเอนต์และตรรกะกระดานผู้นำบนเซิร์ฟเวอร์
  2. ภายใต้ ServerScriptService ให้สร้างสคริปต์ชื่อ LeaderboardRemoteHandler ในสคริปต์นี้:
    1. เรียกใช้ ReplicatedStorage (พื้นที่แชร์ระหว่างไคลเอนต์และเซิร์ฟเวอร์), ServerScriptService (ซึ่งถือโมดูลกระดานผู้นำ), และ leaderboardRemote (ฟังก์ชันระยะไกลที่ไคลเอนต์จะเรียกเพื่อขอข้อมูลกระดานผู้นำ)


      local ReplicatedStorage = game:GetService("ReplicatedStorage")
      local ServerScriptService = game:GetService("ServerScriptService")
      local leaderboardRemote = ReplicatedStorage:WaitForChild("LeaderboardRemote")
    2. โหลดโมดูล LeaderboardManager ที่คุณสร้างขึ้นก่อนหน้านี้ ซึ่งรวมถึงฟังก์ชันที่ดึงคะแนนสูงสุดจาก Data Store ที่เรียงลำดับ


      local leaderboardManager = require(ServerScriptService:WaitForChild("LeaderboardManager"))
    3. ตั้งค่าพฤติกรรมสำหรับเมื่อไคลเอนต์เรียกใช้ InvokeServer. เซิร์ฟเวอร์ตอบสนองโดยการดึงคะแนนสูงสุด 3 คะแนนและส่งผลลัพธ์กลับไปยังไคลเอนต์


      leaderboardRemote.OnServerInvoke = function(player)
      return leaderboardManager.GetTopScores(3)
      end

แสดงข้อมูลใน UI กระดานผู้นำแบบกำหนดเอง

หลังจากตั้งค่าสคริปต์ด้านเซิร์ฟเวอร์แล้ว ให้สร้างสคริปต์ท้องถิ่นเพื่อดึง 3 อันดับแรกทุก 3 วินาทีและแสดงผลลัพธ์ใน UI กระดานผู้นำทั่วโลกภายในเกม

ในการแสดงข้อมูลในกระดานผู้นำแบบกำหนดเองของคุณ:

  1. ภายใต้ StarterGuiLeaderboardGui สร้างสคริปต์ท้องถิ่นชื่อ LeaderboardGuiScript.

  2. ที่ด้านบนของสคริปต์ เชื่อมต่อกับฟังก์ชันระยะไกล เรียกใช้ ReplicatedStorage เพื่อเข้าถึงวัตถุที่แชร์ระหว่างเซิร์ฟเวอร์และไคลเอนต์ จากนั้นเรียกใช้ leaderboardRemote เพื่อให้ไคลเอนต์สามารถร้องขอข้อมูลกระดานผู้นำจากเซิร์ฟเวอร์ได้


    local ReplicatedStorage = game:GetService("ReplicatedStorage")
    local leaderboardRemote = ReplicatedStorage:WaitForChild("LeaderboardRemote")
  3. อ้างอิง UI สิ่งของกระดานผู้นำที่มีอยู่ภายใต้ LeaderboardGui.


    local gui = script.Parent
    local leaderboardFrame = gui:WaitForChild("LeaderboardFrame")
    local entriesFrame = leaderboardFrame:WaitForChild("EntriesFrame")
    local template = entriesFrame:WaitForChild("LeaderboardEntry")
  4. สร้างฟังก์ชันที่เรียกว่า clearEntries เพื่อล้างรายการกระดานผู้นำเก่า ฟังก์ชันนี้วนรอบผ่านเด็ก ๆ ทั้งหมดของ entriesFrame ซึ่งมีแถวกระดานผู้นำ และให้แน่ใจว่ากระดานผู้นำจะถูกอัปเดตเต็มที่ก่อนแสดงข้อมูลใหม่


    local function clearEntries()
    for _, child in ipairs(entriesFrame:GetChildren()) do
    if child:IsA("TextLabel") and child.Name:match("^Row%d+$") then
    child:Destroy()
    end
    end
    end
  5. สร้างฟังก์ชันที่เรียกว่า renderLeaderboard เพื่อแทรกและแสดงข้อมูลผู้เล่นในแถวกระดานผู้นำ อ็อบเจกต์ data คือตารางที่ส่งคืนโดยเซิร์ฟเวอร์ซึ่งมีรายการที่มีชื่อผู้เล่นและคะแนน


    local function renderLeaderboard(data)
    clearEntries()
    for i, entry in ipairs(data) do
    local row = template:Clone()
    row.Name = "Row" .. i
    row.Visible = true
    row.LayoutOrder = i
    row.Text = string.format("%d%s place: %s - %d",
    i, i == 1 and "st" or i == 2 and "nd" or i == 3 and "rd" or "th",
    entry.Username, entry.Score)
    row.Parent = entriesFrame
    end
    end
  6. สร้างลูปเพื่อดึงข้อมูลของกระดานผู้นำเป็นระยะ ๆ ทุก 3 วินาที ลูปทำงานและเรียกเซิร์ฟเวอร์โดยใช้ฟังก์ชัน InvokeServer ที่คุณสร้างขึ้นก่อนหน้านี้ในสคริปต์ LeaderboardRemoteHandler หากการเรียกล้มเหลว UI จะถูกรีเฟรชด้วยคะแนนที่อัปเดต


    while true do
    local success, data = pcall(function()
    return leaderboardRemote:InvokeServer()
    end)
    if success and data then
    renderLeaderboard(data)
    end
    task.wait(3)
    end

โค้ดสุดท้าย

ดูส่วนโค้ดด้านล่างสำหรับ GoldManager, LeaderboardManager, LeaderboardRemoteHandler, และ LeaderboardGuiScript สคริปต์ทั้งหมด คุณสามารถวางและรันพวกมันในไฟล์ Gold Rush create leaderboard tutorial - Start .rbxl ใน Studio ได้อย่างตรงไปตรงมา

GoldManager

สคริปต์ GoldManager สร้าง Data Store ที่เรียงลำดับเพื่อจัดการการอัปเดตกระดานผู้นำ


-- ดึงบริการต่าง ๆ
local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local CollectionService = game:GetService("CollectionService")
local DataStoreService = game:GetService("DataStoreService")
-- อีเวนต์ระยะไกลเพื่อติดตาม UI
local uiEvent = ReplicatedStorage:WaitForChild("UIEvent")
-- Data Store สำหรับบันทึกทองคำที่เป็นก้อนของผู้เล่น
local goldStore = DataStoreService:GetDataStore("PlayerGold")
-- Data Store ที่เรียงลำดับเพื่อบันทึกทองคำไปยังกระดานผู้นำ
local leaderboardStore = DataStoreService:GetOrderedDataStore("GlobalLeaderboard")
-- สร้างตัวสร้างหมายเลขสุ่มสำหรับการจัดตำแหน่งทองคำ
local random = Random.new()
-- ตารางเพื่อเก็บทองคำของผู้เล่นในเซสชันเดียว
local playerGold = {}
-- ค่าคงที่
local GOLD_VALUE = 10 -- จำนวนทองคำที่ก้อนทองคำแต่ละก้อนมีค่า
local GOLD_REGENERATION_BOUNDS = { -- ขอบเขตพื้นที่ที่ใช้ในการจัดตำแหน่งทองคำให้สุ่ม
minX = -72,
maxX = 72,
minZ = -72,
maxZ = 72
}
local GOLD_REGEN_DELAY = 2 -- ความล่าช้าก่อนที่จะแสดงทองคำใหม่ (ในวินาที)
local AUTOSAVE_INTERVAL = 30 -- ความถี่ที่ทองคำของผู้เล่นจะถูกบันทึก (ในวินาที)
-- ฟังก์ชันเพื่อจัดการการเก็บทองคำของผู้เล่น
local function processGoldTouch(chunk, player)
-- ซ่อนก้อนทองเมื่อผู้เล่นเก็บมันไป
chunk.Parent = nil
-- เพิ่มก้อนทองเข้ากับคะแนนทองคำของผู้เล่นในเซสชัน
local userId = player.UserId
playerGold[userId] = (playerGold[userId] or 0) + GOLD_VALUE
print(player.Name, "มีทองคำ", playerGold[userId], "ก้อนแล้ว")
-- อัปเดต UI แถบคะแนนเพื่อสะท้อนคะแนนทองคำใหม่ในเซสชันนี้
uiEvent:FireClient(player, {
gold = playerGold[userId],
doTween = true,
showAlert = false
})
-- รอสักครู่แล้วจึงแสดงก้อนทองที่ถูกเก็บในตำแหน่งสุ่มใหม่
task.delay(GOLD_REGEN_DELAY, function()
-- นำก้อนทองไปยังตำแหน่งสุ่มใหม่
local nextPositionX = random:NextInteger(GOLD_REGENERATION_BOUNDS.minX, GOLD_REGENERATION_BOUNDS.maxX)
local nextPositionZ = random:NextInteger(GOLD_REGENERATION_BOUNDS.minZ, GOLD_REGENERATION_BOUNDS.maxZ)
chunk.CFrame = CFrame.new(nextPositionX, 50, nextPositionZ) -- ย้ายก้อนทองไปยังตำแหน่งใหม่
chunk:SetAttribute("DropCollided", false) -- รีเซ็ตธงข้อขัดข้อง
chunk.Parent = workspace.GoldChunks
end)
end
-- วนรอบผ่านทุกส่วนที่ติดแท็กว่า "Gold" และเชื่อมต่อเข้ากับการตรวจจับการสัมผัส
for _, chunk in ipairs(CollectionService:GetTagged("Gold")) do
chunk.Touched:Connect(function(otherPart)
local player = Players:GetPlayerFromCharacter(otherPart.Parent)
if player then
processGoldTouch(chunk, player)
end
end)
end
-- ฟังก์ชันเพื่อบันทึกทองคำของผู้เล่นลงใน Data Store ทั้งแบบมาตรฐานและแบบเรียงลำดับ
local function saveGold(player, value)
local userId = player.UserId
local success, err = pcall(function()
goldStore:SetAsync(userId, value)
leaderboardStore:SetAsync(tostring(userId), value)
end)
if not success then
warn("ไม่สามารถบันทึกทองคำสำหรับ", player.Name, ":", err)
end
end
-- ฟังก์ชันเพื่อจัดการผู้เล่นที่เข้าร่วมเกม
local function onPlayerAdded(player)
local userId = player.UserId
print(player.Name, "เข้าร่วมเกมแล้ว")
-- พยายามโหลดทองคำของผู้เล่นจาก Data Store
local success, storedGold = pcall(function()
return goldStore:GetAsync(userId)
end)
-- ตั้งค่าคะแนนทองคำในเซสชันปัจจุบันโดยใช้ค่าจาก Data Store สำหรับผู้เล่น
local currentGold = if success and storedGold then storedGold else 0
playerGold[userId] = currentGold
-- อัปเดต UI ด้วยค่าจาก Data Store สำหรับผู้เล่น
uiEvent:FireClient(player, {
gold = currentGold,
doTween = false,
showAlert = not success
})
if success then
print("โหลด", currentGold, "ทองคำ สำหรับ", player.Name)
else
-- แจ้งผู้เล่นว่าทองคำของพวกเขาไม่สามารถโหลดได้
uiEvent:FireClient(player, { showAlert = true })
warn("ไม่สามารถโหลดทองคำสำหรับ", player.Name)
end
-- เริ่มการอัปเดตอัตโนมัติเพื่อลงบันทึกทองคำของผู้เล่นทุก 30 วินาที
coroutine.wrap(function()
while player.Parent do
task.wait(AUTOSAVE_INTERVAL)
if playerGold[userId] then
saveGold(player, playerGold[userId])
print("บันทึกทองคำ", playerGold[userId], "สำหรับ", player.Name)
end
end
end)()
end
-- ฟังก์ชันเพื่อจัดการผู้เล่นที่ออกจากเกม
local function onPlayerRemoving(player)
local userId = player.UserId
print(player.Name, "ออกจากเกม")
-- ตรวจสอบว่าทองคำของผู้เล่นได้รับการติดตามไหม
if playerGold[userId] then
-- บันทึกทองคำของผู้เล่นลงใน Data Store ก่อนที่เขาจะออก
saveGold(player, playerGold[userId])
end
end
-- เชื่อมต่อเหตุการณ์ผู้เล่นที่เข้าร่วมและออกจากเกม
Players.PlayerAdded:Connect(onPlayerAdded)
Players.PlayerRemoving:Connect(onPlayerRemoving)

LeaderboardManager

โมดูลสคริปต์ LeaderboardManager:

  • เรียก GetSortedAsync() บน Data Store ที่เรียงลำดับ GlobalLeaderboard
  • แปลง userIds เป็นชื่อผู้ใช้โดยใช้ GetNameFromUserIdAsync.
  • ส่งคืนรายการของ { Username, Score } ตารางสำหรับผู้เล่นที่ถูกจัดอันดับสูงสุด
  • ถูกเรียกโดย LeaderboardRemoteHandler เมื่อใดก็ตามที่ไคลเอนต์ร้องขอข้อมูลกระดานผู้นำ

-- ดึงบริการต่าง ๆ
local Players = game:GetService("Players")
local DataStoreService = game:GetService("DataStoreService")
-- Data Store ที่เรียงลำดับสำหรับบันทึกคะแนนกระดานผู้นำ
local leaderboardStore = DataStoreService:GetOrderedDataStore("GlobalLeaderboard")
-- ตารางสำหรับจัดเก็บคะแนนกระดานผู้นำ
local leaderboardManager = {}
-- ฟังก์ชันเพื่อส่งคืนคะแนนสูงสุด
function leaderboardManager.GetTopScores(limit)
-- พยายามดึงรายการกระดานผู้นำที่เรียงลำดับจาก Data Store
local success, pages = pcall(function()
-- false = ลดลง (คะแนนสูงสุดมาก่อน)
return leaderboardStore:GetSortedAsync(false, limit)
end)
-- หากการเรียกล้มเหลวหรือไม่ส่งคืนอะไรเลย ให้บันทึกข้อควรระวังและส่งกลับตารางเปล่า
if not success or not pages then
warn("ไม่สามารถดึงข้อมูลกระดานผู้นำได้")
return {}
end
-- สร้างตารางสำหรับเก็บข้อมูลผู้เล่นระดับสูง
local topPlayers = {}
-- วนลูปผ่านแต่ละรายการในหน้าผลลัพธ์กระดานผู้นำ
for _, entry in ipairs(pages:GetCurrentPage()) do
local userId = tonumber(entry.key) -- แปลงกุญแจของรายการเป็นหมายเลข (userId ถูกจัดเก็บเป็นสตริง)
local score = entry.value -- ค่าเป็นคะแนนของผู้เล่น (จำนวนทองคำ)
local username = "Unknown" -- ชื่อเริ่มต้นในกรณีที่การค้นหาล้มเหลว
-- พยายามที่จะดึงชื่อผู้เล่นจาก userId ของพวกเขา
local ok, name = pcall(function()
return Players:GetNameFromUserIdAsync(userId)
end)
-- หากการค้นหาประสบความสำเร็จ ให้เก็บชื่อผู้ใช้จริง
if ok then
username = name
end
-- เพิ่มผู้เล่นนี้และคะแนนของเขาไปยังรายการ
table.insert(topPlayers, {
Username = username,
Score = score
})
end
-- ส่งคืนรายการผู้เล่นชั้นนำที่มีชื่อผู้ใช้และคะแนน
return topPlayers
end
-- ส่งคืนโมดูล LeaderboardManager เพื่อให้สคริปต์อื่นสามารถใช้งานได้
return leaderboardManager

LeaderboardRemoteHandler

สคริปต์ LeaderboardRemoteHandler ดึงและส่งคืนคะแนนสูงสุด 3 คะแนนไปยังไคลเอนต์ที่เรียก


-- ดึงบริการต่าง ๆ
local ServerScriptService = game:GetService("ServerScriptService") -- เข้าถึงโมดูลด้านเซิร์ฟเวอร์
local ReplicatedStorage = game:GetService("ReplicatedStorage") -- วัตถุที่ใช้ในการสื่อสารระหว่างไคลเอนต์กับเซิร์ฟเวอร์
-- รอให้ RemoteFunction ที่ไคลเอนต์ใช้ร้องขอข้อมูลกระดานผู้นำ
local leaderboardRemote = ReplicatedStorage:WaitForChild("LeaderboardRemote")
-- โหลดโมดูล LeaderboardManager ที่มีฟังก์ชัน GetTopScores
local leaderboardManager = require(ServerScriptService:WaitForChild("LeaderboardManager"))
-- ตั้งค่าการจัดการเมื่อไคลเอนต์เรียกใช้ฟังก์ชัน RemoteFunction ของกระดานผู้นำ
leaderboardRemote.OnServerInvoke = function(player)
-- เรียกใช้โมดูลกระดานผู้นำเพื่อดึงคะแนนสูงสุด 3 คะแนนและส่งกลับไปยังไคลเอนต์
return leaderboardManager.GetTopScores(3)
end

LeaderboardGuiScript

สคริปต์ท้องถิ่น LeaderboardGuiScript:

  • ร้องขอข้อมูลกระดานผู้นำจากเซิร์ฟเวอร์ทุก 3 วินาทีโดยใช้ Class.RemoteHandler.InvokeServer|InvokeServer.
  • ใช้เทมเพลต LeaderboardEntry ที่ซ่อนเพื่อแสดงแต่ละแถวของกระดานผู้นำ
  • จัดรูปแถวแต่ละแถวในรูปแบบ "1st place: Username - Score".
  • จัดการการสร้าง การแสดง และการจัดเลย์เอาต์ของแถวกระดานผู้นำโดยใช้ UIListLayout.

-- ดึงการจัดเก็บข้อมูลสำหรับการเข้าถึง RemoteFunction
local ReplicatedStorage = game:GetService("ReplicatedStorage")
-- ดึง RemoteFunction ที่ใช้ร้องขอข้อมูลกระดานผู้นำจากเซิร์ฟเวอร์
local leaderboardRemote = ReplicatedStorage:WaitForChild("LeaderboardRemote")
-- การอ้างอิง UI
local gui = script.Parent -- สคริปต์ท้องถิ่นภายใต้ ScreenGui
local leaderboardFrame = gui:WaitForChild("LeaderboardFrame") -- ตัวเก็บข้อมูลหลักสำหรับกระดานผู้นำ
local entriesFrame = leaderboardFrame:WaitForChild("EntriesFrame") -- เฟรมที่รายการคะแนนกระดานผู้นำปรากฏ
local template = entriesFrame:WaitForChild("LeaderboardEntry") -- TextLabel ที่เป็นเทมเพลตซ่อนที่ใช้สร้างแถว
-- ฟังก์ชันเพื่อลบแถวกระดานผู้นำเก่า (แต่ไม่ใช่เทมเพลต)
local function clearEntries()
for _, child in ipairs(entriesFrame:GetChildren()) do
-- ทำลายเฉพาะเลเบลที่ชื่อว่า "Row1", "Row2" เป็นต้น (เว้นแต่เทมเพลตเอาไว้)
if child:IsA("TextLabel") and child.Name:match("^Row%d+$") then
child:Destroy()
end
end
end
-- ฟังก์ชันเพื่อแสดงข้อมูลกระดานผู้นำบนจอ
local function renderLeaderboard(data)
-- ลบแถวเก่าก่อน
clearEntries()
for i, entry in ipairs(data) do
local row = template:Clone() -- โคลนเทมเพลตที่ซ่อนอยู่
row.Name = "Row" .. i -- ตั้งชื่อให้มีลักษณะเฉพาะ
row.Visible = true -- ทำให้มันแสดง
row.LayoutOrder = i -- ปล่อยให้ UIListLayout จัดลำดับมันได้อย่างถูกต้อง
-- รูปแบบกระดานผู้นำ: "1st place: Username - 123"
row.Text = string.format("%d%s place: %s - %d",
i,
i == 1 and "st" or i == 2 and "nd" or i == 3 and "rd" or "th",
entry.Username,
entry.Score
)
-- เพิ่มข้อมูลลงใน UI
row.Parent = entriesFrame
end
end
-- ลูปหลัก: อัปเดตกระดานผู้นำทุก 3 วินาที
while true do
-- ถามเซิร์ฟเวอร์เกี่ยวกับข้อมูลของกระดานผู้นำ
local success, data = pcall(function()
return leaderboardRemote:InvokeServer()
end)
if success and data then
-- แสดงผลลัพธ์บนกระดานผู้นำ
renderLeaderboard(data)
else
warn("ไม่สามารถดึงข้อมูลกระดานผู้นำได้")
end
-- รอ 3 วินาทีแล้วค่อยอัปเดตอีกครั้ง
task.wait(3)
end
©2026 Roblox Corporation. Roblox, โลโก้ Roblox และ Powering Imagination เป็นส่วนหนึ่งของเครื่องหมายการค้าที่จดทะเบียน และไม่ได้จดทะเบียนของเราในสหรัฐฯ และประเทศอื่นๆ