🚫

ClusterScriptの制限逆引きリスト

に公開

Advent Calendarの季節なので、今年もクラスター Advent Calendarに投稿です。
気づけば今年で4回目。

ClusterScriptの様々な制限について

今年もたくさんClusterScriptを書き、そしてたくさんのバグを生み出しました。
その中でよく悩まされたのが、Scriptが何らかの制限に引っかかってしまい、正常に動作しなくなることです。

Script Referenceに記載されている制限には、大きく「頻度制限」と「容量制限」があります。
「頻度制限」は、例えば $.createItem は1アイテムにつき10回/秒までしかできないよ、といったこと。
「容量制限」は、例えば _.setPlayerStorageData では10KBまでしか保存できないよ、といったこと。

そしてこの制限というのは、一人で動作確認していると見逃してしまうことも多いです。
10人とか20人、あるいはそれ以上のプレイヤーが体験することで制限に到達する、そういうことが多々ありました。

ということで、今回は制限値を意識し直すために、逆引きリストを作ってみました。
Script Referenceで配布されているindex.d.tsをClaudeに読ませて、まとめてもらいました。あまりちゃんとチェックしてないので、間違っていたり漏れていたらすいません。

データは2025/12/01時点のものです。

制限逆引きリスト

頻度制限

瞬間的な超過は可能だが平均回数は制限を下回る必要がある

最大10回/秒(ひとつのアイテムあたり)

  • $.createItem
  • $.requestOwnership
  • ItemHandle.send(クラフトアイテムの場合)
  • PlayerHandle.send(クラフトアイテムの場合)
  • _.sendTo(クラフトアイテムの場合)
  • ItemHandle.addImpulsiveForce
  • ItemHandle.addImpulsiveTorque
  • ItemHandle.addImpulsiveForceAt
  • PlayerHandle.setPosition
  • PlayerHandle.setRotation
  • PlayerHandle.setHumanoidPose
  • PlayerHandle.respawn
  • PlayerHandle.addVelocity
  • PlayerHandle.setMoveSpeedRate
  • PlayerHandle.setJumpSpeedRate
  • PlayerHandle.setGravity
  • PlayerHandle.resetPlayerEffects
  • PlayerHandle.requestTextInput
  • PlayerHandle.setPostProcessEffects
  • PlayerHandle.requestPurchase

最大3000回/秒(スペース内の全アイテム合計)

  • ItemHandle.send(ワールドアイテムの場合)
  • PlayerHandle.send(ワールドアイテムの場合)
  • _.sendTo(ワールドアイテムの場合)

最大5回/分(ひとつのアイテムあたり)

  • $.getOwnProducts(クラフトアイテムの場合)

最大100回/分(スペース内の全アイテム合計)

  • $.getOwnProducts(ワールドアイテムの場合)

容量制限

100byte以下

  • ItemHandle.sendmessageType
  • PlayerHandle.sendmessageType
  • _.sendTomessageType
  • $.callExternalmeta
  • $.getOwnProductsmeta
  • PlayerHandle.requestPurchasemeta
  • PlayerHandle.requestGrantProductmeta
  • PlayerHandle.requestTextInputmeta

200byte以下

  • PlayerHandle.requestTextInputtitle

1000byte以下

  • ItemHandle.sendarg (soft limit)
  • PlayerHandle.sendarg (soft limit)
  • _.sendToarg (soft limit)
  • SubNode.setText の文字列

1000byte以下 かつ 250文字以下

ASCIIは1文字あたり0.5文字として換算

  • PlayerHandle.requestTextInput で受け取るプレイヤーの入力文字列
  • $.onTextInput コールバックで受け取れる文字列

10kB以下

  • _.setPlayerStorageDatadata

100kB以下

  • $.callExternalrequest
  • $.callExternal の外部サーバーからの response

配列要素数の制限

最大64個まで

  • $.setVisiblePlayersplayers 配列

リストを眺めた所感

頻度制限

$.createItem が10回/秒なのはイメージしやすいですね。自分の場合、たくさんのItemを同時に生成しなければならない時は0.1秒ごとに1個ずつ生成して、「そういう演出」であるかのように見せることが多いです。 $.onCreate でAnimationを再生したりして。

一方で、PlayerHandle系が10回/秒なのは少し注意が必要かもしれません。例えば、「たくさんのプレイヤーを同時にワープさせる」みたいな場合は、PlayerHandle.setPositionを使うと10人以上同時にワープさせられないので、対象プレイヤー全員に PlayerHandle.send してからPlayerScript側で _.setPosition するのも手ですね。

リファレンスに書かれてないけど、自分の記憶では $.setPlayerScript も10回/秒だった気がする。

容量制限

覚えておくとよいのは以下の3点だと思います。

  • ItemHandle.send PlayerHandle.send _.sendToarg1000byteまで(soft limit)
  • _.setPlayerStorageDatadata10kBまで
  • $.callExternalrequest100kBまで

例えば、PlayerStorageの内容を $.callExternal で外部サーバーに送りたい時があったとしましょう。
PlayerStorageの data の容量は10kBまでなので、100kB制限である $.callExternalrequest に格納するには特に問題ない…と思いきや、 $.callExternal するためにはPlayerScriptからItemに _.sendTo しなければならず、その制限は1000byteなのです。

配列要素数の制限

$.setVisiblePlayersplayers 配列の要素数が最大64個までとなっています。
ひとつのアイテムに対する可視性フィルターは64人までしか設定できない、ということですね。

スペースには25人までしか入室できないので64個もあれば十分と思うかもしれませんが、退室したプレイヤーを検知してその情報を配列から削除しておかないと、スペースが生き続ける限り要素数が増えていきます。スペースが長く残るタイプのワールドを作っている方は要注意です。

Discussion