春までRoblox — 第1回ブログ

テーマは Robloxのメモリー制限とユーザー毎データ保持の方法 です。


🔹 Robloxのメモリー制限の背景

  • サーバー側 (約6.4GB)
    多数のプレイヤーを同時に扱うため、膨大なデータを保持する必要があります。ワークスペースのオブジェクト、スクリプト、物理演算、プレイヤーごとの状態などを一括管理するため「共有データ」だけでなく、差分やシミュレーション用の情報も含まれます。

  • クライアント側 (約100MB)
    個々のプレイヤーに必要なデータのみを受け取ります。表示用のアセット、ローカルスクリプト、UI、プレイヤー自身の状態など。端末性能やネットワーク帯域を考慮して制限が厳しく設定されています。

👉 「共有データ」という観点で考えると、サーバーも100MB+αでよいのでは?という発想は理にかなっています。しかし実際には プレイヤー数×差分データ+シミュレーション領域 が必要になるため、6.4GBという枠が設定されています。


🔹 DelphiからRoblox(Lua)へのデータ定義移植

Delphiの recordconst を Roblox(Lua) に移す場合は以下のように書き換えます。

-- 定数定義
local Const = {
    FieldMax = 20,
    Magnification = 40,
    CubesMax = 320000,
    CubesUndoMax = 32000,
    CameraS = 150,
    CameraM = 200,
    CameraL = 320,
    LightDark = 0.4,
    LightMiddle = 0.7,
    LightLight = 1.0
}

-- レコード型をLuaのtableで表現
local function Cube(x,y,z,u,child,state,range)
    return {
        x = x or 0, y = y or 0, z = z or 0,
        u = u or 0, child = child or 0,
        state = state or 0, range = range or 0
    }
end

local function CubeUndo(x,y,z,w,h,d,child,state,range,groupId)
    return {
        x = x or 0, y = y or 0, z = z or 0,
        w = w or 0, h = h or 0, d = d or 0,
        child = child or 0, state = state or 0,
        range = range or 0, groupId = groupId or 0
    }
end

👉 Delphiの record は Luaの tableconstlocal Const = {}Array[...] of は Luaの配列で代替します。


🔹 Robloxでユーザー毎データを持たせる方法

1. プレイヤーごとのデータ領域を用意する

local PlayerData = {}

game.Players.PlayerAdded:Connect(function(player)
    PlayerData[player.UserId] = {
        Cubes = {},
        CubeUndo = {}
    }
end)

game.Players.PlayerRemoving:Connect(function(player)
    PlayerData[player.UserId] = nil
end)

2. Cube / CubeUndo の生成関数(共通器)

local function Cube(x,y,z,u,child,state,range)
    return {x=x or 0, y=y or 0, z=z or 0,
            u=u or 0, child=child or 0,
            state=state or 0, range=range or 0}
end

local function CubeUndo(x,y,z,w,h,d,child,state,range,groupId)
    return {x=x or 0, y=y or 0, z=z or 0,
            w=w or 0, h=h or 0, d=d or 0,
            child=child or 0, state=state or 0,
            range=range or 0, groupId=groupId or 0}
end

3. ユーザー毎に追加する関数

local function AddCubeForPlayer(player, cube)
    table.insert(PlayerData[player.UserId].Cubes, cube)
end

local function AddCubeUndoForPlayer(player, cubeUndo)
    table.insert(PlayerData[player.UserId].CubeUndo, cubeUndo)
end

4. イベントは一本化して利用する

game.Players.PlayerAdded:Connect(function(player)
    PlayerData[player.UserId] = { Cubes = {}, CubeUndo = {} }

    local c = Cube(1,2,3,10,0,1,0)
    AddCubeForPlayer(player, c)

    local cu = CubeUndo(1,2,3,10,10,10,0,1,0,123)
    AddCubeUndoForPlayer(player, cu)
end)

game.Players.PlayerRemoving:Connect(function(player)
    PlayerData[player.UserId] = nil
end)

🔹 イベントドリブンの仕組み

  • game.Players.PlayerAdded は「新しいプレイヤーが参加したとき」に自動的に発火するイベント。
  • 引数 player には参加したプレイヤーのオブジェクトが渡される。
  • これにより「ユーザー毎にCubeデータを初期化する」処理が自然にイベントドリブンで行える。
  • 対になるイベントは game.Players.PlayerRemoving。退出時にデータを破棄するのが一般的。

🔹 まとめ

  • サーバーは 共有データ+プレイヤー差分+シミュレーション領域 を持つため6.4GBが必要。
  • Delphiの定義はLuaの tablelocal Const に移せる。
  • ユーザー毎データは PlayerData[userId] に保持し、イベント一本化で管理する。

📖 以上を第1回目のブログ記事「春までRoblox」としました。
次回は「Cubeデータをゲーム内のPartに同期させる方法」をテーマにすると、さらに実践的になります。