📉

【Roblox】負荷チェック用データの取得

に公開

はじめに

Robloxではマルチプラットフォームである関係上、さまざまなデバイスで動作する開発を心がける必要があります。
今回はRobloxでリソースの使用状況とパフォーマンス情報を取得する方法について紹介します。

Robloxバージョン: 0.664.0.6640713

Stats

Robloxにはリアルタイムのパフォーマンス情報を取得する方法としてStatsサービスが存在します。
Statsサービスを利用することでプレース上の表示されているインスタンスの数やレンダリングに対する負荷などを取得することができます。

プロパティ

ContactsCount

現在接触しているパーツの数を表します。2つのパーツのうちの1つが物理的にシミュレートされているため、BasePart:GetTouchingParts()メソッドを使用して触れ合っているパーツを取得できます。

DataReceiveKbps

現在のインスタンスが1秒当たりに受信しているデータのキロバイト数を取得できます。サーバー側では接続しているクライアントから受信しているデータの合計量を表し、クライアント側ではサーバーから受信しているデータの合計量を表します。

DataSendKbps

現在のインスタンスによって1秒当たりに送信されているデータのキロバイト数を取得できます。サーバー側では接続されているクライアントに送信されるデータの合計量を表し、クライアント側ではサーバー側に送信されるデータの合計量を表します。

FrameTime

最新のフレームをレンダリングするのにかかった時間を秒単位で測定します。この値を使用することでFPS値を計算することができます。このプロパティはクライアントでしか動作しません。

HeartbeatTime

サーバーがタスクスケジューラジョブを更新するのにかかる合計時間を秒単位で測定します。

InstanceCount

現在メモリ内にあるインスタンスの数を測定します。

MovingPrimitivesCount

現在動いている物理的にシミュレートされているコンポーネントの数を測定します。

PhysicsReceiveKbps

現在のインスタンスが1秒あたりに受信している物理データのキロバイト数を取得します。サーバー側ではサーバーに接続されているクライアントから受信されている物理データの合計量を表し、クライアント側ではサーバー側から受信されている物理データの合計量を表します。

PhysicsSendKbps

現在のインスタンスによって1秒あたりに送信されている物理データのキロバイト数を取得します。サーバー側では接続されているクライアントに送信される物理データの合計量を表し、クライアント側ではサーバーに送信される物理データの合計量を表します。

PhysicsStepTime

物理エンジンが現在の状態を更新するのにかかる時間を測定します。

PrimitivesCount

現在物理的にシミュレートされているコンポーネントの数を測定します。

RenderCPUFrameTime

CPUがフレームのすべてのレンダリングタスクを処理するのにかかる時間を測定します。

RenderGPUFrameTime

GPUがフレームのレンダリングに必要なすべてのタスクを処理するのにかかる時間を測定します。

SceneDrawcallCount

現在のシーンによって行われた描画呼び出しの数を表します。

SceneTriangleCount

現在のシーンによってレンダリングされた三角形ポリゴンの数を表します。

ShadowsDrawcallCount

現在のシーンによって影に対して行われる描画呼び出しの数を表します。

ShadowsTriangleCount

現在のシーンによって影としてレンダリングされる三角形ポリゴンの数を表します。

UI2DDrawcallCount

現在のシーン内のUI要素に対して行われた2D描画呼び出しの数を測定します。

UI2DTriangleCount

現在のシーンで2DUI要素に対してレンダリングされている三角形ポリゴンの数を表します。

UI3DDrawcallCount

現在のシーン内のUI要素に対して行われた3D描画呼び出しの数を測定します。

UI3DTriangleCount

現在のシーンで3DUI要素に対してレンダリングされている三角形ポリゴンの数を表します。

メソッド

GetMemoryUsageMbForTag

引数:Enum.DeveloperMemoryTag
指定されたEnum.DeveloperMemoryTagカテゴリで消費されているメモリ量をメガバイト単位で返します。

GetTotalMemoryUsageMb

現在のゲームセッションで消費されているメモリの合計量をメガバイト単位で返します。

実装例

①Guiを用意する

②コードを作成
今回は画面の右上に5項目ずつデータが表示されるように実装しています。
項目の切り替えはCtrlキーを押しながら数字キーを押すことで切り替えられるようになっているのでお好みで変更してみてください。

local Stats = game:GetService("Stats")
local UserInputService = game:GetService("UserInputService")

local ScreenGui = script.Parent
local BackFrame = ScreenGui:WaitForChild("Back")
local ItemPrefab = BackFrame:WaitForChild("Item")

--データを表示するテキストラベルを複製
--テキストラベルはtableに格納して管理します。
local items = {}
for i = 1, 6 do
    print(i)
    local Item = ItemPrefab:Clone()
    Item.Parent = BackFrame
    Item.Position = UDim2.new(0, 0, 0.1 * (i - 1), 0)
    table.insert(items, Item)
end
ItemPrefab:Destroy()

--今回は6項目5ページを切り替えて表示する形式で実装します。
local pageNum = 1
local MaxPage = 5
local isControll = false

--表示されているテキストを更新するためのメソッドです。
--表示されているページに合わせて取得するデータを切り替えています。
local function UpdateText()
    if pageNum == 1 then
        items[1].Text = "ReceiveData:"..string.format("%.4f", Stats.DataReceiveKbps).."Kbps"
        items[2].Text = "SendData:"..string.format("%.4f", Stats.DataSendKbps).."Kbps"
        items[3].Text = "HeartbeatTime(Server):"..string.format("%.4f", Stats.HeartbeatTime).."s"
        items[4].Text = "PhysStepTime:"..string.format("%.4f", Stats.PhysicsStepTime).."s"
    elseif pageNum == 2 then
        items[1].Text = "PhysReceiveKbps:"..string.format("%.4f", Stats.PhysicsReceiveKbps).."Kbps"
        items[2].Text = "PhysSendKbps:"..string.format("%.4f", Stats.PhysicsSendKbps).."Kbps"
        items[3].Text = "RendCpuTime:"..string.format("%.4f", Stats.RenderCPUFrameTime).."s"
        items[4].Text = "RendGpuTime:"..string.format("%.4f", Stats.RenderGPUFrameTime).."s"
    elseif pageNum == 3 then
        items[1].Text = "ContactsCount:"..string.format("%d", Stats.ContactsCount)
        items[2].Text = "InstanceCount:"..string.format("%d", Stats.InstanceCount)
        items[3].Text = "MovePrimCount:"..string.format("%d", Stats.MovingPrimitivesCount)
        items[4].Text = "PrimitiveCount:"..string.format("%d", Stats.PrimitivesCount)
	elseif pageNum == 4 then
        items[1].Text = "DrawcallCount:"..string.format("%d", Stats.SceneDrawcallCount)
        items[2].Text = "TriangleCount:"..string.format("%d", Stats.SceneTriangleCount)
        items[3].Text = "ShadowDrawcall:"..string.format("%d", Stats.ShadowsDrawcallCount)
        items[4].Text = "ShadowTriangle:"..string.format("%d", Stats.ShadowsTriangleCount)
    elseif pageNum == 5 then
        items[1].Text = "UI2DDrawcall:"..string.format("%d", Stats.UI2DDrawcallCount)
        items[2].Text = "UI2DTriangle:"..string.format("%d", Stats.UI2DTriangleCount)
        items[3].Text = "UI3DDrawcall:"..string.format("%d", Stats.UI3DDrawcallCount)
        items[4].Text = "UI3DTriangle:"..string.format("%d", Stats.UI3DTriangleCount)
    end
    --FPS値と使用メモリは常に表示されるようにしています。
    items[5].Text = "FPS:"..string.format("%d", 1 / Stats.FrameTime)
    items[6].Text = "UsageMemory:"..string.format("%2f", Stats:GetTotalMemoryUsageMb()).."MB"
end

--表示されるページを切り替えるためのメソッドです。
local function ChangePages(change:number)
    if isControll then
        if change > 0 and change <= MaxPage then
            pageNum = change
            for i,v in ipairs(items) do
                v.Text = ""
            end
        end
    end
end

--キー入力で表示されるページを変更
UserInputService.InputBegan:Connect(function(input)
    if input.UserInputType == Enum.UserInputType.Keyboard then
        if input.KeyCode == Enum.KeyCode.LeftControl then
            isControll = true
		end
        if input.KeyCode == Enum.KeyCode.One then
            ChangePages(1)
        elseif input.KeyCode == Enum.KeyCode.Two then
            ChangePages(2)
        elseif input.KeyCode == Enum.KeyCode.Three then
            ChangePages(3)
        elseif input.KeyCode == Enum.KeyCode.Four then
            ChangePages(4)
        elseif input.KeyCode == Enum.KeyCode.Five then
            ChangePages(5)
        elseif input.KeyCode == Enum.KeyCode.LeftShift then
            ScreenGui.Enabled = not ScreenGui.Enabled
        end
    end
end)
UserInputService.InputEnded:Connect(function(input)
    if input.UserInputType == Enum.UserInputType.Keyboard then
        if input.KeyCode == Enum.KeyCode.LeftControl then
            isControll = false
        end
    end
end)

--テキストをおおまかに0.1秒に一回更新する
while true do
    UpdateText()
    wait(0.1)
end

これでゲームを実行すると右上にパフォーマンスが表示されるようになります。

まとめ

  • パフォーマンス情報の取得にはStatsサービスを使用する。
  • 取得したデータをGuiに表示して確認できる状態にする。

今回はパフォーマンス情報を取得できるStatsサービスについて紹介しました。
実際にゲーム開発をしていると特定環境で重くなることなどがありますが、パフォーマンス情報があれば重くなっている原因を探りやすくなります。負荷検証は最後に行おうとすると修正作業にかなりの時間を要することもあるので、開発初期からパフォーマンス情報をチェックして負荷の少ないゲーム開発を心がけましょう。

参考

https://create.roblox.com/docs/reference/engine/classes/Stats

ランド・ホー Roblox開発チーム

Discussion