Unityレイヤーマスクでビットシフトを使用する必要があるのはなぜですか?


10

ようやく、地上衝突コードのレイヤーマスクが機能しない理由がわかりました。NameToLayer()必要なレイヤーを取得するために使用していましたが、レイヤーマスクはビットシフトを使用して実際にレイヤーマスク値を設定します。これは非常に珍しく、コードビハインドで処理されない理由はありません。なぜ次のようなコードを使用する必要があるのですか。

mask = 1 << LayerMask.NameToLayer("Default");

このような場合:

mask = LayerMask.NameToLayer("Default");

より直感的に理解でき、Unity APIの他の部分と同様に機能しますか?


2
文字列バージョンを使用すると、処理能力が高くなります。文字列は内部的には参照型の配列であり、ガベージコレクターに追加されます。
Krythic

回答:


3

これは非常に高性能です。それだけです。明らかな例は10倍遅いため、文字列を比較します。物理演算は非常に最適化する必要があるため、何が起こっているかを知っている人がこのように書いたのは良いことです。

したがって、明らかなフォローアップの質問は、変換とビットシフトを処理するヘルパーメソッドにラップされていないのはなぜですか。私は実際に誰もそれに到達しなかったと思います-私は自分の気の利いたヘルパーユーティリティをロールアップしました、そしてそれは一般的な慣行です。


1
Unityチームによる正しい設計の選択は、文字列ではなく整数をインデクサーとして使用することでした。文字列配列の割り当ては言うまでもなく、ガベージコレクターが現在の実装でどれほど狂っているのかを考えると、私はうんざりします。
Krythic 2016年

1
絶対に-どの配列も整数で参照するのが最適です。整数は、単純な列挙型によって人間が読めるようになる可能性があります。
ヨルダンゲオルギエフ2016年

迅速でダーティな実装は機能しますが、より大きなプロジェクトでは[Type Safe]を使用します(assetstore.unity3d.com/en/#!/content/35903)。
ヨルダンゲオルギエフ

20

ビットシフトを使用すると、1回の物理演算で複数のレイヤーを考慮することができます。

 Physics.Raycast(ray, out hitInfo, Mathf.Infinity, layerMask )

ビットシフトがなければ、1つのレイヤーで1つだけレイキャストすることができます。ビットシフトを使用すると、複数の特定のレイヤーでレイキャストできます。

layerMask = (1 << LayerMask.NameToLayer("MyLayer1")) | (1 << LayerMask.NameToLayer("MyLayer2")) ;

特定のレイヤーを除くすべてのレイヤーでレイキャストすることもできます。

layerMask = (1 << LayerMask.NameToLayer("MyLayer1")) | (1 << LayerMask.NameToLayer("MyLayer2")) ;
layerMask = ~layerMask;

Unityの「レイヤーマネージャー」を見ると、レイヤーは単純な1次元配列のインデックスと見なすことができます


編集:私は以前にそれを見たことはありませんが、LayerMaskクラスには、レイヤー名を指定して「計算された」レイヤーマスクを取得するユーティリティ関数があります:

Debug.Log( LayerMask.GetMask("UserLayerA", "UserLayerB") ) ;

仮定UserLayerAし、UserLayerB第10及び第十層です。これらのユーザーレイヤー値は10と11になります。レイヤーマスク値を取得するには、名前をGetMaskに渡すことができます。引数は、名前のリストまたは名前を格納する文字列の配列のいずれかです。この場合、戻り値は2 ^ 10 + 2 ^ 11 = 3072になります。

ドキュメントへのリンク:https : //docs.unity3d.com/ScriptReference/LayerMask.GetMask.html


2
マスクの和集合を作成するとき|は、整数加算の代わりにビット単位ORを使用する必要があります+。整数加算は予期しない動作を引き起こす可能性があります。
2016年

1
しかし、その後、再び、彼らは内部などの方法提供することを行っている可能性LayerMask.NamesToLayers(params string[] layerNames)
QBrute

良い点@wondra!;)-はい、彼らはこのQBruteを実行できたかもしれませんが、レイヤーマスクを動的に変更する場合(レイヤーの追加、削除、反転など)、ビットシフト操作を使用する方がはるかに柔軟です
Hellium

ビット処理も非常に高速です。これらは、大きなバイナリデータを合成するための優れた方法です。
Gusdor 2016年

ただし、メソッドがレイヤ番号ではなくレイヤマスクを返すのではないという問題には、実際には答えません。
2016年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.