【Roblox】ジャンル別ステージ抽選機能の作り方
はじめに
今回は弊社からリリースした『UGC Romance Obby Fall Game』で実装したジャンル別ステージ抽選機能について紹介します。
今回は上記のゲームで実装した条件に当てはまったステージのリストを取得する方法について紹介したいと思います。
Roblox バージョン: 0.661.0.6610708
ジャンル機能
冒頭にも記載しましたがRobloxのDataStoreには保存されたデータの内容を参照してのフィルタリングはすることができません。なので前もって条件にあったステージリストをテーブルとして作成しておいて取得する必要があります。今回紹介する方法ではステージ情報の更新タイミングでジャンル機能の条件にあっているかの判定を行い、保存されているリスト情報と異なっていた場合のみ更新を行うようにします。こうすることでジャンルごとのテーブルを取得しなくてもすでにジャンルに割り振られているかを確認することができるようになります。
各ジャンルのステージリストはランダムに取得することができるようにテーブル型にArrayのように保存しています。
ステージごとのデータ構造
local stageData = {
PlayCount :number,
ClearCount :number,
GoodCount :number,
BadCount :number,
StageGenre :{number}
}
ジャンルのID
1:ハード
2:ポピュラー
ステージデータのDataStoreへの更新
local HttpService = gamge:GetService("HttpService")
local DataStoreService = game:GetService("DataStoreService")
local StageDataStore = DataStoreService:GetDataStore("StageData")
local StageGenreStore = DataStoreService:GetDataStore("StageGenre")
--ステージリストを保存するキー
local HardStage = "HardStageList"
local PopularStage = "PopularStageList"
local StageDataManager = {}
--ここで渡しているplayDataはステージを遊んだプレイヤーごとのキャッシュデータです。
function StageDataManager:UpdateStageData(stageId, playData)
local oldStageGenre, newStageGenre
StageDataStore:UpdateAsync(stageId, function(oldData)
--データがなければ作成を行う
if not oldData then
oldData = {
PlayCount = 0,
ClearCount = 0,
GoodCount = 0,
BadCount = 0,
StageGenre = {}
}
end
--ステージジャンル情報以外のデータを更新する
local newData = {
PlayCount = oldData.PlayCount + playData.PlayCount,
ClearCount = oldData.ClearCount + playData.ClearCount,
GoodCount = oldData.GoodCount + playData.GoodCount,
BadCount = oldData.BadCount + playData.BadCount,
StageGenre = oldData
}
--ジャンルごとの基準を満たしているか判定を行う
oldStageGenre = newData.StageGenre
newStageGenre = {}
-- クリア率が30%以下ならハードのジャンルナンバーを追加
if newData.ClearCount / newData.PlayCount <= 0.3 then
table.insert(newStageGenre, 1)
end
-- いいね率が70%以上ならポピュラーのジャンルナンバーを追加
if newData.GoodCount / (newData.GoodCount + newData.BadCount) >= 0.7 then
table.insert(newStageGenre, 2)
end
newData.StageGenre = newStageGenre
return newData
end)
--tableをJSONにエンコードしてstringとして比較を行い、ジャンル情報に更新があった場合はステージリストを更新する
if HttpService:JSONEncode(oldStageGenre) ~= HttpService:JSONEncode(newStageGenre) then
-- 新しいデータにあって古いデータにないものは追加を行う
for i,newGenre in ipairs(newStageGenre) do
if not table.find(oldStageGenre, newGenre) then
StageGenreStore:UpdateAsync(HardStage, function(oldList)
local index = table.find(oldList, stageId)
if not index then
table.insert(oldList, stageId)
end
return oldList
end)
end
end
--古いデータにあって新しいデータにないものは削除を行う
for i,oldGenre in ipairs(oldStageGenre) do
if not table.find(newStageGenre, oldGenre) then
StageGenreStore:UpdateAsync(HardStage, function(oldList)
local index = table.find(oldList, stageId)
if index then
table.remove(oldList, stageId)
end
return oldList
end)
end
end
end
end
return StageDataManager
以上がステージ情報の更新タイミングでジャンルごとのステージリストを更新する方法になります。
上記の方法だとステージの更新を行うタイミングでDataStoreへ複数回アクセスする必要があるので、ゲームによってはステージのプレイ情報をキャッシュしておいて更新回数を減らしたり、ステージ情報内にジャンル情報の最終更新時間を保存しておいて一定時間は処理を行わないようにするなどの工夫をする必要があります。
まとめ
- ステージ情報の更新タイミングでジャンル機能の条件にあっているかの判定を行う
- ステージ情報にジャンル情報を入れておくことでジャンルごとのテーブルの参照回数を減らす
- DataStoreへのアクセスが集中する可能性があるため回数制限に注意する
今回は条件に当てはまったステージのリストを取得する方法について紹介しました。
ステージのクリア率などの変動のあるデータを基準にフィルタリングを行うにはそれなりに工夫が必要になってくるので、ゲームごとにあった設計をするように心がけましょう。
最後までお読みいただき、ありがとうございました!
参考

当社ではRobloxを活用したゲームの開発、 また企業の商品やサービスの認知度拡大に寄与する3Dワールドの制作など、 Robloxにおける様々な活用支援を行っております。 Robloxのコンテンツ開発をご検討されている企業様は、お気軽にご相談ください。 landho.co.jp/
Discussion