youtube-playables-js-sdk について
youtube-playables-js-sdkは、YouTube Playables JavaScript SDKをゲームに組み込むためのスキルです。ゲーム開発者向けに、初期化、セーブデータ、広告、スコア送信の手順を説明します。
主な機能
- 01ytgameグローバルの待機
- 02ゲーム準備完了APIの順次呼び出し
- 03セーブデータの読み書き
- 04インタースティシャル広告とリワード広告の要求
- 05整数のランキングスコア送信
活用シーン
- 01ゲームへのYouTube Playables統合
- 02プレイヤーデータの保存と更新
- 03広告フローとスコア送信の追加
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ hungify/ playables-skills --skill youtube-playables-js-sdkインストール後、Claude Code で/youtube-playables-js-sdkを入力して読み込まれたか確認します。
詳細
YouTube Playables JavaScript SDK
インストール
ytgame グローバルは YouTube ホストによって注入されるため、インストールは不要です。表示されるまでポーリングしてから、解決します。
function waitForYtgame(timeoutMs = 10000) {
return new Promise((resolve, reject) => {
if (window.ytgame) {
resolve(window.ytgame);
return;
}
const deadline = Date.now() + timeoutMs;
const intervalId = setInterval(() => {
if (window.ytgame) {
clearInterval(intervalId);
resolve(window.ytgame);
} else if (Date.now() >= deadline) {
clearInterval(intervalId);
reject(new Error('ytgame SDK not available — running outside YouTube Playables?'));
}
}, 100);
});
}
初期化
手順:ytgame を待つ → 言語の取得と保存データの読み込みを並行して行う → firstFrameReady() を呼び出す → 完全に操作可能になったら gameReady() を呼び出す。
let ytgame = null;
let platformLanguage = 'en';
let savedData = {};
waitForYtgame()
.then((sdk) => {
ytgame = sdk;
const getLanguagePromise = ytgame.system.getLanguage().then((language) => {
platformLanguage = language.length > 2 ? language.slice(0, 2) : language;
});
const getDataPromise = ytgame.game.loadData().then((data) => {
if (typeof data === 'string' && data !== '') {
try {
savedData = JSON.parse(data);
} catch (e) {
console.error('Failed to parse saved data, starting fresh', e);
savedData = {};
}
}
});
ytgame.system.onAudioEnabledChange((isEnabled) => {
// Mute or unmute the game audio based on isEnabled
});
ytgame.system.onPause(() => {
// Pause the game loop and audio
});
ytgame.system.onResume(() => {
// Resume the game loop and audio
});
return Promise.all([getLanguagePromise, getDataPromise]);
})
.then(() => {
ytgame.game.firstFrameReady();
})
.catch((err) => {
console.error('YouTube Playables SDK initialization failed', err);
// Fall back to a non-Playables code path if needed
});
ゲームが完全に操作可能になったら:
function notifyGameReady() {
ytgame.game.gameReady();
}
ストレージ(保存データ)
保存データは、プレイヤーごとに 1 つの JSON シリアライズ可能なデータです。関係のないキーを上書きしないよう、必ず読み取り → マージ → 書き込みの順で処理してください。書き込み後、再度読み取って保存を確認します。
// Read one or many keys from saved data
function getDataFromStorage(key, tryParseJson) {
return ytgame.game.loadData().then((data) => {
if (typeof data === 'string' && data !== '') {
try {
savedData = JSON.parse(data);
} catch (e) {
console.error('loadData parse error', e);
}
}
const readOne = (k) => {
let value = typeof savedData[k] === 'undefined' ? null : savedData[k];
if (typeof value === 'string' && tryParseJson) {
try {
value = JSON.parse(value);
} catch (e) {
/* keep as-is */
}
}
return value;
};
return Array.isArray(key) ? key.map(readOne) : readOne(key);
});
}
// Write one or many keys, then verify by reloading
function setDataToStorage(key, value) {
const data = savedData !== null ? { ...savedData } : {};
if (Array.isArray(key)) {
for (let i = 0; i < key.length; i++) data[key[i]] = value[i];
} else {
data[key] = value;
}
return ytgame.game
.saveData(JSON.stringify(data))
.then(() => {
savedData = data;
return ytgame.game.loadData();
})
.then((persisted) => {
if (persisted !== JSON.stringify(data)) {
console.warn(
'saveData verification mismatch — persisted value differs from written value'
);
}
})
.catch((err) => {
console.error('saveData failed', err);
});
}
// Delete one or many keys
function deleteDataFromStorage(key) {
const data = savedData !== null ? { ...savedData } : {};
if (Array.isArray(key)) {
for (const k of key) delete data[k];
} else {
delete data[key];
}
return ytgame.game
.saveData(JSON.stringify(data))
.then(() => {
savedData = data;
})
.catch((err) => {
console.error('deleteData (saveData) failed', err);
});
}
広告
インタースティシャル広告
ytgame.ads.requestInterstitialAd() は、広告フローが終了すると解決します。リクエストの前に一時停止し、解決または拒否された後に再開してください。
function showInterstitial() {
// Pause game and mute audio before requesting
ytgame.ads
.requestInterstitialAd()
.then(() => {
// Resume game and unmute audio
})
.catch(() => {
// Ad failed to deliver — resume game and continue
});
}
リワード広告
ytgame.ads.requestRewardedAd(placement) はブール値で解決します。解決された値が真の場合にのみ、報酬を付与してください。
function showRewarded(placement) {
// Pause game and mute audio before requesting
ytgame.ads
.requestRewardedAd(placement)
.then((isRewardEarned) => {
if (isRewardEarned) {
// Grant reward to the player
}
// Resume game and unmute audio
})
.catch(() => {
// Ad failed to deliver — resume game and continue
});
}
リーダーボード
ytgame.engagement.sendScore({ value }) を使って整数のスコアを送信します。送信前に文字列を整数に変換してください。
function submitScore(score) {
const value = typeof score === 'string' ? parseInt(score, 10) : score;
return ytgame.engagement.sendScore({ value });
}
コメント
Markdown 対応