【Roblox】ValueObject と Attributes の違いと使い分け方

Roblox

はじめに

この記事では ValueObject と Attributes の違いと使い分け方について解説します。
この記事での環境は以下の通りです。

  • OS:Windows
  • Roblox Studio:Version 0.717.0.7170982 (64bit)

ValueObject とは

まず、ValueObject とは何でしょうか?
ValueObject とは一言でいうと値を保持するためだけの Instance のことです。

エディタからの扱い方

Explorer から Instance を手動で追加するときに「value」と検索すると BoolValue や BrickColorValue、CFrameValue などがヒットします。

これらは全て ValueObject であり、RayValue 以外は「Properties > Data > Value」で保持させたい値を手動で設定することができます。

StringValue を追加して Value に「Hello World」と入力

ここで設定することのできる値の型は StringValue なら文字列、IntValue なら整数、NumberValue なら倍精度浮動小数点数といったようにその ValueObject のクラスによって異なります。

公式ドキュメントに記載されているようにこの記事の執筆時点(2026年4月時点)では RayValue のみ Properties で Value を編集することができません。

a RayValue’s stored ray cannot be viewed or edited within the Properties window within studio.

RayValue

スクリプトからの扱い方

また、ValueObject やその Value は Roblox Studio から手動で編集する以外にもスクリプトから編集することもできます。
Part などの他の Instance と同様に Instance.new() でインスタンス化でき、「.Value」でその ValueObject の値を読み書きすることができます。

local stringValue = Instance.new("StringValue")
stringValue.Parent = workspace

stringValue.Value = "Hello World"
local sampleVariable = stringValue.Value

全ての ValueObject は ValueBase というクラスを継承しているため、とある Instance が ValueObject かどうかを確認するときは以下のコードのようにその Instance が ValueBase の派生クラスかどうかを確認すればOKです。

local function isValueObject(instance)
    return instance:IsA("ValueBase")
end

ValueObject の置き場所

基本的に ValueObject はどこに置いても大丈夫ですが、下の画像のように Configuration という Instance の中にまとめて置くことが推奨されています。

Configuration というクラス自体に何か特別な機能が備わっているわけではありませんが、Explorer の至る所に ValueObject が置いてあるよりも「ValueObject は必ず Configuration の中に置く」というルールを設けることで ValueObject を探しやすくなったり、その値を編集しやすくなったりします。

Attributes とは

では Attributes とは何でしょうか?
Attributes も ValueObject と同様にエディタやスクリプトでその値を編集できる仕組みですが、ValueObject よりも扱いやすく、パフォーマンスの面でも優れています。
ValueObject の場合は1つの値につき1つの Instance を作成する必要がありましたが、Attributes の場合は複数の値を1つの Instance に持たせることができます。

エディタからの扱い方

エディタから Attributes を追加するときはまず、Explorer でその Instance を選択し、「Properties > Attributes」の右の「+」を押します。

「Add Attribute」というウィンドウが表示されるので、追加したい Attribute の名前と型を設定して「Save」を押します。

Attributes の名前は以下のルールに沿う必要があります。
(参考「New Studio Beta: Attributes!」)

  • 英数字とアンダーバーのみを使用すること(スペースや特殊記号は使用不可)
  • 100文字以内であること
  • 「RBX」という文字列から始めないこと

「Properties > Attributes」を確認するとその名前の Attribute が追加されているのがわかります。
右半分のスペースをクリックして値を変更できます。

また、右にある歯車マークからその Attribute を削除したり、名前を変更したりできます。

スクリプトからの扱い方

Attributes も ValueObject と同様にスクリプトから扱うこともできます。

既存の Attribute の値を変更するときは Instance:SetAttribute() を使用します。
第一引数にその Attribute の名前を、第二引数にその Attribute に設定したい値を渡してあげます。

local sampleInstance = workspace.SampleInstance
sampleInstance:SetAttribute("SampleAttribute", "Hello World")

Instance:SetAttribute() は、第一引数で指定した名前の Attribute がその Instance に存在しない場合はその名前の Attribute を新たに追加して第二引数の値を設定します。
また、Instance:SetAttribute() の第二引数に nil を渡すと、その名前の Attribute を削除することができます。

Attribute を取得したいときは Instance:GetAttribute() を使用します。
引数にはその Attribute の名前を渡してあげます。
(引数に渡した名前の Attribute がその Instance に設定されていない場合は nil が返ってきます。)

local sampleInstance = workspace.SampleInstance
local sampleAttribute = sampleInstance:GetAttribute("SampleAttribute")

また、Instance:GetAttributes() という関数を使用するとその Instance に設定されている全ての Attribute の名前と値を連想配列で取得することができます。

local sampleInstance = workspace.SampleInstance

for key, value in sampleInstance:GetAttributes() do
    local attributeName = key
    local attribute = value
end

ValueObject と Attributes の違いと使い分け方

ここからは ValueObject と Attributes の違いと使い分け方について説明します。

対応している型の違い

まずは対応している型の違いについてです。
この記事の執筆時点(2026年4月時点)での対応している型の違いは以下の表の通りです。

ValueObjectAttributes
string
boolean
int
number
UDim
UDim2
BrickColor
Color3
Vector2
Vector3
CFrame
NumberSequence
ColorSequence
NumberRange
Rect
Font
Object(Instance)
Ray

この表を見ると ValueObject よりも Attributes の方がより多くの型に対応しているのがわかりますが、ValueObject のみ Object(Instance)に対応しているという非常に大きな違いがあります。
この型を扱える ValueObject は ObjectValue というクラスであり、ObjectValue の「Properties > Data > Value」をクリックするとマウスカーソルの右上に謎のマークが表示されます。

この状態で Explorer にあるいずれかの Instance を選択すると、その Instance を ObjectValue.Value に設定することができます。

「SampleInstance」という名前の Instance を Explorer で選択

このように ObjectValue は Unity C# でいうところの SerializeField、Unreal Engine のブループリントでいうところの Instance Editable、Unreal C++ でいうところの EditAnywhere に近い存在です。
スクリプトから他の Instance を取得するときは「workspace.SampleFolder.SampleInstance」のようにその Instance のパスを記述するか、Instance:FindFirstChild() や Instance:WaitForChild() などの関数を使用するか、CollectionService を使用してタグ経由で取得するなどの方法がありますが、ObjectValue を使用すると対象の Instance がどこに移動してもコードを一切修正する必要がありません。
また、コードを修正することなく対象の Instance を簡単に変更することもできます。

ValueObject と Attributes の使い分け方について、対応している型の違いから考えると基本的には Attributes を使用して、ValueObject にしかない型(特に ObjectValue)を使いたい場合は ValueObject を使用するという使い分けが良いかと思います。

コード量の違い

ValueObject と Attributes ではスクリプトから扱う際のコード量にも違いがあります。

例えば「string 型の ValueObject または Attributes に『Hello World』という値を設定するが、もしそれがまだ無い場合は新たに作って追加する」という処理の場合は ValueObject と Attributes でそれぞれ以下のコードのようになるかと思います。

local sampleInstance = workspace.SampleInstance
local stringValue = sampleInstance:FindFirstChild("StringValue")

if not stringValue then
    stringValue = Instance.new("StringValue")
    stringValue.Name = "StringValue"
    stringValue.Parent = sampleInstance
end

stringValue.Value = "Hello World"
local sampleInstance = workspace.SampleInstance
sampleInstance:SetAttribute("StringAttribute", "Hello World")

ValueObject の場合は Instance:FindFirstChild() で探し、結果が nil だった場合(その名前の Instance が無かった場合)は if 文で条件分岐して Instance.new() で ValueObject をインスタンス化し、名前と親を設定しています。
その後に「Hello World」という値を設定しています。

Attributes の場合は「その名前の Attributes が無かった場合は新たに作成する」という処理が Instance:SetAttribute() に含まれているため、sampleInstance の取得処理を除けばたったの1行で済んでいます。

このように ValueObject は「1つのインスタンスにつき1つの値しか持てない」という特性上、Attributes と比較してコード量が多くなりがちであり、ロジックも少し複雑になりがちです。

ValueObject が必須な状況

ここまでの説明を踏まえると「int や Object(Instance)などの ValueObject にしかない型を扱いたいときだけ Attributes ではなく、ValueObject を使用した方がいい」という結論に至りますが、それら以外の型において ValueObject が必須な状況もあります。
それは Roblox 標準のリーダーボード機能を使用するときです。
この機能を使用することで独自のUIを作成することなく、下の画像のようなリーダーボードを簡単に実装することができます。

Roblox 標準のリーダーボード機能のUI

このリーダーボード機能の使用方法については「In-experience leaderboards」という公式ドキュメントで解説されています。
この公式ドキュメントを読むとわかるように Roblox 標準のリーダーボード機能では Folder をインスタンス化して「leaderstats」という名前に変更し、各 Player に親子付けした後、その中に StringValue や IntValue、NumberValue などの値型の ValueObject をインスタンス化して親子付けする必要があります。

「Players.{プレイヤー名}.leaderstats」内に置かれた ValueObject

このように(自分が知る限りでは)リーダーボード機能でのみ ValueObject が必須です。
(他にも ValueObject が必須な状況がありましたら、@tsubasamusu まで教えていただけると泣いて喜びます。)

処理負荷の違い

最後は処理負荷の違いです。
これが ValueObject と Attributes の最も大きな違いです。
ValueObject は1つの値につき1つの Instance を作成するため、Attributes に比べて処理負荷が大きくなってしまいます。

Attributes がベータ機能としてリリースされた時の公式アナウンス「New Studio Beta: Attributes!」には以下のように記述されています。

・Attributes take up less memory on your device
・Attributes are ~18x faster to create dynamically
・Attributes are ~240x faster to delete

New Studio Beta: Attributes!

実際に自分で測定したわけではありませんが、この公式ドキュメントの内容によると動的に Attributes を作成するのは ValueObject に比べておよそ18倍速く、Attributes の削除においてはおよそ240倍速いそうです。

最後に

まとめ

int や Object(Instance)などの ValueObject にしかない型を扱いたいときや、Roblox 標準のリーダーボード機能を使用したいときは ValueObject を、それら以外の場合においては基本的に Attributes を使用すると良いかと思います。

参考

フォーラム

公式APIドキュメント

公式Learn

お問い合わせ

    タイトルとURLをコピーしました