#はじめに
こちらは「裏 Unreal Engine 4 (UE4) Advent Calendar 2016」12日目の記事になります。
先日は_kenji_さんの「UE4を触り始めてからの体験談、そしてこんな開発環境でもゲームは作れる!」でした。
UE4.12からBPでBitmaskが使えるようになりました。
UE4でBitmaskに触れてる人は少なかったので書いてみることに(UE4独自の仕組みってわけではないのでわざわざ書く人が少ないんだと思います)
用語の解説的なこともしてますがふんわりしてるので、使い方だけ見たい人はBitmaskを使う準備から読むと良いと思います。
使用バージョン:UE4.14.0
#Bitmaskとは
説明してるサイトとかで言ってることがまちまちなのですが、
・AND演算で特定ビットを抽出するビットパターン
・ビット演算を用いて1つの変数で複数のフラグを管理する手法
他にも見かけたことがある気がする(結局どの説明が正解なのか)
#メリット・デメリット
-
メリット
- データ量が少なくて済む(boolなどは言語によって違いがありますが、1bit確保してるのではなくて1byte(8bit)とか4byte(32bit)とか数byte確保することが殆どのため、余分なデータが存在する
- 処理速度が早い(よりPCが内部で扱う状態に近いため
-
デメリット
- 可読性が落ちる(あまり見かけたことがないので、作った人以外が見ると混乱するかもしれないです。プロのゲームプログラマーの世界だと違うのかもしれません
#2進数
今回扱うのは普段目にするような10進数ではなくて、2進数での話になってくるので、2進数の説明を軽くしておきます。
そんなに難しいことはなくて、どのくらい加算したら桁上げが発生するかの違いしかありません。各桁が持つ上限が違うといえばいいでしょうか。
以下は10進数と2進数の対応表です
10進数 | 2進数 |
---|---|
0 | 0000 |
1 | 0001 |
2 | 0010 |
3 | 0011 |
4 | 0100 |
5 | 0101 |
6 | 0110 |
7 | 0111 |
8 | 1000 |
9 | 1001 |
10 | 1010 |
10進数では10加算されるごとに桁上げが発生します。9に1を足せば10になりますよね。
2進数では2加算されるごとに桁上げが発生します。0001(10進数でいう1)に0001を足せば、0002ではなく桁上げして0010になります
#ビット
ビットっていうのはPC上で取り扱う最小の単位です。桁と思っていいです。
1bitは0と1で表現されます。つまり2進数です。
4bitなら4桁あります。0001とか0100とか言う風に書きます。
Bitmaskでは各桁の0、1をフラグとして利用します。
#ビット演算(論理演算)
Bitmaskを使うにはビット演算が出来ないといけないので振り返っておきます。
ビット演算にはAND、OR、XOR、NOTというものがあります。
以下の表では1桁の計算ですが、実際には複数桁(32桁など)をまとめてやったりします。ですが、1桁ずつそれぞれ計算するだけですので難しく考える必要はありません。
- AND
UE4ではBitwise ANDノード
両方1でないと1を返してくれません
A | B | A AND B |
---|---|---|
0 | 0 | 0 |
0 | 1 | 0 |
1 | 0 | 0 |
1 | 1 | 1 |
例)
0101 AND 1100 = 0100
- OR
UE4ではBitwise ORノード
どちらかが1ならば1を返します
A | B | A OR B |
---|---|---|
0 | 0 | 0 |
0 | 1 | 1 |
1 | 0 | 1 |
1 | 1 | 1 |
例)
0101 AND 1100 = 1101
- XOR
UE4ではBitwise XORノード
どちらかが1の時だけ1を返してくれます
A | B | A XOR B |
---|---|---|
0 | 0 | 0 |
0 | 1 | 1 |
1 | 0 | 1 |
1 | 1 | 0 |
例)
0101 AND 1100 = 1001
- NOT
UE4ではBitwise NOTノード
反対の値を返してくれます
A | NOT A |
---|---|
0 | 1 |
1 | 0 |
例)
NOT 0101 = 1010
#Bitmaskを使う準備
1.Integer型の変数を一つ用意してプロパティ(詳細)のBitmaskにチェックを入れる
この状態になるとInteger型を2進数で取り扱う事ができます。といってもそのまま2進数というわけではなくて、フラグとして扱うこと前提になっていますので、一桁一桁に名前がついています。
UE4のBPでのInteger型は4byte(32bit)確保しますので以下のようにデフォルトではなっています
2.Enum型(列挙型)をBitmaskFlags(上の画像のFlag1とかの名前の代わり)として宣言する
列挙型を宣言してBitmaskFlagsにチェックをいれます
3.先程作ったInteger型変数のプロパティ(詳細)のBitmaskEnumで選べるようになっているので選択
そうすると以下のように自分がつけた名前に代わると思います。
*上の画像だと4つしかフラグがありませんが、4bitしか確保されないってわけでは無いと思います。しっかり32bit確保すると思うのでご注意を!
#フラグをONにする
- エディター上
ONにしたいフラグにチェックする
- Blueprint
下の図はFlagAをONにする場合です。複数同時にONにすることも可能です。
#フラグをOFFにする
- エディター上
チェックを外すだけ
- Blueprint
下の図はFlagAをOFFにする場合です。複数同時にOFFにすることも可能です。
#フラグがONか判定する
下の図はFlagAがONか判定する場合です。複数同時にONかどうか確認することも可能です。
#フラグをトグルさせる
下の図はFlagAをトグルさせる場合です。複数同時にトグルさせることも可能です
#おわりに
本当はInteger型で使える演算ノードを一つずつ解説する記事でも書こうかと思ったのですが、Bitmaskだけの記事になってしまいました。
実際に使う場面がくるかは分かりませんが、覚えておくといいかもしれません。
ここまで読んで頂きありがとうございました。
明日はyoshikataさんより「androidでVRを動かせる所まで解説(すごい初歩)」です。
#参考URL
ビット演算によるフラグ管理
Bitmask ブループリント変数
bool型の落とし穴
ビット(bit)とバイト(Byte) 情報量の単位と2進数
Why should I use 1bit bitfields instead of bools?
ビットフィールド
Questions about bool variable
Why does UE4 use uint32 to represent a bool?
bool型