0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

U#でサイズの大きい数値配列を扱う

Posted at

この記事は、UniMagic Advent Calendar 2024 9日目の記事です。
まあ厳密には関係者じゃない気がするけど、細かいことは気にしたら負け。


UdonSharpで数~数十MBくらいのサイズの数値配列を扱いたい時のメモ。

サイズが小さい配列であれば、普通に定義すればよい。
しかし、配列のサイズが大きくなってくると、次第にコンパイルに時間がかかり、メモリも必要になってくる。

(こんな感じに100MB越えのcsファイルを作ると、コンパイル時にメモリ不足になる。)

VRCJsonを使う手もあるが、文字列として扱うのでサイズが大きくなりがちである。
また、数値が内部的にDoubleとして扱われるので、そこまでの精度が必要ない時はリソースの無駄になってしまう。

System.Buffer.BlockCopy

ここで使えるのが、System.Buffer.BlockCopyである。
これを使うと、Byteの配列から他の数値型の配列に値をコピーすることができる。

コピー元となるByteの配列だが、ワールドデータに含めるのであればTextAssetを使うのがよいと思う。
拡張子を.bytesにして保存すれば、Unityがバイナリデータであると認識してくれる。

using System;
using UnityEngine;
using UdonSharp;

public class ExampleClass : UdonSharpBehaviour
{
    [SerializeField] public TextAsset bigArrayData;

    private uint[] _uintArray;

    void Start()
    {
        // uintは4byteなので、4で割っている
        // 型に合わせて割る数を変える
        _uintArray = new uint[bigArrayData.bytes.Length / 4];
        Buffer.BlockCopy(bigArrayData.bytes, 0, _uintArray, 0, bigArrayData.bytes.Length);
    }
}

また、ワールドデータに含めず、インターネット経由にしたい場合は、VRCStringDownloaderのResultBytesを使えばいいと思われる。(自分では未確認)


なお、元となるByte配列のデータは、pythonで用意した。
structを用いればいい感じのバイナリデータを作成できる。

import struct

data = [1, 2, 3, 4, 5]

with open("bigArrayData.bytes", "wb") as f:
    # "<": リトルエンディアン
    # "I": uint(ここの文字は数値の型によって変える)
    f.write(struct.pack("<"+"I"*len(data), *data))

余談

書き終わってから気づいたが、VRC公式ドキュメントにもBlockCopyの記載があった。
(コードだけの分かりにくいものだったので、この記事を書いた意味はあったかな…?)

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?