対応する
API
を探すのが若干面倒くさい
DOTS系テク
ノロ
ジー
の殆どはstruct(構造体)を利用しており、構造体自体にメソッドを追加していることは殆どありません。大抵の場合、Utility系の
API
が幅を利かせており、利用する場合には対応する構造体に対応するUtility、
API
に対応するデータを渡す必要があります。
例えば「オブジェクトを回転させる」という場合、少なくとも「Unity.Mathematics.quaternion.RotateYで回転行列を作る」「Unity.Mathematics.math.mulはquaternionにも対応している」という情報を知らなければ作るのは割と面倒くさいです。回転するジョブは下のような感じ。
struct RotationJob : IJobForEach<Rotation, RotationSpeed>
public void Execute(ref Rotation c0, ref RotationSpeed c1)
c0.Value = math.mul(c0.Value, quaternion.RotateY(c1.Value));
しかもECS初期コードではusing static Unity.Mathematics.math;が設定されてるせいでquaternionクラスが即使えないっていう。
Rotatoinの中身を確認しても、何をどうすればよいのか良くわからん
拡張メソッドで拡張する
これを拡張メソッドを使用して簡単に記述できるようにしてみます。構造体の拡張メソッドも基本的には通常の拡張メソッドと同じで、 static クラス内に定義したstaticメソッドであること と メソッド引数の最初にthis を使用 の二つです。
struct RotationJob : IJobForEach<Rotation, RotationSpeed>
public void Execute(ref Rotation c0, ref RotationSpeed c1)
c0 = c0.RotateY(c1.Value);
public static class EXClass
<summary></summary>
<param name="angle"></param>
<returns></returns>
public static Rotation RotateY(this Rotation q, float angle)
q.Value = math.mul(q.Value, quaternion.RotateY(angle));
return q;
入力補完が効くので、一覧からできることを指定するだけで使えます。
入力補完で何ができるのかを表示してくれる
構造体と拡張メソッドの参照渡し
構造体なので基本的にメソッドが使用するデータはコピーしたデータです。なので、クラスの拡張メソッドと異なり値を返していました。例えば下のコードは正常に動作しません。これが単純にstruct内部にメソッドを定義していたら話は別なのですが、拡張メソッドは外部のstaticメソッド扱いなので、構造体自身に反映されません。
struct RotationJob : IJobForEach<Rotation, RotationSpeed>
public void Execute(ref Rotation c0, ref RotationSpeed c1)
c0.RotateY(c1.Value);
public static class MathEX
public static void RotateY(this Rotation q, float angle)
q.Value = math.mul(q.Value, quaternion.RotateY(angle));
とはいえ、構造体が巨大だったり、メソッドで内部データを書き換えたい場合もあります。そんな時はinやrefを使用できます。試したら出来ました。これが理に適っているかは微妙な所ですが、まぁ出来たので問題なく。ref を使えば、戻り値の構造ではなく直接構造体を操作出来ます。これを許容出来るかとかは兎も角として、出来ます。
struct RotationJob : IJobForEach<Rotation, RotationSpeed>
public void Execute(ref Rotation c0, ref RotationSpeed c1)
c0.RotateY(c1.Value);
public static class MathEX
public static void RotateY(this ref Rotation q, float angle)
q.Value = math.mul(q.Value, quaternion.RotateY(angle));
単純にデータをコピーしたくない場合はin が使えます。例えば下のコードの場合、LocalToWorldに対しての距離を求める拡張メソッドです。
struct DistanceJob : IJobForEach<LocalToWorld>
public float3 playerPos;
public void Execute(ref LocalToWorld c0)
if (c0.Distance(playerPos) < 1) { }
public static class MathEX
<summary></summary>
<param name="position"></param>
<returns></returns>
public static float Distance(this in LocalToWorld world, in float3 position)
return math.distance(world.Position, position);
なおNativeCollectionを使用している場合、内部でポインタを使用して別のデータを参照しているのでコピーされても問題ないです。実際、NativeSort.csを見てみると、特に参照渡しをせずに普通に受け取っています(その直後に内部のポインタを渡してたり)
NativeSort.csでNativeArrayの拡張メソッドを定義