VRChat 非公式日本語ドキュメント

データトークン

データトークンはデータを保持するためのものです。各トークンは必ず1つの変数のみを格納します。データトークンは、Data DictionariesData Lists で使用されます。

データトークンには、以下のトークンタイプを含めることができます。

プロパティ

Property Result
TokenType この DataToken が保持している変数の現在の TokenType を返します。
IsNumber DataToken が数値型を含んでいる場合に true を返します。それ以外の場合は false を返します。
IsNull DataToken 内に保持されている値がどのような形式であれ null である場合に true を返します。数値と bool は決して null にはなりません。TokenType.Null は常に null と見なされます。文字列は空文字ではなく null かどうかをチェックします。参照型については、内部で Utilities.IsValid を使用して、退出したプレイヤーや破棄されたオブジェクトを判定します。
Boolean DataTokenbool を保持している場合に bool を返します。それ以外の場合は例外をスローします。
Number DataToken が数値型を保持している場合に double を返します。それ以外の場合は例外をスローします。
SByte DataTokensbyte を保持している場合に 8ビット符号付き sbyte を返します。それ以外の場合は例外をスローします。
Byte DataTokenbyte を保持している場合に 8ビット符号なし byte を返します。それ以外の場合は例外をスローします。
Short DataTokenshortsbyte、または byte を保持している場合に 16ビット符号付き short を返します。それ以外の場合は例外をスローします。
UShort DataTokenushort または byte を保持している場合に 16ビット符号なし ushort を返します。それ以外の場合は例外をスローします。
Int DataTokenintsbytebyteshort、または ushort を保持している場合に 32ビット符号付き int を返します。それ以外の場合は例外をスローします。
UInt DataTokenuintbyte、または ushort を保持している場合に 32ビット符号なし uint を返します。それ以外の場合は例外をスローします。
Long DataTokenlongsbytebyteshortushort、または uint を保持している場合に 64ビット符号付き long を返します。それ以外の場合は例外をスローします。
ULong DataTokenulongbyteushort、または uint を保持している場合に 64ビット符号なし ulong を返します。それ以外の場合は例外をスローします。
Float DataTokenfloatsbytebyteshortushortintuintlong、または ulong を保持している場合に 32ビット float を返します。それ以外の場合は例外をスローします。
Double DataTokendouble またはその他の数値型を保持している場合に 64ビット double を返します。それ以外の場合は例外をスローします。
String DataTokenstring を保持している場合に string を返します。それ以外の場合は例外をスローします。
DataDictionary DataTokenDataDictionary を保持している場合に DataDictionary を返します。それ以外の場合は例外をスローします。
DataList DataTokenDataList を保持している場合に DataList を返します。それ以外の場合は例外をスローします。
Reference DataToken がオブジェクト参照を保持している場合にオブジェクト参照を返します。それ以外の場合は例外をスローします。
Error このトークンに関連付けられているエラーを返します。それ以外の場合は DataError.None を返します。他のプロパティとは異なり、このプロパティにアクセスしても例外がスローされることはありません。エラーではないトークンから Error にアクセスしようとした場合、単に DataError.None が返されます。

関数

関数 結果
Bitcast DataToken 内の既存のデータを再利用しつつ型を変更します。C++ の reinterpret_cast や C# の BitConverter と同様です。変換先の方が型サイズが小さい場合は値が切り捨てられ、変換先の方が大きい場合はゼロ拡張されます。プリミティブ型でのみ動作し、コピーを返します。
ToString トークンの内容を文字列に変換します。String プロパティへのアクセスとは異なり、この関数は基となる値の ToString を使用するため、常に成功します。
GetHashCode トークンの内容のハッシュコードを返します。これは主に辞書のキーといった内部処理で使用されます。
CompareTo このトークンを別のトークンと比較します。比較対象の方が大きい場合は -1、等しい場合は 0、小さい場合は 1 を返します。リストや辞書といったコンテナは要素数によって比較されます。型が異なるトークン同士や数値以外を比較する場合、TokenType enum の順序が使用されます。

Data Token の作成

UdonSharp

UdonSharp では、DataToken を「暗黙的」に作成できます。これは、関数が DataToken を要求する際に new DataToken(value) を呼び出す必要がないことを意味します。代わりに値を直接渡すだけで、自動的に DataToken が作成されます。

// You could do this
DataToken _explicitFloat = new DataToken(5.3f);
DataToken _explicitInt = new DataToken(5);
DataToken _explicitString = new DataToken("value");
DataToken _explicitBool = new DataToken(true);

// But this is easier and simpler
DataToken _float = 5.3f;
DataToken _Int = 5;
DataToken _String = "value";
DataToken _Bool = true;
warning

UdonSharp で DataToken を暗黙的に作成する際に nameof() を使用しないでください。エラーが発生する可能性があります。

Udon Graph

Udon Graph では、 DataToken Implicit ノードまたは DataToken Constructor ノードを使用して、値を含む DataToken を作成する必要があります。
data-tokens-7GAcVrY.png

DataToken から値を取得する

DataToken から値を取得する前に、そのトークンがどのような型を含んでいるかを確認する必要があります。互換性のない型を取得しようとすると、UdonBehaviour が停止してしまうためです。含まれている型が目的のデータ型と互換性があることを確認するには、いくつかの方法があります。

// If we know that it's a string, we can safely pull the string out of the token
if (unknownToken.TokenType == TokenType.String)
{
    Debug.Log(unknownToken.String);
}

// We can use IsNumber to see if it's some type of number, even if we don't know which.
if (unknownToken.IsNumber)
{
    Debug.Log(unknownToken.Number);
}

// If we're pulling a value from a container, we can use the version that does its own type check
if (dictionary.TryGetValue("key", TokenType.String, out DataToken value))
{
    Debug.Log(value.String);
}

data-tokens-SqQqE5w.png

適切な型であることを確認したら、DataToken.FloatDataToken.Boolean といった値プロパティにアクセスすることで、DataToken から値を取得できます。各型には、その特定の型を取り出すために使用できる独自のプロパティが用意されています。

取り扱うデータを完全に制御できている場合は、すべての TokenType チェックをスキップして、トークンから直接値を取得しても構いません。これによりコード量を減らすことができますが、外部ソースからデータが来る場合や、他の型である可能性がある場合は、この方法をとらないようにしてください。

dictionary["A"] = 5;
dictionary["B"] = 10;

// This makes the assumption that A and B will always contain integers.
// This is a safe assumption to make since we set them just above in a controlled environment.
// If the data is coming from an external source, we shouldn't make these assumptions!
int sum = dictionary["A"].Int + dictionary["B"].Int;

エラー

Data List または Data Dictionary に対する操作が失敗し、DataToken が返された場合、エラートークンが生成されます。エラートークンには、エラーの種類を分類する列挙型(enum)と、エラーの詳細を説明する文字列が含まれます。詳細な説明が不要な場合など、すべてのエラーに文字列が含まれるわけではありません。

エラートークンを取得した場合、DataToken.Error を使用してエラーの列挙型を、DataToken.String を使用してメッセージを取得できます。また、DataToken.ToString() を使用すれば、列挙型と文字列を自動的に結合して完全なメッセージを作成できるため、単純に Debug.Log(token) を呼び出す際に便利です。

エラートークンには、主に以下の種類があります。

意味
KeyDoesNotExist Data Dictionary 内のキーにアクセスしようとしましたが、そのキーが存在しません。
IndexOutOfRange Data Array 内のインデックスにアクセスしようとしましたが、そのインデックスが 0 未満、あるいは配列の要素数以上でした。
TypeMismatch 値にアクセスしようとしましたが、期待した型ではありませんでした。注:これは型を指定するバージョンの TryGetValue を使用している場合にのみ発生します。
TypeUnsupported データコンテナに、使用しようとしたシリアライズ形式でサポートされていない型が含まれていました。これは、Data Container に参照トークンを入れ、それを JSON にシリアライズしようとした場合などに発生します。
ValueUnsupported データコンテナに、使用しようとしたシリアライズ形式でサポートされていない値が含まれていました。これは、Data Container に NaN や Infinity の浮動小数点数を入れた状態で、JSON にシリアライズしようとした場合などに発生します。
UnableToParse シリアライズされた形式を解析できませんでした。これは、元の JSON が無効な場合に発生します。
if (dictionary.TryGetValue("key", TokenType.Float out DataToken value)) {
    // If TryGetValue succeeds, we can do things with the token
    Debug.Log($"Successfully retrieved value {token.Float}");
} else {
    // If TryGetValue fails, the token will instead be an error
    Debug.Log($"Failed to retrieve value with error {token.Error}");
}

data-tokens-zcqKePv.png

FAQ

String と ToString の違いは何ですか?

DataToken.StringDataToken.ToString() は似ていますが、全く同じものではありません。DataToken.String は DataToken 内にある文字列の値に直接アクセスするのに対し、DataToken.ToString() は存在するあらゆるデータを文字列に変換するためです。

結果として、ToString は DataToken の中身に関わらず常に有効であり、UdonBehaviour が停止することはありません。中身が bool であれば true または false を返し、数値であれば ToString("G", CultureInfo.InvariantCulture) を用いてその数値を表す文字列を作成します。

その一方で、DataToken.String へのアクセスは、DataToken に文字列が含まれている場合にのみ有効です。DataToken に float が含まれている状態で DataToken.String にアクセスしようとすると、例外が発生し、UdonBehaviour は停止します。

DataErrors は、Error enum と文字列の両方を含んでいるという点で特殊です。DataErrors に対しては ToString() を使用することをお勧めします。これは、ToString() を使うと enum と文字列が結合され、エラーの内容と理由の両方を含む単一のメッセージとして取得できるためです。

トークンを介さず、直接値を取得する TryGetValue はないのですか?

トークンを介さずに直接値を取得できる TryGetValue メソッドがあれば便利でしょう。コンテナから毎回トークンを取得し、その中からさらに値を取り出すという手間を考えると、この質問はもっともです。このプロセスを簡略化するためにいくつかの選択肢が検討されており、その解決策の一つとして、TryGetValue に型チェック機能を組み込むという実装が行われました。

また別の検討案として、T 引数を使用してシステム型を指定するジェネリック版の TryGetValue を作成することも考えられました。UdonSharp は(少なくとも静的メソッド内であれば)このアプローチをサポートしていますが、Udon 自体は対応していません。さらに、この方法には利点がある一方で、エラー発生時に DataToken を介して DataError を返すことができなくなり、代わりにデフォルト値が返されてしまうという問題があります。最終的に、ユーザーからエラーが隠蔽され、問題の特定が困難になるという理由から、この実装は採用しませんでした。幸いなことに、UdonSharp であれば Generics、Statics、および拡張メソッドが利用できるため、ユーザー自身でジェネリックな値取得のためのソリューションを作成することが可能です。

最終更新: