การจัดเก็บข้อมูล Open Cloud

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

นอกเหนือจากการเข้าถึงการจัดเก็บข้อมูลจาก Engine API ใน Studio หรือเกมสด (DataStoreService) คุณสามารถใช้ Open Cloud APIs เพื่อเข้าถึง มาตรฐาน และ การจัดเก็บข้อมูลที่เรียงลำดับ จากสคริปต์ภายนอกและเครื่องมืออื่น ๆ

การเข้าถึง Open Cloud ไปยังการจัดเก็บข้อมูลของคุณเปิดโอกาสให้มีการใช้งานที่หลากหลาย รวมถึง:

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

ตัวอย่างในหน้านี้แสดงวิธีการสร้าง พอร์ทัลสนับสนุนสินค้าคงคลังของผู้ใช้ และ กระดานผู้นำภายนอก ด้วย Node.js และ Python แต่คุณสามารถใช้ภาษาใดก็ได้ที่คุณต้องการ; Open Cloud APIs รองรับทุกภาษาการเขียนโปรแกรมที่สามารถส่งคำขอ HTTP

ความแตกต่างจาก Engine API

แม้ว่า Open Cloud APIs จะเข้าถึงการจัดเก็บข้อมูลพื้นฐานเดียวกันและมีความคล้ายคลึงกับการทำงานกับ DataStoreService แต่ก็มีความแตกต่างที่สำคัญบางประการ:

  • รหัสจักรวาล: แตกต่างจาก Engine API, Open Cloud APIs ไม่มีสถานะและสามารถมาจากที่ใดก็ได้ ดังนั้นคุณต้องให้ รหัสจักรวาล เสมอ ซึ่งเป็นตัวระบุที่ไม่ซ้ำกันของเกมของคุณ

  • สิทธิ์แยกสำหรับการสร้างและการอัปเดต: Engine API จะสร้างรายการใหม่หากไม่มีอยู่เมื่อคุณเรียกใช้ DataStore:SetAsync() แต่ Open Cloud วิธีการสำหรับการสร้างและการอัปเดตรายการจะแยกกัน สิทธิ์แยกสามารถปลอดภัยและยืดหยุ่นมากขึ้นในบางสถานการณ์ ตัวอย่างเช่น คุณอาจต้องการให้เครื่องมือสนับสนุนลูกค้าของคุณสามารถแก้ไขโปรไฟล์ของผู้ใช้ที่มีอยู่เท่านั้น ไม่ใช่สร้างโปรไฟล์ใหม่

  • การจัดรูปแบบข้อมูล: ทุกจุดสิ้นสุดของ Open Cloud ต้องการให้คุณจัดรูปแบบข้อมูลก่อนที่จะส่ง การจัดรูปแบบหมายถึงการแปลงวัตถุเป็นสตริง การแปลงกลับเป็นวัตถุเป็นสิ่งตรงกันข้าม Engine API จะจัดรูปแบบและแปลงกลับเนื้อหาของรายการโดยอัตโนมัติ แต่สำหรับ Open Cloud คุณต้องสร้างหรือแยกวิเคราะห์รายการของคุณไปและกลับจาก JSON ด้วยตัวเอง

ตัวเลขที่ไม่สิ้นสุด

รายการการจัดเก็บข้อมูลที่เขียนผ่าน Engine API สามารถมีตัวเลข Luau ที่ไม่สิ้นสุด เนื่องจาก JSON ไม่สามารถแสดงตัวเลขเหล่านี้ได้ การตอบสนองของ Open Cloud จะเปลี่ยนเป็นวัตถุ JSON ที่มีแท็กในค่ารายการที่ส่งคืน:

  • อนันต์บวก (inf): {"m": null, "t": "numeric", "v": "inf"}
  • อนันต์ลบ (-inf): {"m": null, "t": "numeric", "v": "-inf"}
  • NaN (nan): {"m": null, "t": "numeric", "v": "nan"}

สิทธิ์

การจัดเก็บข้อมูลมักเก็บข้อมูลที่ละเอียดอ่อน เช่น โปรไฟล์ผู้ใช้และสกุลเงินเสมือน เพื่อรักษาความปลอดภัย วิธีการ Open Cloud แต่ละวิธีมีสิทธิ์ที่สอดคล้องกันเรียกว่า ขอบเขต ที่คุณต้องเพิ่มไปยัง API key ของคุณ เช่น ขอบเขต universe-datastores.control:list สำหรับวิธีการ รายการการจัดเก็บข้อมูล หากคุณไม่เพิ่มสิทธิ์ที่จำเป็น คำขอ API ของคุณจะส่งคืนข้อผิดพลาด ดูเอกสารอ้างอิงสำหรับขอบเขตที่จำเป็นสำหรับแต่ละจุดสิ้นสุด

สำหรับข้อมูลเพิ่มเติมเกี่ยวกับการจัดการสิทธิ์ ดูที่ จัดการ API keys

พอร์ทัลสนับสนุนสินค้าคงคลังของผู้ใช้

ตัวอย่างนี้ใช้การจัดเก็บข้อมูลชื่อ Inventory และสคีมาสำหรับแต่ละรายการของ "userId": {"currency": number, "weapon": string, "level": number} คีย์คือ userId

ขอบเขตที่จำเป็น

เมื่อ สร้าง API Key สำหรับตัวอย่างนี้ ให้เพิ่มขอบเขตต่อไปนี้ไปยังคีย์ของคุณ:

  • universe-datastores.objects:list
  • universe-datastores.objects:read
  • universe-datastores.objects:update

โดยเลือกได้ ให้เพิ่มสิทธิ์สำหรับการจัดเก็บข้อมูล Inventory เท่านั้น ตั้งค่าการจำกัดที่อยู่ IP และตั้งค่าวันหมดอายุ

เพิ่มสคริปต์สำหรับพอร์ทัลสนับสนุนสินค้าคงคลังของผู้ใช้

หลังจากสร้าง API key ที่มีสิทธิ์ที่จำเป็นสำหรับแอปตัวอย่างแล้ว คุณสามารถสร้างสคริปต์เพื่อทำการร้องขอไปยังจุดสิ้นสุด สคริปต์เหล่านี้จะดึงรายการแรก 10 รายการในการจัดเก็บข้อมูล เพิ่มค่า currency สำหรับแต่ละรายการโดย 10 และจากนั้นอัปเดตแต่ละรายการ สำหรับการจัดเก็บข้อมูลที่ใหญ่ขึ้น คุณจะต้องจัดการกับ การแบ่งหน้า โดยใช้พารามิเตอร์การค้นหา maxPageSize และ pageToken

incrementCurrency.js
const apiKey = process.env.API_KEY;
if (!apiKey) {
throw new Error('ตัวแปรสภาพแวดล้อม API_KEY ไม่ได้ตั้งค่าไว้');
}
const apiHeaderKey = 'x-api-key';
const universeId = '';
const dataStoreId = 'Inventory';
const baseUrl = 'https://apis.roblox.com/cloud/v2/';
async function listEntries(universe, dataStore) {
const listPath = `universes/${universe}/data-stores/${dataStore}/entries`;
const url = baseUrl + listPath;
const response = await fetch(url, {
headers: { [apiHeaderKey]: apiKey }
});
return response.json();
}
async function getEntry(path) {
const url = baseUrl + path;
const response = await fetch(url, {
headers: { [apiHeaderKey]: apiKey }
});
return response.json();
}
async function updateEntry(path, payload) {
const url = baseUrl + path;
const response = await fetch(url, {
method: 'PATCH',
headers: {
[apiHeaderKey]: apiKey,
'Content-Type': 'application/json'
},
body: JSON.stringify(payload) // เนื้อหาต้องเป็นสตริง
});
return response;
}
(async () => {
try {
const entries = await listEntries(universeId, dataStoreId);
for (const entry of entries.dataStoreEntries) {
const path = entry.path;
console.log(`\nกำลังประมวลผลรายการ: ${path}`);
const currentData = await getEntry(path);
currentData.value.currency += 10;
const payload = { value: currentData.value };
const updateResponse = await updateEntry(path, payload);
console.log(`สถานะ: ${updateResponse.status}`);
console.log(`การตอบสนอง: ${await updateResponse.text()}`);
}
} catch (error) {
console.error('เกิดข้อผิดพลาดระหว่างการดำเนินการ:', error);
}
})();

ในการทดสอบ ตั้งค่าตัวแปรสภาพแวดล้อม API_KEY ติดตั้งการพึ่งพา และรันสคริปต์:

export API_KEY=<your_key>
node incrementCurrency.js

กระดานผู้นำภายนอกที่คงอยู่

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

ขอบเขตที่จำเป็น

เมื่อ สร้าง API Key สำหรับตัวอย่างนี้ ให้เพิ่มขอบเขตต่อไปนี้ไปยังคีย์ของคุณ:

  • universe.ordered-data-store.scope.entry:read
  • universe.ordered-data-store.scope.entry:write

เพิ่มสคริปต์สำหรับกระดานผู้นำ

หลังจากสร้าง API key ที่มีสิทธิ์ที่จำเป็นสำหรับแอปตัวอย่างแล้ว คุณสามารถสร้างสคริปต์เพื่อทำการร้องขอไปยังจุดสิ้นสุด สคริปต์เหล่านี้จะเพิ่มรายการตัวอย่างบางรายการไปยังการจัดเก็บข้อมูลที่เรียงลำดับด้วยหมายเลขสุ่มและจากนั้นดึงข้อมูลจากค่าที่สูงที่สุดไปต่ำสุด สำหรับการจัดเก็บข้อมูลที่ใหญ่ขึ้น คุณจะต้องจัดการกับ การแบ่งหน้า โดยใช้พารามิเตอร์การค้นหา maxPageSize และ pageToken

leaderboard.js
const apiKey = process.env.API_KEY;
const apiHeaderKey = 'x-api-key';
const universeId = '';
const orderedDataStoreId = 'PlayerScores';
const scopeId = 'global';
const baseUrl = 'https://apis.roblox.com/cloud/v2/';
async function createOrderedEntry(universe, orderedDataStore, entryId, payload) {
const createPath = `universes/${universe}/ordered-data-stores/${orderedDataStore}/scopes/${scopeId}/entries`;
const url = new URL(baseUrl + createPath);
url.searchParams.append('id', entryId);
const response = await fetch(url, {
method: 'POST',
headers: {
[apiHeaderKey]: apiKey,
'Content-Type': 'application/json',
},
body: JSON.stringify(payload),
});
if (!response.ok) {
const errorText = await response.text();
throw new Error(`ข้อผิดพลาด API (${response.status}): ${errorText}`);
}
return response.text();
}
async function listOrderedEntries(universe, orderedDataStore) {
const listPath = `universes/${universe}/ordered-data-stores/${orderedDataStore}/scopes/${scopeId}/entries`;
const url = new URL(baseUrl + listPath);
url.searchParams.append('orderBy', 'value desc');
return fetch(url, {
headers: {
[apiHeaderKey]: apiKey,
},
});
}
async function main() {
if (!apiKey) {
console.error('ข้อผิดพลาด: ตัวแปรสภาพแวดล้อม API_KEY ไม่ได้ตั้งค่าไว้');
process.exit(1);
}
const entryNames = ['Ragdoll', 'Balinese', 'Tabby', 'Siamese'];
console.log('กำลังสร้างข้อมูลตัวอย่าง...');
for (const name of entryNames) {
try {
const randomValue = Math.floor(Math.random() * 50) + 1;
const payload = { value: randomValue };
const responseText = await createOrderedEntry(universeId, orderedDataStoreId, name, payload);
console.log(responseText);
} catch (error) {
console.error(`ไม่สามารถสร้างรายการสำหรับ "${name}": ${error.message}`);
}
}
console.log('\nกำลังดึงรายการที่เรียงลำดับ...');
try {
const playerScoresResponse = await listOrderedEntries(universeId, orderedDataStoreId);
console.log(playerScoresResponse.status);
const responseText = await playerScoresResponse.text();
console.log(responseText);
} catch (error) {
console.error(`ไม่สามารถแสดงรายการได้: ${error.message}`);
}
}
main();

ในการทดสอบ ตั้งค่าตัวแปรสภาพแวดล้อม API_KEY ติดตั้งการพึ่งพา และรันสคริปต์:

export API_KEY=<your_key>
node leaderboard.js
©2026 Roblox Corporation. Roblox, โลโก้ Roblox และ Powering Imagination เป็นส่วนหนึ่งของเครื่องหมายการค้าที่จดทะเบียน และไม่ได้จดทะเบียนของเราในสหรัฐฯ และประเทศอื่นๆ