دروس تعليمية متوسطة

حفظ بيانات اللاعبين باستخدام مخازن البيانات القياسية

*This content is translated using AI (Beta) and may contain errors. To view this page in English, click here.

مخازن البيانات هي خدمة يمكنك استخدامها لحفظ وتحميل بيانات اللاعبين المستمرة عبر جلسات اللاعبين المختلفة. تخزن معلومات هامة، مثل تقدم اللاعب أو مخزونه، وتتيح لك استرجاعها للاعب في المرة القادمة التي ينضم فيها إلى لعبتك. بدون مخازن البيانات، سيخسر اللاعب جميع تقدمه في كل مرة يغادر فيها اللعبة.

هناك نوعان من مخازن البيانات: القياسية والمرتبة. يستخدم هذا البرنامج التعليمي مخازن البيانات القياسية، والتي تخزن البيانات مثل الأرقام والسلاسل والجداول التي لا تحتاج إلى ترتيب أو فرز.

باستخدام دليل مخزن بيانات جولد راش - البداية .rbxl كنقطة انطلاق ودليل مخزن بيانات جولد راش - الكاملة .rbxl كمرجع، يوفر لك هذا البرنامج التعليمي الأساس الذي تحتاجه لحفظ تقدم اللاعبين وإنشاء ألعاب أكثر اتساقًا، بما في ذلك إرشادات حول:

  • حفظ وتحميل كمية الذهب التي جمعها اللاعب.
  • تحديث واجهة المستخدم لعرض مخزون الذهب الخاص باللاعب.
  • حفظ مخزون الذهب الخاص باللاعب تلقائيًا كل 30 ثانية.
  • حفظ موقع اللاعب عندما يغادر اللعبة.
  • استعادة موقع اللاعب عندما ينضم إلى اللعبة مرة أخرى.

بنهاية هذا البرنامج التعليمي، يجب أن تحتوي على نصين برمجيين مع مخازن بيانات تحت ServerScriptService:

  1. نص برمجي محدث مدير الذهب يتتبع ويحمل ويحفظ تلقائيًا ذهب اللاعب.
  2. نص برمجي محدث مدير الموقع الذي يحفظ موقع اللاعب عند مغادرته اللعبة ويستعيد موقعه عند عودته إلى اللعبة.

تمكين الوصول إلى Studio لخدمات API

لا تُخزن مخازن البيانات محليًا على جهازك، لذلك تعتمد لعبتك على الاتصال من خادم إلى خادم مع البنية التحتية لروبلكس لاستخدامها. بشكل افتراضي، يقيّد Studio هذا الاتصال لمنع إساءة الاستخدام أو الاستخدام غير المقصود. يعد الوصول إلى خدمات API في Studio غير مفعل حتى تقوم بتمكينه صراحةً لضمان أن الألعاب الموثوقة فقط يمكنها القراءة من وكتابة إلى خوادم روبلكس.

لتمكين الوصول إلى Studio لخدمات API بحيث يمكنك استخدام مخازن البيانات:

  1. افتح ملف دليل مخزن بيانات جولد راش - البداية .rbxl في Studio وأنشئ نسخة محلية.
  2. عد إلى Studio، وانتقل إلى ملفإعدادات التجربةالأمان.
  3. قم بتشغيل تمكين الوصول إلى Studio لخدمات API.
  4. احفظ تغييراتك.

إنشاء مخزن بيانات قياسي

عند إنشاء مخزن بيانات، يجب عليك دائمًا استدعاء DataStoreService من Script جانب الخادم. يعد ذلك مهمًا لأن:

  • تحظر روبلكس الوصول إلى جميع مخازن البيانات من العميل بحيث يكون للخادم فقط إذن بالوصول إلى بيانات اللاعبين المستمرة وتعديلها.
  • تعمل النصوص البرمجية جانب الخادم في بيئة مركزية، مما يضمن أن البيانات التي تتم قراءتها وكتابتها إلى مخزن البيانات الخاص بك دقيقة وصحيحة.
  • نظرًا لأن النصوص البرمجية جانب العميل تعمل على جهاز اللاعب، يمكن لأي لاعب استغلال اللعبة وسرقة أو الكتابة فوق بيانات لاعبين آخرين إذا كان للعميل وصول إلى مخازن البيانات الخاصة بك.

يجب عليك أيضًا إعطاء مخزن البيانات الخاص بك اسمًا فريدًا للحفاظ على تنظيم بياناتك ولمنعها من التداخل أو التعارض في مخازن البيانات المختلفة. في هذا البرنامج التعليمي، يُطلق على مخزن البيانات الذي يحفظ ويخزن مخزون الذهب الخاص باللاعب PlayerGold.

لإنشاء مخزن بيانات PlayerGold:

  1. افتح نص مدير الذهب الموجود تحت ServerScriptService.

  2. تحت الخدمات الأخرى في أعلى النص، قم بتهيئة DataStoreService واستدعي GetDataStore مع السلسلة "PlayerGold".


    local DataStoreService = game:GetService("DataStoreService")
    local goldStore = DataStoreService:GetDataStore("PlayerGold")

حفظ وتحميل بيانات اللاعب

تتكون مخازن البيانات من مفاتيح تحدد البيانات، وقيم تخزن البيانات.

المفتاحالقيمة
الوصفالمفتاح هو معرف فريد يمكنك استخدامه للوصول إلى قطعة معينة من البيانات.

تسمح لك المفاتيح بتنظيم بياناتك بحيث يمكنك إدارتها بسهولة وتصحيح الأخطاء فيها.
القيمة هي البيانات الفعلية التي تريد حفظها أو تحميلها، مثل مخزون اللاعب أو إعداداته.

تتيح لك القيم تخزين التقدم بين الجلسات، بالإضافة إلى استرجاع بيانات اللاعب في المرة القادمة التي ينضم فيها إلى لعبتك.
التنسيقات المسموح بهايمكن أن تكون فقط سلاسل نصية.يمكن أن تكون أرقامًا أو سلاسل نصية أو قيم منطقية أو جداول.
أمثلة"Player_A", "TopScore", "GameSetting"100, "Level_5", true, {gold = 100, level = 5}

في هذا البرنامج التعليمي، المفتاح هو userId اللاعب والقيمة هي كمية الذهب التي جمعها. لاستخدام هذا المفتاح والقيمة لحفظ وتحميل بيانات اللاعب:

  1. في نص مدير الذهب، أضف دالة مساعدة تسمى saveGold لحفظ ذهب اللاعب في مخزن بيانات PlayerGold.


    local function saveGold(userId, value)
    local success, err = pcall(function()
    -- `userId` هو المعرف الفريد للاعب
    -- `value` هي كمية الذهب التي يجب حفظها لذلك اللاعب
    goldStore:SetAsync(userId, value)
    end)
    end
  2. اختياري
    أضف تحذيرًا إلى saveGold يقوم بطباعة ID اللاعب ورسالة الخطأ. على الرغم من عدم الإلزام، فإن هذه الخطوة تعتبر ممارسة جيدة لتسهيل تصحيح الأخطاء في حال فشل دالتك.


    local function saveGold(userId, value)
    local success, err = pcall(function()
    -- `userId` هو المعرف الفريد للاعب
    -- `value` هي كمية الذهب التي يجب حفظها لذلك اللاعب
    goldStore:SetAsync(userId, value)
    end)
    if not success then
    warn("[SAVE ERROR] لم نتمكن من حفظ الذهب لـ", userId, ":", err)
    end
    end
  3. عدل حدث onPlayerAdded لتحميل ذهب اللاعب عندما ينضم لأول مرة إلى اللعبة. دالة onPlayerAdded المحدثة:

    • تحاول تحميل المحتوى داخل مخزن بيانات PlayerGold. تعيد إما ذهب اللاعب المحفوظ أو قيمة 0 إذا لم يكن لدى اللاعب أي ذهب أو لم يلعب اللعبة من قبل.
    • توفر لك سجل تصحيح لمساعدتك في تصحيح الكود الخاص بك بسهولة أكبر. يتضمن سجل التصحيح هذا ذهب اللاعب المنضم المحفوظ، أو رسالة خطأ إذا لم تتمكن onPlayerAdded من الوصول إلى مخزن البيانات.
    • تُحدّث واجهة المستخدم لعرض ذهب اللاعب المحفوظ على شاشته.

    local function onPlayerAdded(player)
    local userId = player.UserId
    local success, storedGold = pcall(function()
    return goldStore:GetAsync(userId)
    end)
    if success then
    local currentGold = storedGold or 0
    playerGold[userId] = currentGold
    uiEvent:FireClient(player, {
    gold = currentGold,
    doTween = false,
    showAlert = not success
    })
    else
    uiEvent:FireClient(player, { showAlert = true })
    warn("لم نتمكن من تحميل الذهب لـ", player.Name)
    end
    end
  4. عدل حدث onPlayerRemoving لاستدعاء دالة saveGold التي أنشأتها سابقًا وحفظ ذهب اللاعب عندما يغادر اللعبة.


    local function onPlayerRemoving(player)
    local userId = player.UserId
    if playerGold[userId] then
    saveGold(userId, playerGold[userId])
    end
    end

حفظ بيانات اللاعب تلقائيًا

يعتبر حفظ بيانات اللاعب تلقائيًا ممارسة جيدة لأنه يحمي اللاعب من فقدان بياناته. إذا قمت بحفظ بيانات اللاعب فقط عندما يغادر اللعبة باستخدام onPlayerRemoving، فقد تفقد أحدث تقدم له إذا انقطع الاتصال بالخادم بشكل غير متوقع.

لحفظ بيانات اللاعب تلقائيًا:

  1. أنشئ ثابتًا جديدًا لتحديد مدى رغبتك في أن تقوم لعبتك بحفظ بيانات اللاعب تلقائيًا. الثابت هو متغير لا تتغير قيمته أثناء تشغيل اللعبة. يمكنك استخدام هذا الثابت للإشارة إلى فاصل الحفظ التلقائي على مدار النص واستخدامه لتعديل تكرار الحفظ التلقائي بسهولة.


    -- هذا الرقم بالثواني
    local AUTOSAVE_INTERVAL = 30
  2. أضف خيط حفظ تلقائي إلى دالة onPlayerAdded الموجودة لإنشاء حلقة خلفية تعمل بينما يكون اللاعب داخل اللعبة. الخيط هو دالة تعمل بشكل غير متزامن؛ يمكن أن تتوقف عند نقاط معينة، وتستأنف من حيث توقفت، وتعمل بالتوازي مع أجزاء أخرى من نصك دون حظرها.

    في هذا النص، تنتظر حلقة الخيط الخلفية لفترة الزمنية المحددة في الثابت AUTOSAVE_INTERVAL، ثم تستدعي دالة saveGold التي أنشأتها سابقًا.


    coroutine.wrap(function()
    while player.Parent do
    task.wait(AUTOSAVE_INTERVAL)
    if playerGold[userId] then
    print("[AUTOSAVE] حفظ", playerGold[userId], "ذهب لـ", player.Name)
    saveGold(userId, playerGold[userId])
    end
    end
    end)()

حفظ وتحميل موقع اللاعب

لحفظ موقع اللاعب، اعمل مع Character بدلاً من كائن Player نفسه. يمثل Character اللاعب نموذجه الفيزيائي في العالم ثلاثي الأبعاد ويحتوي على الإحداثيات لموقعه الحالي واتجاهه، بينما يمثل كائن Player حساب المستخدم فقط.

نظرًا لأن مخازن البيانات يمكن أن تحفظ فقط أنواع البيانات الأساسية مثل الأرقام والسلاسل والجداول، لا يمكنك تخزين كائنات معقدة مثل قيم Vector3 أو CFrame مباشرة. لحفظ موقع اللاعب، تحتاج إلى تقسيمه إلى ثلاثة أرقام منفصلة (إحداثيات X وY وZ) وحفظها بشكل فردي. عند تحميل الموقع لاحقًا، يمكنك إعادة بناء Vector3 باستخدام الإحداثيات المحفوظة.

لحفظ وتحميل موقع الشخصية:

  1. افتح النص الموجود مدير الموقع تحت ServerScriptService.

  2. في أعلى النص، قم بتهيئة DataStoreService واستدعي GetDataStore مع السلسلة "PlayerPosition".


    local DataStoreService = game:GetService("DataStoreService")
    local positionStore = DataStoreService:GetDataStore("PlayerPosition")
  3. أضف دالة مساعدة تسمى savePosition التي تأخذ userId اللاعب وموضع Vector3. نظرًا لأنك لا تستطيع حفظ قيم Vector3 مباشرة، قم بتحويل الموضع إلى جدول من الأرقام X، Y، Z.


    local function savePosition(player, position)
    local userId = player.UserId
    local success, err = pcall(function()
    positionStore:SetAsync(userId, {position.X, position.Y, position.Z})
    end)
    end
  4. اختياري
    أضف تحذيرًا إلى savePosition يقوم بطباعة رسالة خطأ واسم اللاعب الذي فشلت في حفظ موضعه. على الرغم من عدم الإلزام، فإن هذه الخطوة تعتبر ممارسة جيدة لتسهيل تصحيح الأخطاء في حال فشلت دالتك.


    local function savePosition(player, position)
    local userId = player.UserId
    local success, err = pcall(function()
    positionStore:SetAsync(userId, {position.X, position.Y, position.Z})
    end)
    if not success then
    warn("لم نتمكن من حفظ الموضع لـ", player.Name, ":", err)
    end
    end
  5. أضف دالة مساعدة أخرى تسمى loadPosition لتحميل الإحداثيات المحفوظة للاعب في مخزن بيانات PlayerPosition. استخدم PivotTo لاستعادة موقع الشخصية في العالم. نظرًا لأن موضع اللاعب المحفوظ يُعاد كجدول، عليك إعادة بناء Vector3 ثم تحويله إلى CFrame لنقل الشخصية.


    local function loadPosition(userId, character)
    local userId = player.UserId
    local success, savedCoords = pcall(function()
    return positionStore:GetAsync(userId)
    end)
    if success and savedCoords then
    local pos = Vector3.new(savedCoords[1], savedCoords[2], savedCoords[3])
    print("تم استعادة الموقع لـ", player.Name)
    character:PivotTo(CFrame.new(pos))
    elseif not success then
    warn("لم نتمكن من تحميل الموضع لـ", player.Name)
    end
    end
  6. عدل حدث onPlayerAdded لإعداد المنطق المتعلق بالموقع لكل لاعب ينضم إلى لعبتك. داخل دالة onPlayerAdded المحدثة:

    • CharacterAdded تستدعي loadPosition لاستعادة آخر موقع معروف عندما يولد شخصية اللاعب.
    • CharacterRemoving تستدعي savePosition لحفظ الموقع الحالي لشخصية اللاعب إذا تمت إزالتها من اللعبة.
    • GetPivot يحصل على الموقع الدقيق للشخصية في العالم في الوقت الذي تمت إزالتها فيه.

    local function onPlayerAdded(player)
    local userId = player.UserId
    player.CharacterAdded:Connect(function(character)
    loadPosition(player, character)
    end)
    player.CharacterRemoving:Connect(function(character)
    local pos = character:GetPivot().Position
    savePosition(player, pos)
    end)
    end
    Player.PlayerAdded:Connect(onPlayerAdded)

الكود النهائي

انظر إلى مقتطفات الكود التالية للحصول على النصين البرمجيين الكاملين مدير الذهب ومدير الموقع. يمكنك لصقها وتشغيلها مباشرةً في ملف دليل حفظ بيانات جولد راش - البداية .rbxl في Studio.

مدير الذهب


-- الحصول على الخدمات
-- الحصول على الخدمات
local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local CollectionService = game:GetService("CollectionService")
local DataStoreService = game:GetService("DataStoreService")
-- حدث عن بعد لتحديث واجهة المستخدم
local uiEvent = ReplicatedStorage:WaitForChild("UIEvent")
-- مخزن بيانات لحفظ قطع ذهب اللاعب
local goldStore = DataStoreService:GetDataStore("PlayerGold")
-- جدول لتخزين قطع ذهب اللاعب لجلسة واحدة
local playerGold = {}
-- الثوابت
local GOLD_VALUE = 10 -- كم تساوي كل قطعة ذهب
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], "ذهب")
-- تحديث واجهة المستخدم لتعكس النتيجة الجديدة من الذهب لهذه الجلسة
uiEvent:FireClient(player, {
gold = playerGold[userId],
doTween = true,
showAlert = false
})
-- انتظر قليلًا ثم أجدد قطعة الذهب التي تم جمعها للتو
task.delay(GOLD_REGEN_DELAY, function()
chunk.Parent = workspace.GoldChunks
end)
end
-- حلقة عبر جميع الأجزاء المعلمة بـ "ذهب" وربطها مع كشف اللمس
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
-- وظيفة لحفظ ذهب اللاعب إلى مخزن البيانات
local function saveGold(player, value)
local userId = player.UserId
local success, err = pcall(function()
goldStore:SetAsync(userId, value)
end)
if not success then
warn("لم نتمكن من حفظ الذهب لـ", player.Name, ":", err)
end
end
-- وظيفة للتعامل مع انضمام اللاعب إلى اللعبة
local function onPlayerAdded(player)
local userId = player.UserId
print(player.Name, "انضم إلى اللعبة")
-- حاول تحميل ذهب اللاعب من مخزن البيانات
local success, storedGold = pcall(function()
return goldStore:GetAsync(userId)
end)
if success then
-- تعيين سجل ذهب الجلسة الحالية باستخدام قيمة مخزن البيانات للاعب
local currentGold = storedGold or 0
playerGold[userId] = currentGold
-- تحديث واجهة المستخدم بقيمة مخزن البيانات للاعب
uiEvent:FireClient(player, {
gold = currentGold,
doTween = false,
showAlert = false
})
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
-- احفظ ذهب اللاعب في مخزن البيانات قبل مغادرته
saveGold(player, playerGold[userId])
end
end
-- ربط أحداث انضمام ومغادرة اللاعبين
Players.PlayerAdded:Connect(onPlayerAdded)
Players.PlayerRemoving:Connect(onPlayerRemoving)

مدير الموقع


-- الحصول على الخدمات
local Players = game:GetService("Players")
local DataStoreService = game:GetService("DataStoreService")
-- مخزن بيانات لحفظ موقع اللاعب
local positionStore = DataStoreService:GetDataStore("PlayerPosition")
-- وظيفة لحفظ موقع اللاعب كجدول من {X, Y, Z}
local function savePosition(player, position)
local userId = player.UserId
local success, err = pcall(function()
positionStore:SetAsync(userId, {position.X, position.Y, position.Z})
end)
if not success then
warn("لم نتمكن من حفظ الموضع لـ", player.Name, ":", err)
end
end
-- وظيفة لتحميل آخر موضع محفوظ للاعب وتحريك شخصيته
local function loadPosition(player, character)
local userId = player.UserId
local success, savedCoords = pcall(function()
return positionStore:GetAsync(userId)
end)
if success and savedCoords then
local pos = Vector3.new(savedCoords[1], savedCoords[2], savedCoords[3])
print("تم استعادة الموضع لـ", player.Name)
character:PivotTo(CFrame.new(pos))
elseif not success then
warn("لم نتمكن من تحميل الموضع لـ", player.Name)
end
end
-- وظيفة للتعامل مع انضمام اللاعب إلى اللعبة
local function onPlayerAdded(player)
local userId = player.UserId
-- حاول تحميل موضع اللاعب عندما تولد شخصيته
player.CharacterAdded:Connect(function(character)
loadPosition(player, character)
end)
-- احفظ موضع اللاعب عندما تتم إزالة شخصيته
player.CharacterRemoving:Connect(function(character)
local pos = character:GetPivot().Position
savePosition(player, pos)
end)
end
Players.PlayerAdded:Connect(onPlayerAdded)
©2026 شركة Roblox Corporation. تُعد منصّة Roblox، وشعار Roblox وشعار "توسيع حدود المخيلة"، من ضمن علاماتنا التجارية المسجّلة وغير المسجّلة في الولايات المتحدة وبلدان أخرى.