UnityのBurstコンパイラを使う条件で、NativeArrayの中身が「Blittableな」値型でなければならないため配列など参照型のものは使えないとのこと。
その関係で固定長バッファを配列代わりに使って(そのとき作っていたのがオクツリーなので要素数は8個固定でよい)構造体を作ったのですが、その過程で、値を書き換えても、VisualStudioのステップ実行中にデバッグウィンドウから見える値だけ変な値が返ってくることに気づいて、なんだこれ?となったので残しておきます。
テスト用に要素数が三個の構造体を定義しています。
固定長バッファはそのままではステップ実行中の先頭の値しか見れないので、構造体のToString()をオーバーライドするという形で3要素を可視化しました。
public unsafe struct Test
{
fixed uint values[3];
public Test(uint value)
{
fixed (uint* p = values)
{
p[0] = value;
p[1] = value * 2;
p[2] = value * 4;
}
}
public override string ToString()
{
string s = "";
fixed (uint* p = values)
{
s = "[0]" + p[0];
s += " [1]" + p[1];
s += " [2]" + p[2];
}
return s;
}
}
protected void Start()
{
Test t = new Test(1);
string s = t.ToString();
}
VisualStudioのデバッグのステップ実行中に値を覗くとToString()の結果が返ってくるのですが、このようにステップ実行で呼び出し側のスコープを抜ける直前にtをカーソルでポイントしたときに見える値と、それをstring変数に改めて書き出した後でポイントした値が違っています。
[0] 1
[1] 358
[2] 3046930464
[0]だけはちゃんと書き換わっていますが、[1]と[2]は変な値が。
初期化する前なら使い古しの変な値が入ってても不思議ではないのですが、コンストラクタ内で書き換わった後のはずなので奇妙です。
[0] 1
[1] 2
[2] 4
こっちは期待通りです。
固定長バッファはGCとかの絡みでメモリ上で位置が固定されてないため、fixedを使って一時的に固定しなければならないとのことですが、もしかしてその絡みかもしれません。(例えばToString()は、ステップ実行中に変数がポイントされて呼ばれるときだけはfixedされないとか、またはいろいろ通常とは条件が違うとか?)
ポインタやVisualStudioの挙動などに詳しい人にとっては簡単な話かもないのですが、この人の知識ではよくわからず「値が書き換わってない!?」「あれ、でも変数に書き出した後の文字列はちゃんと書き換わってる?」と混乱したので残しておきます。
要はデバッグウィンドウで直接覗いた時の値がおかしいだけで、一応ちゃんと書き換わってるっぽいです。